Template
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2efdefa6f6 | ||
|
|
1865389a23 | ||
|
|
01dc6f85d7 | ||
|
|
a48e6b8ba6 | ||
|
|
5e0c68d1c9 | ||
|
|
1f35ffd288 | ||
|
|
58c0cf7460 | ||
|
|
3a4435e7a6 | ||
|
|
38db72d94f | ||
|
|
bfa311b70f | ||
|
|
03810e9cad |
@@ -1,6 +1,5 @@
|
|||||||
# 忽略构建输出目录
|
# 忽略构建输出目录
|
||||||
Build/
|
Build/
|
||||||
.vscode/
|
|
||||||
|
|
||||||
# 忽略 Toolchain 目录下所有内容,但保留目录本身
|
# 忽略 Toolchain 目录下所有内容,但保留目录本身
|
||||||
Toolchain/*
|
Toolchain/*
|
||||||
|
|||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
erase
|
||||||
|
exit
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"marus25.cortex-debug",
|
||||||
|
"ms-vscode.cmake-tools",
|
||||||
|
"twxs.cmake",
|
||||||
|
"ms-vscode.cpptools"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
loadfile Application.hex
|
||||||
|
r
|
||||||
|
go
|
||||||
|
exit
|
||||||
Vendored
+58
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"executable": "${workspaceFolder}/Build/Debug/Application/Application.elf",
|
||||||
|
"name": "Debug with OpenOCD",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"runToEntryPoint": "main",
|
||||||
|
"showDevDebugOutput": "none",
|
||||||
|
"gdbPath": "${env:GD32_GCC_BIN}/arm-none-eabi-gdb.exe",
|
||||||
|
"servertype": "openocd",
|
||||||
|
"serverpath": "${env:GD32_OPENOCD_BIN}/openocd.exe",
|
||||||
|
"svdFile": "${workspaceFolder}/GD32E230.svd",
|
||||||
|
"configFiles": [
|
||||||
|
"${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}"
|
||||||
|
],
|
||||||
|
"serverArgs": [
|
||||||
|
"-s", "${env:GD32_OPENOCD_SCRIPTS}"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
|
||||||
|
},
|
||||||
|
"searchDir": [
|
||||||
|
"${workspaceFolder}"
|
||||||
|
],
|
||||||
|
"preLaunchTask": "Build",
|
||||||
|
"preRestartCommands": [
|
||||||
|
"load",
|
||||||
|
"continue"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"executable": "${workspaceFolder}/Build/Debug/Application/Application.elf",
|
||||||
|
"name": "Debug with J-Link",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"runToEntryPoint": "main",
|
||||||
|
"showDevDebugOutput": "none",
|
||||||
|
"gdbPath": "${env:GD32_GCC_BIN}/arm-none-eabi-gdb.exe",
|
||||||
|
"servertype": "jlink",
|
||||||
|
"device": "${config:gd32.jlink.device}",
|
||||||
|
"interface": "${config:gd32.jlink.interface}",
|
||||||
|
"svdFile": "${workspaceFolder}/GD32E230.svd",
|
||||||
|
"liveWatch": {
|
||||||
|
"enabled": true,
|
||||||
|
"samplesPerSecond": 1
|
||||||
|
},
|
||||||
|
"preLaunchTask": "Build",
|
||||||
|
"preRestartCommands": [
|
||||||
|
"load",
|
||||||
|
"continue"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
r
|
||||||
|
exit
|
||||||
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"cmake.configureOnOpen": true,
|
||||||
|
"cmake.useCMakePresets": "always",
|
||||||
|
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||||
|
"cortex-debug.variableUseNaturalFormat": true,
|
||||||
|
"gd32.openocd.targetConfig": "target/openocd_gdlink_gd32e23x.cfg",
|
||||||
|
"gd32.openocd.massEraseCommand": "gd32e23x mass_erase 0",
|
||||||
|
"gd32.jlink.device": "GD32E230F8",
|
||||||
|
"gd32.jlink.interface": "SWD",
|
||||||
|
"gd32.jlink.speed": "4000",
|
||||||
|
"files.associations": {
|
||||||
|
"*.h": "c",
|
||||||
|
"*.c": "c"
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+229
@@ -0,0 +1,229 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build",
|
||||||
|
"type": "cmake",
|
||||||
|
"command": "build",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"base": "$gcc",
|
||||||
|
"fileLocation": [
|
||||||
|
"relative",
|
||||||
|
"${command:cmake.buildDirectory}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"environment": {
|
||||||
|
"CLICOLOR_FORCE": "1",
|
||||||
|
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"id": "code",
|
||||||
|
"tooltip": "Build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build and Flash",
|
||||||
|
"dependsOn": [
|
||||||
|
"Build",
|
||||||
|
"Flash MCU"
|
||||||
|
],
|
||||||
|
"dependsOrder": "sequence",
|
||||||
|
"group": "build",
|
||||||
|
"icon": {
|
||||||
|
"id": "insert",
|
||||||
|
"tooltip": "Build and Flash"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Flash MCU",
|
||||||
|
"type": "process",
|
||||||
|
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
|
||||||
|
"args": [
|
||||||
|
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
|
||||||
|
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}",
|
||||||
|
"-c", "init; reset halt; flash write_image erase ${command:cmake.launchTargetFilename}; reset; exit"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${command:cmake.buildDirectory}/Application",
|
||||||
|
"environment": {
|
||||||
|
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"id": "gather",
|
||||||
|
"tooltip": "Flash MCU"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Reset MCU",
|
||||||
|
"type": "process",
|
||||||
|
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
|
||||||
|
"args": [
|
||||||
|
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
|
||||||
|
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}",
|
||||||
|
"-c", "init; reset; exit"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${command:cmake.buildDirectory}/Application",
|
||||||
|
"environment": {
|
||||||
|
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"id": "discard",
|
||||||
|
"tooltip": "Reset MCU"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Mass Erase MCU",
|
||||||
|
"type": "process",
|
||||||
|
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
|
||||||
|
"args": [
|
||||||
|
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
|
||||||
|
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}",
|
||||||
|
"-c", "init; reset halt; ${config:gd32.openocd.massEraseCommand}; exit"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${command:cmake.buildDirectory}/Application",
|
||||||
|
"environment": {
|
||||||
|
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"id": "clear-all",
|
||||||
|
"tooltip": "Erase MCU"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "OpenOCD Server",
|
||||||
|
"type": "process",
|
||||||
|
"command": "${env:GD32_OPENOCD_BIN}/openocd.exe",
|
||||||
|
"args": [
|
||||||
|
"-s", "${env:GD32_OPENOCD_SCRIPTS}",
|
||||||
|
"-f", "${env:GD32_OPENOCD_SCRIPTS}/${config:gd32.openocd.targetConfig}"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${command:cmake.buildDirectory}/Application",
|
||||||
|
"environment": {
|
||||||
|
"OPENOCD_SCRIPTS": "${env:GD32_OPENOCD_SCRIPTS}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build and Flash (Jlink)",
|
||||||
|
"dependsOn": [
|
||||||
|
"Build",
|
||||||
|
"Flash MCU (Jlink)"
|
||||||
|
],
|
||||||
|
"dependsOrder": "sequence",
|
||||||
|
"group": "build",
|
||||||
|
"icon": {
|
||||||
|
"id": "insert",
|
||||||
|
"tooltip": "Build and Flash (Jlink)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Flash MCU (Jlink)",
|
||||||
|
"type": "process",
|
||||||
|
"command": "JLink.exe",
|
||||||
|
"args": [
|
||||||
|
"-device", "${config:gd32.jlink.device}",
|
||||||
|
"-if", "${config:gd32.jlink.interface}",
|
||||||
|
"-speed", "${config:gd32.jlink.speed}",
|
||||||
|
"-autoconnect", "1",
|
||||||
|
"-CommanderScript", "${workspaceFolder}/.vscode/flash.jlink"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${command:cmake.buildDirectory}/Application"
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"id": "gather",
|
||||||
|
"tooltip": "Flash MCU (Jlink)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Reset MCU (Jlink)",
|
||||||
|
"type": "process",
|
||||||
|
"command": "JLink.exe",
|
||||||
|
"args": [
|
||||||
|
"-device", "${config:gd32.jlink.device}",
|
||||||
|
"-if", "${config:gd32.jlink.interface}",
|
||||||
|
"-speed", "${config:gd32.jlink.speed}",
|
||||||
|
"-autoconnect", "1",
|
||||||
|
"-CommanderScript", "${workspaceFolder}/.vscode/reset.jlink"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"id": "discard",
|
||||||
|
"tooltip": "Reset MCU (Jlink)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Mass Erase MCU (Jlink)",
|
||||||
|
"type": "process",
|
||||||
|
"command": "JLink.exe",
|
||||||
|
"args": [
|
||||||
|
"-device", "${config:gd32.jlink.device}",
|
||||||
|
"-if", "${config:gd32.jlink.interface}",
|
||||||
|
"-speed", "${config:gd32.jlink.speed}",
|
||||||
|
"-autoconnect", "1",
|
||||||
|
"-CommanderScript", "${workspaceFolder}/.vscode/erase.jlink"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"id": "clear-all",
|
||||||
|
"tooltip": "Erase MCU (Jlink)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ configure_file(${CMAKE_SOURCE_DIR}/cmake/version.h.in ${CMAKE_BINARY_DIR}/genera
|
|||||||
# 添加SDK库
|
# 添加SDK库
|
||||||
add_subdirectory(SDK/CMSIS)
|
add_subdirectory(SDK/CMSIS)
|
||||||
add_subdirectory(SDK/GD32E23x_standard_peripheral)
|
add_subdirectory(SDK/GD32E23x_standard_peripheral)
|
||||||
|
add_subdirectory(SDK/SEGGER_RTT)
|
||||||
|
|
||||||
# 业务代码源文件
|
# 业务代码源文件
|
||||||
set(TARGET_SRC
|
set(TARGET_SRC
|
||||||
@@ -69,6 +70,7 @@ target_link_options(${PROJECT_NAME} PRIVATE
|
|||||||
# 链接SDK库
|
# 链接SDK库
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE CMSIS)
|
target_link_libraries(${PROJECT_NAME} PRIVATE CMSIS)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE GD32E23x_standard_peripheral)
|
target_link_libraries(${PROJECT_NAME} PRIVATE GD32E23x_standard_peripheral)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE SEGGER_RTT)
|
||||||
|
|
||||||
# 生成 bin/hex/list 文件名格式:[工程名_版本号_编译条件_编译日期]
|
# 生成 bin/hex/list 文件名格式:[工程名_版本号_编译条件_编译日期]
|
||||||
set(OUTPUT_PREFIX "${PROJECT_NAME}_${VERSION}_${BUILD_VARIANT}_${BUILD_DATE}")
|
set(OUTPUT_PREFIX "${PROJECT_NAME}_${VERSION}_${BUILD_VARIANT}_${BUILD_DATE}")
|
||||||
@@ -77,6 +79,7 @@ add_custom_command(TARGET ${PROJECT_NAME}
|
|||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND echo -- Running Post Build Commands
|
COMMAND echo -- Running Post Build Commands
|
||||||
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${PROJECT_NAME}> ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.hex
|
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${PROJECT_NAME}> ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.hex
|
||||||
|
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${PROJECT_NAME}> $<TARGET_FILE_DIR:${PROJECT_NAME}>/Application.hex
|
||||||
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${PROJECT_NAME}> ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.bin
|
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${PROJECT_NAME}> ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.bin
|
||||||
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${PROJECT_NAME}>
|
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${PROJECT_NAME}>
|
||||||
COMMAND ${CMAKE_OBJDUMP} -h -S $<TARGET_FILE:${PROJECT_NAME}> > ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.list
|
COMMAND ${CMAKE_OBJDUMP} -h -S $<TARGET_FILE:${PROJECT_NAME}> > ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_PREFIX}.list
|
||||||
|
|||||||
+40
-39
@@ -1,6 +1,14 @@
|
|||||||
#ifndef BOARD_CONFIG_H
|
#ifndef BOARD_CONFIG_H
|
||||||
#define BOARD_CONFIG_H
|
#define BOARD_CONFIG_H
|
||||||
|
|
||||||
|
#ifndef CFG_DISABLE
|
||||||
|
#define CFG_DISABLE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CFG_ENABLE
|
||||||
|
#define CFG_ENABLE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GD32E23XF4 0x10
|
#define GD32E23XF4 0x10
|
||||||
#define GD32E23XF6 0x20
|
#define GD32E23XF6 0x20
|
||||||
#define GD32E23XF8 0x40
|
#define GD32E23XF8 0x40
|
||||||
@@ -11,23 +19,44 @@
|
|||||||
|
|
||||||
/* >>>>>>>>>>>>>>>>>>>>[IIC TYPE DEFINE]<<<<<<<<<<<<<<<<<<<< */
|
/* >>>>>>>>>>>>>>>>>>>>[IIC TYPE DEFINE]<<<<<<<<<<<<<<<<<<<< */
|
||||||
|
|
||||||
// #define SOFTWARE_IIC // IIC Type : Software IIC
|
#define SOFTWARE_IIC CFG_DISABLE // CFG_DISABLE: Hardware IIC; CFG_ENABLE: Software IIC
|
||||||
#undef SOFTWARE_IIC // IIC Type : Hardware IIC
|
|
||||||
|
|
||||||
/* >>>>>>>>>>>>>>>>>>>>[DEBUG MODE]<<<<<<<<<<<<<<<<<<<< */
|
/* >>>>>>>>>>>>>>>>>>>>[DEBUG MODE]<<<<<<<<<<<<<<<<<<<< */
|
||||||
|
|
||||||
// #define DEBUG_MODE // Operating Mode : Debug Mode
|
#define DEBUG_MODE CFG_DISABLE // CFG_DISABLE: Release Mode; CFG_ENABLE: Debug Mode
|
||||||
#undef DEBUG_MODE // Operating Mode : Release Mode
|
|
||||||
|
|
||||||
/* >>>>>>>>>>>>>>>>>>>>[COMMAND DEBUG]<<<<<<<<<<<<<<<<<<<< */
|
/* >>>>>>>>>>>>>>>>>>>>[COMMAND DEBUG]<<<<<<<<<<<<<<<<<<<< */
|
||||||
|
|
||||||
// #define COM_DEBUG // Enable Command Debug Information
|
#define COM_DEBUG CFG_DISABLE // CFG_DISABLE: Command debug off; CFG_ENABLE: Command debug on
|
||||||
#undef COM_DEBUG // Disable Command Debug Information
|
|
||||||
|
|
||||||
/* >>>>>>>>>>>>>>>>>>>>[DEBUG ASSERTIONS DEFINE]<<<<<<<<<<<<<<<<<<<< */
|
/* >>>>>>>>>>>>>>>>>>>>[DEBUG ASSERTIONS DEFINE]<<<<<<<<<<<<<<<<<<<< */
|
||||||
|
|
||||||
// #define DEBUG_VERBOSE // Debug Assertions Status : Debug Verbose Information
|
#define DEBUG_VERBOSE CFG_DISABLE // CFG_DISABLE: Verbose debug off; CFG_ENABLE: Verbose debug on
|
||||||
#undef DEBUG_VERBOSE // Debug Assertions Status : No Debug Verbose Information
|
|
||||||
|
/* >>>>>>>>>>>>>>>>>>>>[SEGGER RTT DETECTION]<<<<<<<<<<<<<<<<<<<< */
|
||||||
|
|
||||||
|
#define SEGGER_RTT_DETECTION CFG_ENABLE // CFG_DISABLE: SEGGER RTT off; CFG_ENABLE: SEGGER RTT on
|
||||||
|
|
||||||
|
#if SEGGER_RTT_DETECTION == CFG_ENABLE
|
||||||
|
#include "SEGGER_RTT.h"
|
||||||
|
#define RTT_printf(ch, ...) SEGGER_RTT_printf(ch, __VA_ARGS__)
|
||||||
|
#define RTT_WriteString(ch, s) SEGGER_RTT_WriteString(ch, s)
|
||||||
|
#define RTT_PutChar(ch, c) SEGGER_RTT_PutChar(ch, c)
|
||||||
|
#else
|
||||||
|
#define RTT_printf(ch, ...)
|
||||||
|
#define RTT_WriteString(ch, s)
|
||||||
|
#define RTT_PutChar(ch, c)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* >>>>>>>>>>>>>>>>>>>>[RS485 MODE]<<<<<<<<<<<<<<<<<<<< */
|
||||||
|
|
||||||
|
#define RS485_MODE CFG_DISABLE // CFG_DISABLE: RS485 off; CFG_ENABLE: RS485 on
|
||||||
|
|
||||||
|
#if RS485_MODE == CFG_ENABLE
|
||||||
|
#define RS485_DE_RCU RCU_GPIOA
|
||||||
|
#define RS485_DE_PORT GPIOA
|
||||||
|
#define RS485_DE_PIN GPIO_PIN_1 // 根据实际硬件修改 DE 引脚
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@@ -58,9 +87,9 @@ void usart1_irq_handler(void);
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
#define LED_RCU RCU_GPIOA
|
#define LED_RCU RCU_GPIOB
|
||||||
#define LED_PORT GPIOA
|
#define LED_PORT GPIOB
|
||||||
#define LED_PIN GPIO_PIN_7
|
#define LED_PIN GPIO_PIN_1
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@@ -75,34 +104,6 @@ void usart1_irq_handler(void);
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
#define FAN_T_GPIO_PORT_RCU RCU_GPIOA
|
|
||||||
#define FAN_T_GPIO_PORT GPIOA
|
|
||||||
#define FAN_T_PWR_EN GPIO_PIN_5
|
|
||||||
#define FAN_T_PWM GPIO_PIN_6
|
|
||||||
#define FAN_T_DETECT GPIO_PIN_4
|
|
||||||
|
|
||||||
#define FAN_A_GPIO_PORT_RCU RCU_GPIOA
|
|
||||||
#define FAN_A_PWR_PORT_RCU RCU_GPIOB
|
|
||||||
#define FAN_A_GPIO_PORT GPIOA
|
|
||||||
#define FAN_A_PWR_PORT GPIOB
|
|
||||||
#define FAN_A_PWR_EN GPIO_PIN_1
|
|
||||||
#define FAN_A_PWM GPIO_PIN_9
|
|
||||||
#define FAN_A_DETECT GPIO_PIN_10
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// UV-LED NTC Temperature Sensor Definitions AD_CHANNEL_0
|
|
||||||
#define LAMP_TEMP_GPIO_PORT_RCU RCU_GPIOA
|
|
||||||
#define LAMP_TEMP_GPIO_PORT GPIOA
|
|
||||||
#define LAMP_TEMP_AD_PIN GPIO_PIN_0
|
|
||||||
|
|
||||||
// DMD NTC Temperature Sensor Definitions AD_CHANNEL_1
|
|
||||||
#define DMD_TEMP_GPIO_PORT_RCU RCU_GPIOA
|
|
||||||
#define DMD_TEMP_GPIO_PORT GPIOA
|
|
||||||
#define DMD_TEMP_AD_PIN GPIO_PIN_1
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
#define DEBUG_UART USART0
|
#define DEBUG_UART USART0
|
||||||
|
|
||||||
void mcu_detect_and_config(void);
|
void mcu_detect_and_config(void);
|
||||||
|
|||||||
@@ -86,12 +86,14 @@ i2c_result_t i2c_bus_reset(void);
|
|||||||
\param[out] none
|
\param[out] none
|
||||||
\retval none
|
\retval none
|
||||||
*/
|
*/
|
||||||
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
void i2c_scan(void);
|
void i2c_scan(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief write 16-bit data to I2C device
|
\brief write 16-bit data to I2C device
|
||||||
\param[in] slave_addr: 7-bit slave address
|
\param[in] slave_addr: 7-bit slave address
|
||||||
\param[in] reg_addr: register address
|
\param[in] reg_addr: register address (16-bit, high byte first)
|
||||||
\param[in] data: pointer to 2-byte data array
|
\param[in] data: pointer to 2-byte data array
|
||||||
\param[out] none
|
\param[out] none
|
||||||
\retval i2c_result_t
|
\retval i2c_result_t
|
||||||
@@ -117,19 +119,29 @@ i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data
|
|||||||
\param[out] none
|
\param[out] none
|
||||||
\retval i2c_result_t: operation result
|
\retval i2c_result_t: operation result
|
||||||
*/
|
*/
|
||||||
i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);
|
i2c_result_t i2c_write(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uint8_t length);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief read data from I2C device with configurable length
|
\brief read data from I2C device with configurable length
|
||||||
\param[in] slave_addr: slave device address (7-bit)
|
\param[in] slave_addr: slave device address (7-bit)
|
||||||
\param[in] reg_addr: register address
|
\param[in] reg_addr: register address (16-bit, high byte first)
|
||||||
\param[out] data: pointer to data buffer
|
\param[out] data: pointer to data buffer
|
||||||
\param[in] length: number of bytes to read (1-255)
|
\param[in] length: number of bytes to read (1-255)
|
||||||
\retval i2c_result_t: operation result
|
\retval i2c_result_t: operation result
|
||||||
*/
|
*/
|
||||||
i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length);
|
i2c_result_t i2c_read(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uint8_t length);
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
/* Pure read response without sub-address phase (for commands that already sent read request parameters) */
|
||||||
|
/*!
|
||||||
|
\brief read data from I2C device without register/sub-address phase
|
||||||
|
\param[in] slave_addr: slave device address (7-bit)
|
||||||
|
\param[out] data: pointer to data buffer
|
||||||
|
\param[in] length: number of bytes to read (1-255)
|
||||||
|
\retval i2c_result_t: operation result
|
||||||
|
*/
|
||||||
|
i2c_result_t i2c_read_raw(uint8_t slave_addr, uint8_t *data, uint8_t length);
|
||||||
|
|
||||||
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
/*!
|
/*!
|
||||||
\brief get status string for debugging
|
\brief get status string for debugging
|
||||||
\param[in] status: i2c_result_t value
|
\param[in] status: i2c_result_t value
|
||||||
|
|||||||
@@ -8,11 +8,15 @@
|
|||||||
|
|
||||||
- [适用范围](#适用范围)
|
- [适用范围](#适用范围)
|
||||||
- [默认配置](#默认配置)
|
- [默认配置](#默认配置)
|
||||||
|
- [快速开始](#快速开始)
|
||||||
|
- [工程结构](#工程结构)
|
||||||
|
- [板级配置](#板级配置)
|
||||||
|
- [Flash 偏移配置(配合 Bootloader)](#flash-偏移配置配合-bootloader)
|
||||||
- [工具链准备](#工具链准备)
|
- [工具链准备](#工具链准备)
|
||||||
|
- [工具链切换](#工具链切换)
|
||||||
- [使用说明](#使用说明)
|
- [使用说明](#使用说明)
|
||||||
- [时钟配置说明](#时钟配置说明)
|
- [时钟配置说明](#时钟配置说明)
|
||||||
- [vcpkg 依赖管理(可选)](#vcpkg-依赖管理可选)
|
- [vcpkg 依赖管理(可选)](#vcpkg-依赖管理可选)
|
||||||
- [建议补充内容](#建议补充内容)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -27,44 +31,368 @@
|
|||||||
## 默认配置
|
## 默认配置
|
||||||
|
|
||||||
- MCU 主频:内部 RC 振荡器,系统时钟配置为 72MHz
|
- MCU 主频:内部 RC 振荡器,系统时钟配置为 72MHz
|
||||||
|
- 调试串口:USART0(PA2 TX / PA3 RX),115200 波特率
|
||||||
|
- I2C:默认硬件 I2C0(PF0 SDA / PF1 SCL),可通过 `board_config.h` 切换为软件 I2C
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 基于模板创建新项目
|
||||||
|
|
||||||
|
1. **克隆或复制本仓库**
|
||||||
|
```bash
|
||||||
|
git clone https://gitea.hulk.wang/hulk/gd32e23x_template_cmake_vscode.git my-new-project
|
||||||
|
cd my-new-project
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **修改项目配置** — 编辑 `cmake/project_config.cmake`:
|
||||||
|
```cmake
|
||||||
|
set(PROJECT_NAME "MyProject") # 项目名称
|
||||||
|
set(BOARD_TYPE_CODE 20) # 板卡类型码(协议帧中的标识)
|
||||||
|
set(VERSION_MAJOR 1) # 主版本号
|
||||||
|
set(VERSION_MINOR 0) # 次版本号
|
||||||
|
set(VERSION_PATCH 0) # 修订号
|
||||||
|
set(BUILD_VARIANT "APP") # 编译变体
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **添加业务源文件** — 编辑 `CMakeLists.txt`,在 `TARGET_SRC` 中添加你的 `.c` 文件。
|
||||||
|
|
||||||
|
4. **配置板级引脚** — 编辑 `Inc/board_config.h`,修改 I2C、UART、LED 等引脚定义。
|
||||||
|
|
||||||
|
5. **编译**
|
||||||
|
```bash
|
||||||
|
cmake --preset Debug
|
||||||
|
cmake --build Build/Debug
|
||||||
|
```
|
||||||
|
产物在 `Build/Debug/` 下,包含 `.elf`、`.hex`、`.bin`、`.map`、`.list`。
|
||||||
|
|
||||||
|
### 分支说明
|
||||||
|
|
||||||
|
| 分支 | 用途 |
|
||||||
|
|------|------|
|
||||||
|
| `template_pc` | **主模板**(推荐),用于桌面端 VSCode 开发 |
|
||||||
|
| `template_xl` | 小琅适配版 |
|
||||||
|
| `main` | 早期版本,不推荐使用 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 工程结构
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── CMakeLists.txt # 主构建文件
|
||||||
|
├── CMakePresets.json # CMake 预设(Debug/Release)
|
||||||
|
├── cmake/
|
||||||
|
│ ├── arm-none-eabi-gcc.cmake # ARM GCC 工具链配置
|
||||||
|
│ ├── project.cmake # 编译选项(-Os/-O0, -mcpu=cortex-m23)
|
||||||
|
│ ├── project_config.cmake # 项目名/版本号/编译变体
|
||||||
|
│ └── version.h.in # 自动生成固件版本头
|
||||||
|
├── Inc/ # 头文件
|
||||||
|
│ ├── board_config.h # 板级引脚定义 + 功能开关
|
||||||
|
│ ├── command.h # 串口命令协议
|
||||||
|
│ ├── i2c.h / led.h / systick.h / uart.h
|
||||||
|
│ └── uart_ring_buffer.h / gd32e23x_it.h / gd32e23x_libopt.h
|
||||||
|
├── Src/ # 源码
|
||||||
|
│ ├── main.c # 入口函数
|
||||||
|
│ ├── command.c # 命令解析处理
|
||||||
|
│ ├── board_config.c # MCU 型号自动检测
|
||||||
|
│ ├── i2c.c / led.c / systick.c / uart.c / uart_ring_buffer.c
|
||||||
|
│ └── gd32e23x_it.c / system_gd32e23x.c / syscalls.c
|
||||||
|
├── SDK/
|
||||||
|
│ ├── CMSIS/ # ARM CMSIS Core (Cortex-M23) + GD 启动文件
|
||||||
|
│ └── GD32E23x_standard_peripheral/ # GD32 标准外设库
|
||||||
|
├── LD/gd32e23x_flash.ld # 链接脚本
|
||||||
|
├── doc/ # 芯片数据手册
|
||||||
|
└── .vscode/ # VSCode 调试/烧录配置
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 板级配置(`Inc/board_config.h`)
|
||||||
|
|
||||||
|
所有功能开关和引脚定义集中在 `Inc/board_config.h`。功能开关均为单行数值宏:将右侧的 `ENABLE` 或 `DISABLE` 改为另一值即可;其中 `ENABLE` 为 `1`,`DISABLE` 为 `0`。以下为完整的宏开关说明和推荐使用方式。
|
||||||
|
|
||||||
|
### 功能开关速查表
|
||||||
|
|
||||||
|
| 宏 | 作用 | 默认值 | Release 建议 |
|
||||||
|
|---|------|:---:|:---:|
|
||||||
|
| `SOFTWARE_IIC` | I2C 实现方式 | `DISABLE`(硬件) | `DISABLE` |
|
||||||
|
| `DEBUG_MODE` | printf 串口输出 | `DISABLE` | `DISABLE` |
|
||||||
|
| `COM_DEBUG` | 命令帧调试打印 | `DISABLE` | `DISABLE` |
|
||||||
|
| `DEBUG_VERBOSE` | 详细调试信息 | `DISABLE` | `DISABLE` |
|
||||||
|
| `SEGGER_RTT_DETECTION` | SEGGER RTT 支持 | `ENABLE` | `DISABLE` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `SOFTWARE_IIC` — I2C 实现方式
|
||||||
|
|
||||||
|
选择 I2C 使用硬件外设还是软件 GPIO 模拟。
|
||||||
|
|
||||||
|
> 当前工程尚未实现 `SOFTWARE_IIC` 的条件编译驱动选择;该宏已迁移为数值配置,但改值不会在此版本切换 I2C 实现。
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define SOFTWARE_IIC DISABLE // DISABLE: 硬件 I2C(默认);ENABLE: 软件 I2C(GPIO 模拟)
|
||||||
|
```
|
||||||
|
|
||||||
|
| 选项 | 优点 | 缺点 |
|
||||||
|
|------|------|------|
|
||||||
|
| 硬件 I2C | DMA 支持、CPU 占用低 | 仅限固定引脚、调试复杂 |
|
||||||
|
| 软件 I2C | 任意 GPIO、移植方便 | CPU 占用高、速率受限 |
|
||||||
|
|
||||||
|
> 切换后需同步修改下方 I2C 引脚定义。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `DEBUG_MODE` — 调试模式
|
||||||
|
|
||||||
|
开启后 USART0 输出 printf 调试信息。**Release 固件必须关闭。**
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define DEBUG_MODE DISABLE // DISABLE: 关闭(默认);ENABLE: 开启调试输出
|
||||||
|
```
|
||||||
|
|
||||||
|
**影响范围:**
|
||||||
|
- 使能 `USART0` 初始化和 `printf` 重定向到串口
|
||||||
|
- 会占用 PA2/PA3 引脚和 USART0 硬件资源
|
||||||
|
- 增加 ROM 约 2~4KB(取决于 printf 调用量)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `COM_DEBUG` — 命令帧调试打印
|
||||||
|
|
||||||
|
开启后串口命令解析过程打印每帧的详细内容(地址、长度、数据、校验)。**仅调试通信协议时开启。**
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define COM_DEBUG DISABLE // DISABLE: 关闭(默认);ENABLE: 开启命令帧调试
|
||||||
|
```
|
||||||
|
|
||||||
|
**依赖:** 需要先开启 `DEBUG_MODE`,否则输出无法外发。
|
||||||
|
|
||||||
|
**输出示例:**
|
||||||
|
```text
|
||||||
|
[CMD] ADDR=01 LEN=05 DATA: AA BB CC DD EE CHK=OK
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ Release 必须关闭,否则大量串口输出会严重拖慢主循环。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `DEBUG_VERBOSE` — 详细调试信息
|
||||||
|
|
||||||
|
在 `DEBUG_MODE` 基础上输出更底层的信息,如 I2C 总线扫描结果、MCU 型号识别等。
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define DEBUG_VERBOSE DISABLE // DISABLE: 关闭(默认);ENABLE: 开启详细调试
|
||||||
|
```
|
||||||
|
|
||||||
|
**额外输出:**
|
||||||
|
- 启动时打印 MCU Flash 容量检测结果
|
||||||
|
- I2C 初始化时扫描总线上的设备地址
|
||||||
|
- 其他诊断信息
|
||||||
|
|
||||||
|
> 依赖 `DEBUG_MODE`,开启后 ROM 进一步增加约 1~2KB。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `SEGGER_RTT_DETECTION` — SEGGER RTT 支持
|
||||||
|
|
||||||
|
RTT(Real-Time Transfer)是 SEGGER 的调试通道技术,通过 SWD 接口传输数据,不占用串口引脚,速度远超 UART。
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define SEGGER_RTT_DETECTION ENABLE // DISABLE: 禁用 RTT;ENABLE: 启用 RTT(默认)
|
||||||
|
```
|
||||||
|
|
||||||
|
**启用时:**
|
||||||
|
- 自动包含 `SEGGER_RTT.h`,提供 `RTT_printf` / `RTT_WriteString` / `RTT_PutChar` 宏
|
||||||
|
- `SDK/SEGGER_RTT/` 模块参与编译和链接
|
||||||
|
- 可用 J-Link RTT Viewer 或 VSCode + cortex-debug 查看实时日志
|
||||||
|
|
||||||
|
**禁用时:**
|
||||||
|
- 应用层 RTT 头文件引用与调用代码均在预处理阶段排除
|
||||||
|
- RTT 宏展开为空操作;应用目标不生成 RTT 调用代码
|
||||||
|
- 为保持现有 CMake SDK 加载方式,`SDK/SEGGER_RTT/` 仍会参与构建;静态库中未被引用的对象不会被链接器提取
|
||||||
|
|
||||||
|
> **Release 建议关闭** — RTT 依赖调试器连接,量产固件中无意义且占用 ROM。
|
||||||
|
|
||||||
|
**依赖关系总览:**
|
||||||
|
```
|
||||||
|
COM_DEBUG ──── 依赖 ──→ DEBUG_MODE
|
||||||
|
DEBUG_VERBOSE ─ 依赖 ──→ DEBUG_MODE
|
||||||
|
SEGGER_RTT_DETECTION ─ 独立,与 DEBUG_MODE 并行
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 引脚定义
|
||||||
|
|
||||||
|
所有引脚宏集中在 `board_config.h` 尾部,按需修改:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* I2C */
|
||||||
|
#define I2C_SCL_PORT GPIOF
|
||||||
|
#define I2C_SCL_PIN GPIO_PIN_1
|
||||||
|
#define I2C_SDA_PORT GPIOF
|
||||||
|
#define I2C_SDA_PIN GPIO_PIN_0
|
||||||
|
|
||||||
|
/* LED */
|
||||||
|
#define LED_RCU RCU_GPIOB
|
||||||
|
#define LED_PORT GPIOB
|
||||||
|
#define LED_PIN GPIO_PIN_1
|
||||||
|
|
||||||
|
/* UART */
|
||||||
|
#define UART_GPIO_PORT GPIOA
|
||||||
|
#define UART_TX_PIN GPIO_PIN_2
|
||||||
|
#define UART_RX_PIN GPIO_PIN_3
|
||||||
|
#define UART_BAUDRATE 115200U
|
||||||
|
```
|
||||||
|
|
||||||
|
### MCU 型号自动检测
|
||||||
|
|
||||||
|
`board_config.c` 中的 `mcu_detect_and_config()` 上电自动识别 GD32E230 的 Flash 容量(F4=16K / F6=32K / F8=64K),结果存入全局变量 `g_mcu_flash_size`,并自动选择对应的 UART 外设(USART0 或 USART1)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Flash 偏移配置(配合 Bootloader)
|
||||||
|
|
||||||
|
如果固件需要通过 Bootloader 启动(Bootloader 占用 Flash 前部区域),需修改两处:
|
||||||
|
|
||||||
|
**1. 链接脚本** — `LD/gd32e23x_flash.ld` 第 15 行:
|
||||||
|
```c
|
||||||
|
// 默认:从 Flash 起始运行
|
||||||
|
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
|
||||||
|
|
||||||
|
// 配合 Bootloader:前 8KB 留给 Bootloader,App 从 0x08002000 开始
|
||||||
|
FLASH (rx) : ORIGIN = 0x08002000, LENGTH = 8K
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. 向量表偏移** — `Src/system_gd32e23x.c` 第 44 行:
|
||||||
|
```c
|
||||||
|
// 默认
|
||||||
|
#define VECT_TAB_OFFSET (uint32_t)0x00
|
||||||
|
|
||||||
|
// 配合 Bootloader(值 = Flash 偏移量,不含 0x0800 前缀)
|
||||||
|
#define VECT_TAB_OFFSET (uint32_t)0x2000
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ 两个偏移值必须对应修改:`LD` 中的 `ORIGIN` 减去 `0x08000000` 应等于 `VECT_TAB_OFFSET`。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 工具链准备
|
## 工具链准备
|
||||||
|
|
||||||
### 1. xPack GNU Arm Embedded GCC Toolchain
|
### 1. ARM GCC 工具链
|
||||||
|
|
||||||
- **版本**:xpack-arm-none-eabi-gcc-11.3.1-1.1
|
- **版本**:xpack-arm-none-eabi-gcc-11.3.1-1.1
|
||||||
- **建议解压路径**:Tools/xpack-arm-none-eabi-gcc-11.3.1-1.1
|
- **安装位置**:每台电脑本机任意目录,工具包不放入工程仓库
|
||||||
- **官方下载地址**:https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases
|
- **官方下载地址**:https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases
|
||||||
- **路径自定义说明**:
|
- **活动变量**:`GD32_GCC_BIN`,值为工具链的 `bin` 目录(也接受工具链根目录)
|
||||||
如需自定义工具链路径,请同步修改以下文件:
|
|
||||||
- `Projects/<BoardName>/<ProjectName>/cmake/arm-none-eabi-gcc.cmake`(第2行)
|
|
||||||
- `Projects/<BoardName>/<ProjectName>/.vscode/launch.json`(第12行)
|
|
||||||
|
|
||||||
### 2. OpenOCD
|
### 2. OpenOCD(调试/烧录)
|
||||||
|
|
||||||
- **版本**:xpack-openocd-0.11.0-3
|
- **版本**:xpack-openocd-0.11.0-3
|
||||||
- **建议解压路径**:Tools/xpack-openocd-0.11.0-3
|
- **安装位置**:每台电脑本机任意目录,工具包不放入工程仓库
|
||||||
- **获取地址**:https://github.com/burakenez/gd32-tools-xpack-openocd/tree/v0.11.0-3
|
- **获取地址**:https://github.com/burakenez/gd32-tools-xpack-openocd/tree/v0.11.0-3
|
||||||
- **说明**:
|
- **活动变量**:`GD32_OPENOCD_BIN`、`GD32_OPENOCD_SCRIPTS`
|
||||||
- 本版本提取自 Embedded Builder V1.4.1.23782。
|
- **版本说明**:GD32 支持依赖发行版补丁,优先使用已验证的 0.11.0-3;更换版本前应先单独验证目标芯片和调试器。
|
||||||
- ⚠️ 请勿随意更换版本,因 GD32 MCU 支持有限,推荐严格使用此版本。
|
|
||||||
- **路径自定义说明**:
|
OpenOCD 的 cfg 文件由工程自己的 `.vscode/settings.json` 指定,环境变量只提供 `scripts` 根目录。模板默认使用 `target/openocd_gdlink_gd32e23x.cfg`;其它芯片工程只需修改 `gd32.openocd.targetConfig`,例如 `target/openocd_gdlink_gd32f4xx.cfg`,不需要修改环境变量。
|
||||||
如需自定义 OpenOCD 路径,请同步修改以下文件:
|
|
||||||
- `Projects/<BoardName>/<ProjectName>/.vscode/launch.json`(第14、17行)
|
cfg 必须可以直接启动完整会话,包含调试器 interface 和目标芯片配置;只有 `target/gd32e23x.cfg` 这种 target-only 文件不能单独启动调试会话。
|
||||||
- `Projects/<BoardName>/<ProjectName>/.vscode/task.json` 中所有相关路径
|
|
||||||
|
例如 CMSIS-DAP 的 wrapper cfg 可以写成:
|
||||||
|
|
||||||
|
```tcl
|
||||||
|
source [find interface/cmsis-dap.cfg]
|
||||||
|
source [find target/gd32e23x.cfg]
|
||||||
|
```
|
||||||
|
|
||||||
|
每台开发电脑配置一次用户环境变量(路径按本机实际位置填写):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
[Environment]::SetEnvironmentVariable("GD32_GCC_BIN", "C:\toolchain\xpack-arm-none-eabi-gcc-11.3.1-1.1\bin", "User")
|
||||||
|
[Environment]::SetEnvironmentVariable("GD32_OPENOCD_BIN", "D:\Tools\xpack-openocd-0.11.0-3\bin", "User")
|
||||||
|
[Environment]::SetEnvironmentVariable("GD32_OPENOCD_SCRIPTS", "D:\Tools\xpack-openocd-0.11.0-3\scripts", "User")
|
||||||
|
```
|
||||||
|
|
||||||
|
重新打开 VSCode,使新环境变量进入 VSCode 进程。`.vscode` 中的编译、GDB、OpenOCD 任务只读取上述 `GD32_*` 变量;OpenOCD 的通用变量 `OPENOCD_SCRIPTS` 仅在任务/调试子进程中覆盖,因此不会继承 STM32Cube 或 ESP-IDF 的全局值。
|
||||||
|
|
||||||
|
## 工具链切换
|
||||||
|
|
||||||
|
环境变量只是字符串,不同变量指向同一个目录完全没有问题。建议给每套工具链保留一个有意义的变量名,再把其中一套设为活动变量:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
[Environment]::SetEnvironmentVariable("GD32_GCC_XPACK11_BIN", "C:\toolchain\xpack-arm-none-eabi-gcc-11.3.1-1.1\bin", "User")
|
||||||
|
[Environment]::SetEnvironmentVariable("GD32_GCC_GNU12_BIN", "C:\toolchain\gcc-arm-none-eabi\bin", "User")
|
||||||
|
|
||||||
|
# 当前使用 xPack GCC 11.3.1
|
||||||
|
[Environment]::SetEnvironmentVariable("GD32_GCC_BIN", "C:\toolchain\xpack-arm-none-eabi-gcc-11.3.1-1.1\bin", "User")
|
||||||
|
# 切换到 GNU Arm GCC 12.3.1 时,把 GD32_GCC_BIN 改为对应路径
|
||||||
|
[Environment]::SetEnvironmentVariable("GD32_GCC_BIN", "C:\toolchain\gcc-arm-none-eabi\bin", "User")
|
||||||
|
```
|
||||||
|
|
||||||
|
切换后重新打开 VSCode,并对 Debug/Release 执行一次 `Delete Cache and Reconfigure`,因为 CMake 会把编译器绝对路径写入构建目录缓存。CMake 也支持临时覆盖环境变量:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cmake --preset Debug -DGD32_GCC_ENV_VAR=GD32_MY_GCC_BIN
|
||||||
|
cmake --preset Debug -DTOOLCHAIN_DIRECTORY="C:/toolchain/gcc-arm-none-eabi/bin"
|
||||||
|
```
|
||||||
|
|
||||||
|
工程变量统一使用 `GD32_` 前缀。`GD32_GCC_ENV_VAR` 只影响 CMake 配置;`.vscode` 的 GDB 路径仍使用规范变量 `GD32_GCC_BIN`,如采用自定义变量名,建议同时让 `GD32_GCC_BIN` 指向同一目录。GCC、GDB、`ar`、`ld`、`objcopy` 等 binutils 必须来自同一套发行版,不要混用不同版本的组件。
|
||||||
|
|
||||||
|
### 环境要求清单
|
||||||
|
|
||||||
|
- **必须配置的环境变量**
|
||||||
|
|
||||||
|
| 变量名 | 值 | 用途 |
|
||||||
|
|---|---|---|
|
||||||
|
| `GD32_GCC_BIN` | 活动 ARM GCC 的 `bin` 目录(或工具链根目录) | CMake 编译、GDB 调试、binutils |
|
||||||
|
| `GD32_OPENOCD_BIN` | 包含 `openocd.exe` 的 `bin` 目录 | OpenOCD 任务/调试 |
|
||||||
|
| `GD32_OPENOCD_SCRIPTS` | OpenOCD `scripts` 根目录 | `-s` 脚本搜索路径 |
|
||||||
|
|
||||||
|
- **可选的环境变量**:为不同 GCC 版本分别建立 `GD32_GCC_XPACK11_BIN`、`GD32_GCC_GNU12_BIN` 等变量,需要切换时手动把选中的路径写入 `GD32_GCC_BIN`。`GD32_GCC_ENV_VAR` 仅在需要让 CMake 使用另一个 `GD32_*` 变量名时设置。
|
||||||
|
- ARM GCC 必须是 `arm-none-eabi` 交叉工具链,变量指向工具链根目录或 `bin` 目录;`gcc`、`g++`、`gdb`、`ar`、`as`、`ld`、`objcopy`、`objdump`、`size`、`ranlib` 必须齐全。
|
||||||
|
- 当前工程已验证 xPack GCC 11.3.1 和 GNU Arm GCC 12.3.1;链接脚本使用 GCC 11+ 支持的 `READONLY` 语法。更换更新版本仍需在目标板上验证编译、链接和调试。
|
||||||
|
- OpenOCD 需要同时提供 `GD32_OPENOCD_BIN`、`GD32_OPENOCD_SCRIPTS`;任务会在 bin 目录下使用固定文件名 `openocd.exe`,每个工程在 `.vscode/settings.json` 中设置相对 `scripts` 根目录的 `gd32.openocd.targetConfig`,不依赖全局 `OPENOCD_SCRIPTS`。
|
||||||
|
- CMake ≥ 3.20、Ninja、VSCode CMake Tools,以及 cortex-debug(使用 OpenOCD 调试时)必须已安装;J-Link 任务另需 `JLink.exe` 在 PATH 中。
|
||||||
|
- J-Link 的 `device`、`interface`、`speed` 是工程属性,配置在 `.vscode/settings.json` 的 `gd32.jlink.*` 中;换 GD32F405 等芯片时只修改这些设置和对应的 OpenOCD target cfg。OpenOCD 的擦除命令同样通过 `gd32.openocd.massEraseCommand` 按芯片调整。
|
||||||
|
- 环境变量建议写入用户级环境(`User`),设置后重启 VSCode;切换 GCC 后必须清理对应 Debug/Release 构建缓存。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
1. **准备工具链**
|
### 编译
|
||||||
- 按上述说明下载并解压 ARM GCC 和 OpenOCD 到 Tools 目录。
|
|
||||||
- Toolchain 目录内容不会被 git 跟踪,需自行维护。
|
|
||||||
|
|
||||||
2. **烧录固件**
|
```bash
|
||||||
- 可直接使用 VSCode 任务栏的 Flash MCU 任务,或命令行运行 OpenOCD。
|
# Debug 构建(-O0, -g3)
|
||||||
|
cmake --preset Debug
|
||||||
|
cmake --build Build/Debug
|
||||||
|
|
||||||
|
# Release 构建(-Os, -g0)
|
||||||
|
cmake --preset Release
|
||||||
|
cmake --build Build/Release
|
||||||
|
```
|
||||||
|
|
||||||
|
### 烧录
|
||||||
|
|
||||||
|
通过 VSCode 任务栏运行 `Flash MCU` 任务,或命令行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openocd -f interface/cmsis-dap.cfg -f target/gd32e23x.cfg -c "program Build/Debug/Application.elf verify reset exit"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 产物
|
||||||
|
|
||||||
|
编译输出位于 `Build/<Config>/`:
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `Application.elf` | ELF 固件(调试用) |
|
||||||
|
| `{项目名}_{版本}_{编译条件}_{日期}.hex` | Hex 文件 |
|
||||||
|
| `{项目名}_{版本}_{编译条件}_{日期}.bin` | 二进制文件 |
|
||||||
|
| `{项目名}_{版本}_{编译条件}_{日期}.list` | 反汇编清单 |
|
||||||
|
| `{项目名}_{版本}_{编译条件}_{日期}.map` | 内存映射 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -84,7 +412,7 @@
|
|||||||
2. 取消你需要的时钟方案的注释,并注释掉其它方案。
|
2. 取消你需要的时钟方案的注释,并注释掉其它方案。
|
||||||
3. 保存后重新编译工程即可生效。
|
3. 保存后重新编译工程即可生效。
|
||||||
|
|
||||||
详细时钟初始化流程可参考 `system_gd32e23x.c` 文件中的 `system_clock_config` 及相关函数实现。
|
详细时钟初始化流程可参考 `Src/system_gd32e23x.c` 文件中的 `system_clock_config` 及相关函数实现。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -122,18 +450,3 @@
|
|||||||
2. 启动 VSCode 或命令行,vcpkg 会自动检测并安装所需工具。
|
2. 启动 VSCode 或命令行,vcpkg 会自动检测并安装所需工具。
|
||||||
|
|
||||||
如不需要 vcpkg,可忽略本文件。
|
如不需要 vcpkg,可忽略本文件。
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 建议补充内容
|
|
||||||
|
|
||||||
- **快速上手示例**:如 main.c 的最小点灯/串口输出代码片段。
|
|
||||||
- **常见问题与解答**:如构建失败、烧录失败的排查建议。
|
|
||||||
- **调试说明**:如何用 VSCode 调试、断点、查看寄存器等。
|
|
||||||
- **多板卡适配说明**:如有多种硬件,如何切换 BoardName。
|
|
||||||
- **贡献指南**:如何提交 PR、代码风格约定等。
|
|
||||||
- **License 说明**:开源协议和版权声明。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
如需进一步完善或有其他建议,欢迎随时反馈!
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
project(SEGGER_RTT LANGUAGES C)
|
||||||
|
|
||||||
|
add_library(SEGGER_RTT STATIC
|
||||||
|
SEGGER_RTT.c
|
||||||
|
SEGGER_RTT_printf.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(SEGGER_RTT PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(SEGGER_RTT PUBLIC CMSIS)
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,486 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* (c) SEGGER Microcontroller GmbH *
|
||||||
|
* The Embedded Experts *
|
||||||
|
* www.segger.com *
|
||||||
|
**********************************************************************
|
||||||
|
* *
|
||||||
|
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||||
|
* https://github.com/SEGGERMicro/RTT *
|
||||||
|
* *
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
---------------------------END-OF-HEADER------------------------------
|
||||||
|
Purpose : Implementation of SEGGER real-time transfer which allows
|
||||||
|
real-time communication on targets which support debugger
|
||||||
|
memory accesses while the CPU is running.
|
||||||
|
|
||||||
|
SEGGER strongly recommends to not make any changes to or
|
||||||
|
modify the source code of this software in order to stay
|
||||||
|
compatible with the RTT protocol and J-Link.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_H
|
||||||
|
#define SEGGER_RTT_H
|
||||||
|
|
||||||
|
#include "SEGGER_RTT_ConfDefaults.h"
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Defines, defaults
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RTT_USE_ASM
|
||||||
|
//
|
||||||
|
// Some cores support out-of-order memory accesses (reordering of memory accesses in the core)
|
||||||
|
// For such cores, we need to define a memory barrier to guarantee the order of certain accesses to the RTT ring buffers.
|
||||||
|
// Needed for:
|
||||||
|
// Cortex-M7 (ARMv7-M)
|
||||||
|
// Cortex-M23 (ARM-v8M)
|
||||||
|
// Cortex-M33 (ARM-v8M)
|
||||||
|
// Cortex-A/R (ARM-v7A/R)
|
||||||
|
//
|
||||||
|
// We do not explicitly check for "Embedded Studio" as the compiler in use determines what we support.
|
||||||
|
// You can use an external toolchain like IAR inside ES. So there is no point in checking for "Embedded Studio"
|
||||||
|
//
|
||||||
|
#if (defined __CROSSWORKS_ARM) // Rowley Crossworks
|
||||||
|
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined(__ARM_ARCH_8_1M_MAIN__)) // Cortex-M85
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#else
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#endif
|
||||||
|
#elif (defined __ARMCC_VERSION)
|
||||||
|
//
|
||||||
|
// ARM compiler
|
||||||
|
// ARM compiler V6.0 and later is clang based.
|
||||||
|
// Our ASM part is compatible to clang.
|
||||||
|
//
|
||||||
|
#if (__ARMCC_VERSION >= 6000000)
|
||||||
|
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#else
|
||||||
|
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#endif
|
||||||
|
#if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture
|
||||||
|
#elif (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif \
|
||||||
|
((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) || \
|
||||||
|
((defined __ARM_ARCH_8A__) || (defined __ARM_ARCH_8R__))
|
||||||
|
//
|
||||||
|
// Cortex-A/R ARMv7-A/R & ARMv8-A/R
|
||||||
|
//
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#else
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#endif
|
||||||
|
#elif ((defined __GNUC__) || (defined __clang__))
|
||||||
|
//
|
||||||
|
// GCC / Clang
|
||||||
|
//
|
||||||
|
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
// ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__
|
||||||
|
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here...
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#elif \
|
||||||
|
(defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__) || \
|
||||||
|
(defined __ARM_ARCH_8A__) || (defined __ARM_ARCH_8R__)
|
||||||
|
//
|
||||||
|
// Cortex-A/R ARMv7-A/R & ARMv8-A/R
|
||||||
|
//
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||||
|
#else
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#endif
|
||||||
|
#elif ((defined __IASMARM__) || (defined __ICCARM__))
|
||||||
|
//
|
||||||
|
// IAR assembler/compiler
|
||||||
|
//
|
||||||
|
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#if (__VER__ < 6300000)
|
||||||
|
#define VOLATILE
|
||||||
|
#else
|
||||||
|
#define VOLATILE volatile
|
||||||
|
#endif
|
||||||
|
#if (defined __ARM7M__) // Needed for old versions that do not know the define yet
|
||||||
|
#if (__CORE__ == __ARM7M__) // Cortex-M3
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if (defined __ARM7EM__)
|
||||||
|
#if (__CORE__ == __ARM7EM__) // Cortex-M4/M7
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if (defined __ARM8M_BASELINE__)
|
||||||
|
#if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if (defined __ARM8M_MAINLINE__)
|
||||||
|
#if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if (defined __ARM8EM_MAINLINE__)
|
||||||
|
#if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-???
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if\
|
||||||
|
((defined __ARM7A__) && (__CORE__ == __ARM7A__)) || \
|
||||||
|
((defined __ARM7R__) && (__CORE__ == __ARM7R__)) || \
|
||||||
|
((defined __ARM8A__) && (__CORE__ == __ARM8A__)) || \
|
||||||
|
((defined __ARM8R__) && (__CORE__ == __ARM8R__))
|
||||||
|
//
|
||||||
|
// Cortex-A/R ARMv7-A/R & ARMv8-A/R
|
||||||
|
//
|
||||||
|
#define _CORE_NEEDS_DMB 1
|
||||||
|
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
//
|
||||||
|
// Other compilers
|
||||||
|
//
|
||||||
|
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// If IDE and core support the ASM version, enable ASM version by default
|
||||||
|
//
|
||||||
|
#ifndef _CORE_HAS_RTT_ASM_SUPPORT
|
||||||
|
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores
|
||||||
|
#endif
|
||||||
|
#if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT)
|
||||||
|
#define RTT_USE_ASM (1)
|
||||||
|
#else
|
||||||
|
#define RTT_USE_ASM (0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _CORE_NEEDS_DMB
|
||||||
|
#define _CORE_NEEDS_DMB 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTT__DMB
|
||||||
|
#if _CORE_NEEDS_DMB
|
||||||
|
#error "Don't know how to place inline assembly for DMB"
|
||||||
|
#else
|
||||||
|
#define RTT__DMB()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||||
|
#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_UNCACHED_OFF
|
||||||
|
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||||
|
#error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||||
|
#else
|
||||||
|
#define SEGGER_RTT_UNCACHED_OFF (0)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if RTT_USE_ASM
|
||||||
|
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||||
|
#error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Defines, fixed
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine how much we must pad the control block to make it a multiple of a cache line in size
|
||||||
|
// Assuming: U8 = 1B
|
||||||
|
// U16 = 2B
|
||||||
|
// U32 = 4B
|
||||||
|
// U8/U16/U32* = 4B
|
||||||
|
//
|
||||||
|
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache
|
||||||
|
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE)
|
||||||
|
#else
|
||||||
|
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes)
|
||||||
|
#endif
|
||||||
|
#define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24))
|
||||||
|
#define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE)
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Types
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Description for a circular buffer (also called "ring buffer")
|
||||||
|
// which is used as up-buffer (T->H)
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
||||||
|
char* pBuffer; // Pointer to start of buffer
|
||||||
|
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||||
|
unsigned WrOff; // Position of next item to be written by either target.
|
||||||
|
volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host.
|
||||||
|
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||||
|
} SEGGER_RTT_BUFFER_UP;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Description for a circular buffer (also called "ring buffer")
|
||||||
|
// which is used as down-buffer (H->T)
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
||||||
|
char* pBuffer; // Pointer to start of buffer
|
||||||
|
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||||
|
volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host.
|
||||||
|
unsigned RdOff; // Position of next item to be read by target (down-buffer).
|
||||||
|
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||||
|
} SEGGER_RTT_BUFFER_DOWN;
|
||||||
|
|
||||||
|
//
|
||||||
|
// RTT control block which describes the number of buffers available
|
||||||
|
// as well as the configuration for each buffer
|
||||||
|
//
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
char acID[16]; // Initialized to "SEGGER RTT"
|
||||||
|
int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
|
||||||
|
int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
|
||||||
|
SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host
|
||||||
|
SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target
|
||||||
|
#if SEGGER_RTT__CB_PADDING
|
||||||
|
unsigned char aDummy[SEGGER_RTT__CB_PADDING];
|
||||||
|
#endif
|
||||||
|
} SEGGER_RTT_CB;
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Global data
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
extern SEGGER_RTT_CB _SEGGER_RTT;
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT API functions
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||||
|
int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||||
|
int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||||
|
int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||||
|
int SEGGER_RTT_GetKey (void);
|
||||||
|
unsigned SEGGER_RTT_HasData (unsigned BufferIndex);
|
||||||
|
int SEGGER_RTT_HasKey (void);
|
||||||
|
unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex);
|
||||||
|
void SEGGER_RTT_Init (void);
|
||||||
|
unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
||||||
|
unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
||||||
|
int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName);
|
||||||
|
int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName);
|
||||||
|
int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags);
|
||||||
|
int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags);
|
||||||
|
int SEGGER_RTT_WaitKey (void);
|
||||||
|
unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
|
unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
|
unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
|
unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
|
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
|
||||||
|
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
|
unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c);
|
||||||
|
unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c);
|
||||||
|
unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c);
|
||||||
|
unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex);
|
||||||
|
unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex);
|
||||||
|
//
|
||||||
|
// Function macro for performance optimization
|
||||||
|
//
|
||||||
|
#define SEGGER_RTT_HASDATA(n) (((SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff)
|
||||||
|
|
||||||
|
#if RTT_USE_ASM
|
||||||
|
#define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT transfer functions to send RTT data via other channels.
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
||||||
|
unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
||||||
|
unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
|
unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT "Terminal" API functions
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
int SEGGER_RTT_SetTerminal (unsigned char TerminalId);
|
||||||
|
int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s);
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT printf functions (require SEGGER_RTT_printf.c)
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
|
||||||
|
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ifndef(SEGGER_RTT_ASM)
|
||||||
|
|
||||||
|
//
|
||||||
|
// For some environments, NULL may not be defined until certain headers are included
|
||||||
|
//
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL ((void*)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Defines
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Operating modes. Define behavior if buffer is full (not enough space for entire message)
|
||||||
|
//
|
||||||
|
#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default)
|
||||||
|
#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits.
|
||||||
|
#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer.
|
||||||
|
#define SEGGER_RTT_MODE_MASK (3)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Control sequences, based on ANSI.
|
||||||
|
// Can be used to control color, and clear the screen
|
||||||
|
//
|
||||||
|
#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors
|
||||||
|
#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left
|
||||||
|
|
||||||
|
#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m"
|
||||||
|
#define RTT_CTRL_TEXT_RED "\x1B[2;31m"
|
||||||
|
#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m"
|
||||||
|
#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m"
|
||||||
|
#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m"
|
||||||
|
#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m"
|
||||||
|
#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m"
|
||||||
|
#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m"
|
||||||
|
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m"
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m"
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m"
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m"
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m"
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m"
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m"
|
||||||
|
#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m"
|
||||||
|
|
||||||
|
#define RTT_CTRL_BG_BLACK "\x1B[24;40m"
|
||||||
|
#define RTT_CTRL_BG_RED "\x1B[24;41m"
|
||||||
|
#define RTT_CTRL_BG_GREEN "\x1B[24;42m"
|
||||||
|
#define RTT_CTRL_BG_YELLOW "\x1B[24;43m"
|
||||||
|
#define RTT_CTRL_BG_BLUE "\x1B[24;44m"
|
||||||
|
#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m"
|
||||||
|
#define RTT_CTRL_BG_CYAN "\x1B[24;46m"
|
||||||
|
#define RTT_CTRL_BG_WHITE "\x1B[24;47m"
|
||||||
|
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m"
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m"
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m"
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m"
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m"
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m"
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m"
|
||||||
|
#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m"
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*************************** End of file ****************************/
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* SEGGER Microcontroller GmbH *
|
||||||
|
* The Embedded Experts *
|
||||||
|
**********************************************************************
|
||||||
|
---------------------------END-OF-HEADER------------------------------
|
||||||
|
File : SEGGER_RTT_Conf.h
|
||||||
|
Purpose : RTT configuration for GD32E230 (8KB RAM, conservative buffers)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_CONF_H
|
||||||
|
#define SEGGER_RTT_CONF_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BUFFER_SIZE_UP (512)
|
||||||
|
#define BUFFER_SIZE_DOWN (16)
|
||||||
|
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2)
|
||||||
|
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2)
|
||||||
|
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
|
||||||
|
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
|
||||||
|
|
||||||
|
// No RTOS, skip locking
|
||||||
|
#define SEGGER_RTT_LOCK()
|
||||||
|
#define SEGGER_RTT_UNLOCK()
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,476 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* (c) SEGGER Microcontroller GmbH *
|
||||||
|
* The Embedded Experts *
|
||||||
|
* www.segger.com *
|
||||||
|
**********************************************************************
|
||||||
|
* *
|
||||||
|
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||||
|
* https://github.com/SEGGERMicro/RTT *
|
||||||
|
* *
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
---------------------------END-OF-HEADER------------------------------
|
||||||
|
Purpose : Default configuration for RTT.
|
||||||
|
Do not change this file! Use SEGGER_RTT_Conf.h instead.
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_CONF_DEFAULTS_H
|
||||||
|
#define SEGGER_RTT_CONF_DEFAULTS_H
|
||||||
|
|
||||||
|
#include "SEGGER_RTT_Conf.h"
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Defines, configurable
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Take in and set to correct values for Cortex-A systems with CPU cache
|
||||||
|
//
|
||||||
|
//#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system
|
||||||
|
//#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached
|
||||||
|
//
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_MAX_NUM_UP_BUFFERS
|
||||||
|
*
|
||||||
|
* Description
|
||||||
|
* Maximum number of RTT up-buffers (Target -> Host).
|
||||||
|
*
|
||||||
|
* Additional information
|
||||||
|
* Common use case:
|
||||||
|
* Up-buffer channel 0: RTT Terminal I/O.
|
||||||
|
* Up-buffer channel 1: SystemView.
|
||||||
|
*/
|
||||||
|
#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
|
||||||
|
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3)
|
||||||
|
#endif
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
|
||||||
|
*
|
||||||
|
* Description
|
||||||
|
* Maximum number of RTT down-buffers (Host -> Target).
|
||||||
|
*
|
||||||
|
* Additional information
|
||||||
|
* Common use case:
|
||||||
|
* Down-buffer channel 0: RTT Terminal I/O.
|
||||||
|
* Down-buffer channel 1: SystemView.
|
||||||
|
*
|
||||||
|
* The number of up- and down-buffers may differ.
|
||||||
|
*/
|
||||||
|
#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
|
||||||
|
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* BUFFER_SIZE_UP
|
||||||
|
*
|
||||||
|
* Description
|
||||||
|
* Size of (auto-installed) up-buffer channel 0.
|
||||||
|
*
|
||||||
|
* Additional information
|
||||||
|
* Channel 0 is commonly used for Terminal I/O.
|
||||||
|
* Buffer should be large enough for all terminal (to host) output
|
||||||
|
* messages.
|
||||||
|
*/
|
||||||
|
#ifndef BUFFER_SIZE_UP
|
||||||
|
#define BUFFER_SIZE_UP (1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* BUFFER_SIZE_DOWN
|
||||||
|
*
|
||||||
|
* Description
|
||||||
|
* Size of (auto-installed) down-buffer channel 0.
|
||||||
|
*
|
||||||
|
* Additional information
|
||||||
|
* Channel 0 is commonly used for Terminal I/O.
|
||||||
|
* Buffer should be large enough to receive all terminal
|
||||||
|
* (from host) input.
|
||||||
|
*/
|
||||||
|
#ifndef BUFFER_SIZE_DOWN
|
||||||
|
#define BUFFER_SIZE_DOWN (16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_MODE_DEFAULT
|
||||||
|
*
|
||||||
|
* Description
|
||||||
|
* RTT Mode for channel 0.
|
||||||
|
*/
|
||||||
|
#ifndef SEGGER_RTT_MODE_DEFAULT
|
||||||
|
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||||
|
*
|
||||||
|
* Description
|
||||||
|
* Size of temporary buffer for RTT printf bulk-send.
|
||||||
|
*/
|
||||||
|
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||||
|
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT memcpy configuration
|
||||||
|
*
|
||||||
|
* memcpy() is good for large amounts of data,
|
||||||
|
* but the overhead is big for small amounts, which are usually stored via RTT.
|
||||||
|
* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead.
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions.
|
||||||
|
* This is may be required with memory access restrictions,
|
||||||
|
* such as on Cortex-A devices with MMU.
|
||||||
|
*/
|
||||||
|
#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
||||||
|
#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets
|
||||||
|
//
|
||||||
|
//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__))
|
||||||
|
// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes))
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Target is not allowed to perform other RTT operations while string still has not been stored completely.
|
||||||
|
// Otherwise we would probably end up with a mixed string in the buffer.
|
||||||
|
// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
|
||||||
|
//
|
||||||
|
// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
|
||||||
|
// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
|
||||||
|
// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
|
||||||
|
// (Higher priority = lower priority number)
|
||||||
|
// Default value for embOS: 128u
|
||||||
|
// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||||
|
// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC
|
||||||
|
// or define SEGGER_RTT_LOCK() to completely disable interrupts.
|
||||||
|
//
|
||||||
|
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||||
|
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for SEGGER Embedded Studio,
|
||||||
|
* Rowley CrossStudio and GCC
|
||||||
|
*/
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32))
|
||||||
|
#if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
__asm volatile ("mrs %0, primask \n\t" \
|
||||||
|
"movs r1, #1 \n\t" \
|
||||||
|
"msr primask, r1 \n\t" \
|
||||||
|
: "=r" (_SEGGER_RTT__LockState) \
|
||||||
|
: \
|
||||||
|
: "r1", "cc" \
|
||||||
|
);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
|
||||||
|
: \
|
||||||
|
: "r" (_SEGGER_RTT__LockState) \
|
||||||
|
: \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__))
|
||||||
|
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||||
|
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||||
|
#endif
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
__asm volatile ("mrs %0, basepri \n\t" \
|
||||||
|
"mov r1, %1 \n\t" \
|
||||||
|
"msr basepri, r1 \n\t" \
|
||||||
|
: "=r" (_SEGGER_RTT__LockState) \
|
||||||
|
: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
|
||||||
|
: "r1", "cc" \
|
||||||
|
);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
|
||||||
|
: \
|
||||||
|
: "r" (_SEGGER_RTT__LockState) \
|
||||||
|
: \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif (defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__))
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||||
|
"mov %0, r1 \n\t" \
|
||||||
|
"orr r1, r1, #0xC0 \n\t" \
|
||||||
|
"msr CPSR_c, r1 \n\t" \
|
||||||
|
: "=r" (_SEGGER_RTT__LockState) \
|
||||||
|
: \
|
||||||
|
: "r1", "cc" \
|
||||||
|
);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||||
|
"mrs r1, CPSR \n\t" \
|
||||||
|
"bic r1, r1, #0xC0 \n\t" \
|
||||||
|
"and r0, r0, #0xC0 \n\t" \
|
||||||
|
"orr r1, r1, r0 \n\t" \
|
||||||
|
"msr CPSR_c, r1 \n\t" \
|
||||||
|
: \
|
||||||
|
: "r" (_SEGGER_RTT__LockState) \
|
||||||
|
: "r0", "r1", "cc" \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#elif defined(__riscv) || defined(__riscv_xlen)
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
__asm volatile ("csrr %0, mstatus \n\t" \
|
||||||
|
"csrci mstatus, 8 \n\t" \
|
||||||
|
"andi %0, %0, 8 \n\t" \
|
||||||
|
: "=r" (_SEGGER_RTT__LockState) \
|
||||||
|
: \
|
||||||
|
: \
|
||||||
|
);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \
|
||||||
|
"or %0, %0, a1 \n\t" \
|
||||||
|
"csrs mstatus, %0 \n\t" \
|
||||||
|
: \
|
||||||
|
: "r" (_SEGGER_RTT__LockState) \
|
||||||
|
: "a1" \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for IAR EWARM
|
||||||
|
*/
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#ifdef __ICCARM__
|
||||||
|
#ifdef __IAR_SYSTEMS_ICC__
|
||||||
|
#include <intrinsics.h>
|
||||||
|
#endif
|
||||||
|
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \
|
||||||
|
(defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||||
|
__set_PRIMASK(1);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||||
|
}
|
||||||
|
#elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \
|
||||||
|
(defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \
|
||||||
|
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \
|
||||||
|
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__))
|
||||||
|
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||||
|
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||||
|
#endif
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
_SEGGER_RTT__LockState = __get_BASEPRI(); \
|
||||||
|
__set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \
|
||||||
|
}
|
||||||
|
#elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \
|
||||||
|
(defined (__ARM7R__) && (__CORE__ == __ARM7R__))
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||||
|
"mov %0, r1 \n\t" \
|
||||||
|
"orr r1, r1, #0xC0 \n\t" \
|
||||||
|
"msr CPSR_c, r1 \n\t" \
|
||||||
|
: "=r" (_SEGGER_RTT__LockState) \
|
||||||
|
: \
|
||||||
|
: "r1", "cc" \
|
||||||
|
);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||||
|
"mrs r1, CPSR \n\t" \
|
||||||
|
"bic r1, r1, #0xC0 \n\t" \
|
||||||
|
"and r0, r0, #0xC0 \n\t" \
|
||||||
|
"orr r1, r1, r0 \n\t" \
|
||||||
|
"msr CPSR_c, r1 \n\t" \
|
||||||
|
: \
|
||||||
|
: "r" (_SEGGER_RTT__LockState) \
|
||||||
|
: "r0", "r1", "cc" \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for IAR RX
|
||||||
|
*/
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#ifdef __ICCRX__
|
||||||
|
#ifdef __IAR_SYSTEMS_ICC__
|
||||||
|
#include <intrinsics.h>
|
||||||
|
#endif
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned long _SEGGER_RTT__LockState; \
|
||||||
|
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||||
|
__disable_interrupt();
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for IAR RL78
|
||||||
|
*/
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#ifdef __ICCRL78__
|
||||||
|
#ifdef __IAR_SYSTEMS_ICC__
|
||||||
|
#include <intrinsics.h>
|
||||||
|
#endif
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
__istate_t _SEGGER_RTT__LockState; \
|
||||||
|
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||||
|
__disable_interrupt();
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for KEIL ARM
|
||||||
|
*/
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#ifdef __CC_ARM
|
||||||
|
#if (defined __TARGET_ARCH_6S_M)
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \
|
||||||
|
_SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \
|
||||||
|
_SEGGER_RTT__PRIMASK = 1u; \
|
||||||
|
__schedule_barrier();
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \
|
||||||
|
__schedule_barrier(); \
|
||||||
|
}
|
||||||
|
#elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
|
||||||
|
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||||
|
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||||
|
#endif
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
register unsigned char BASEPRI __asm( "basepri"); \
|
||||||
|
_SEGGER_RTT__LockState = BASEPRI; \
|
||||||
|
BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
|
||||||
|
__schedule_barrier();
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \
|
||||||
|
__schedule_barrier(); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for TI ARM
|
||||||
|
*/
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#ifdef __TI_ARM__
|
||||||
|
#if defined (__TI_ARM_V6M0__)
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||||
|
__set_PRIMASK(1);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||||
|
}
|
||||||
|
#elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
|
||||||
|
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||||
|
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||||
|
#endif
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned int _SEGGER_RTT__LockState; \
|
||||||
|
_SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for CCRX
|
||||||
|
*/
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#ifdef __RX
|
||||||
|
#include <machine.h>
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
unsigned long _SEGGER_RTT__LockState; \
|
||||||
|
_SEGGER_RTT__LockState = get_psw() & 0x010000; \
|
||||||
|
clrpsw_i();
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration for embOS Simulation on Windows
|
||||||
|
* (Can also be used for generic RTT locking with embOS)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(SEGGER_RTT_LOCK) || !defined (SEGGER_RTT_UNLOCK)
|
||||||
|
#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS)
|
||||||
|
|
||||||
|
void OS_SIM_EnterCriticalSection(void);
|
||||||
|
void OS_SIM_LeaveCriticalSection(void);
|
||||||
|
|
||||||
|
#define SEGGER_RTT_LOCK() { \
|
||||||
|
OS_SIM_EnterCriticalSection();
|
||||||
|
|
||||||
|
#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* RTT lock configuration fallback
|
||||||
|
*/
|
||||||
|
#ifndef SEGGER_RTT_LOCK
|
||||||
|
#define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_UNLOCK
|
||||||
|
#define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* If SEGGER_RTT_SECTION is defined but SEGGER_RTT_BUFFER_SECTION
|
||||||
|
* is not, use the same section for SEGGER_RTT_BUFFER_SECTION.
|
||||||
|
*/
|
||||||
|
#ifndef SEGGER_RTT_BUFFER_SECTION
|
||||||
|
#if defined(SEGGER_RTT_SECTION)
|
||||||
|
#define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*************************** End of file ****************************/
|
||||||
@@ -0,0 +1,483 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* (c) SEGGER Microcontroller GmbH *
|
||||||
|
* The Embedded Experts *
|
||||||
|
* www.segger.com *
|
||||||
|
**********************************************************************
|
||||||
|
* *
|
||||||
|
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||||
|
* https://github.com/SEGGERMicro/RTT *
|
||||||
|
* *
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
---------------------------END-OF-HEADER------------------------------
|
||||||
|
Purpose : Replacement for printf to write formatted data via RTT
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#include "SEGGER_RTT.h"
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Defines, configurable
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||||
|
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
|
||||||
|
#define FORMAT_FLAG_PAD_ZERO (1u << 1)
|
||||||
|
#define FORMAT_FLAG_PRINT_SIGN (1u << 2)
|
||||||
|
#define FORMAT_FLAG_ALTERNATE (1u << 3)
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Types
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* pBuffer;
|
||||||
|
unsigned BufferSize;
|
||||||
|
unsigned Cnt;
|
||||||
|
|
||||||
|
int ReturnValue;
|
||||||
|
|
||||||
|
unsigned RTTBufferIndex;
|
||||||
|
} SEGGER_RTT_PRINTF_DESC;
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Function prototypes
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Static code
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* _StoreChar
|
||||||
|
*/
|
||||||
|
static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
|
||||||
|
unsigned Cnt;
|
||||||
|
|
||||||
|
Cnt = p->Cnt;
|
||||||
|
if ((Cnt + 1u) <= p->BufferSize) {
|
||||||
|
*(p->pBuffer + Cnt) = c;
|
||||||
|
p->Cnt = Cnt + 1u;
|
||||||
|
p->ReturnValue++;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Write part of string, when the buffer is full
|
||||||
|
//
|
||||||
|
if (p->Cnt == p->BufferSize) {
|
||||||
|
if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
|
||||||
|
p->ReturnValue = -1;
|
||||||
|
} else {
|
||||||
|
p->Cnt = 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* _PrintUnsigned
|
||||||
|
*/
|
||||||
|
static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||||
|
static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||||
|
unsigned Div;
|
||||||
|
unsigned Digit;
|
||||||
|
unsigned Number;
|
||||||
|
unsigned Width;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
Number = v;
|
||||||
|
Digit = 1u;
|
||||||
|
//
|
||||||
|
// Get actual field width
|
||||||
|
//
|
||||||
|
Width = 1u;
|
||||||
|
while (Number >= Base) {
|
||||||
|
Number = (Number / Base);
|
||||||
|
Width++;
|
||||||
|
}
|
||||||
|
if (NumDigits > Width) {
|
||||||
|
Width = NumDigits;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Print leading chars if necessary
|
||||||
|
//
|
||||||
|
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
|
||||||
|
if (FieldWidth != 0u) {
|
||||||
|
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
|
||||||
|
c = '0';
|
||||||
|
} else {
|
||||||
|
c = ' ';
|
||||||
|
}
|
||||||
|
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||||
|
FieldWidth--;
|
||||||
|
_StoreChar(pBufferDesc, c);
|
||||||
|
if (pBufferDesc->ReturnValue < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pBufferDesc->ReturnValue >= 0) {
|
||||||
|
//
|
||||||
|
// Compute Digit.
|
||||||
|
// Loop until Digit has the value of the highest digit required.
|
||||||
|
// Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
|
||||||
|
//
|
||||||
|
while (1) {
|
||||||
|
if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
|
||||||
|
NumDigits--;
|
||||||
|
} else {
|
||||||
|
Div = v / Digit;
|
||||||
|
if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Digit *= Base;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Output digits
|
||||||
|
//
|
||||||
|
do {
|
||||||
|
Div = v / Digit;
|
||||||
|
v -= Div * Digit;
|
||||||
|
_StoreChar(pBufferDesc, _aV2C[Div]);
|
||||||
|
if (pBufferDesc->ReturnValue < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Digit /= Base;
|
||||||
|
} while (Digit);
|
||||||
|
//
|
||||||
|
// Print trailing spaces if necessary
|
||||||
|
//
|
||||||
|
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
|
||||||
|
if (FieldWidth != 0u) {
|
||||||
|
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||||
|
FieldWidth--;
|
||||||
|
_StoreChar(pBufferDesc, ' ');
|
||||||
|
if (pBufferDesc->ReturnValue < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* _PrintInt
|
||||||
|
*/
|
||||||
|
static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||||
|
unsigned Width;
|
||||||
|
int Number;
|
||||||
|
|
||||||
|
Number = (v < 0) ? -v : v;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get actual field width
|
||||||
|
//
|
||||||
|
Width = 1u;
|
||||||
|
while (Number >= (int)Base) {
|
||||||
|
Number = (Number / (int)Base);
|
||||||
|
Width++;
|
||||||
|
}
|
||||||
|
if (NumDigits > Width) {
|
||||||
|
Width = NumDigits;
|
||||||
|
}
|
||||||
|
if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
|
||||||
|
FieldWidth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print leading spaces if necessary
|
||||||
|
//
|
||||||
|
if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
|
||||||
|
if (FieldWidth != 0u) {
|
||||||
|
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||||
|
FieldWidth--;
|
||||||
|
_StoreChar(pBufferDesc, ' ');
|
||||||
|
if (pBufferDesc->ReturnValue < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Print sign if necessary
|
||||||
|
//
|
||||||
|
if (pBufferDesc->ReturnValue >= 0) {
|
||||||
|
if (v < 0) {
|
||||||
|
v = -v;
|
||||||
|
_StoreChar(pBufferDesc, '-');
|
||||||
|
} else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
|
||||||
|
_StoreChar(pBufferDesc, '+');
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
if (pBufferDesc->ReturnValue >= 0) {
|
||||||
|
//
|
||||||
|
// Print leading zeros if necessary
|
||||||
|
//
|
||||||
|
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
|
||||||
|
if (FieldWidth != 0u) {
|
||||||
|
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||||
|
FieldWidth--;
|
||||||
|
_StoreChar(pBufferDesc, '0');
|
||||||
|
if (pBufferDesc->ReturnValue < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pBufferDesc->ReturnValue >= 0) {
|
||||||
|
//
|
||||||
|
// Print number without sign
|
||||||
|
//
|
||||||
|
_PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* Public code
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_vprintf
|
||||||
|
*
|
||||||
|
* Function description
|
||||||
|
* Stores a formatted string in SEGGER RTT control block.
|
||||||
|
* This data is read by the host.
|
||||||
|
*
|
||||||
|
* Parameters
|
||||||
|
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||||
|
* sFormat Pointer to format string
|
||||||
|
* pParamList Pointer to the list of arguments for the format string
|
||||||
|
*
|
||||||
|
* Return values
|
||||||
|
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||||
|
* < 0: Error
|
||||||
|
*/
|
||||||
|
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
|
||||||
|
char c;
|
||||||
|
SEGGER_RTT_PRINTF_DESC BufferDesc;
|
||||||
|
int v;
|
||||||
|
unsigned char PrecisionSet;
|
||||||
|
unsigned Precision;
|
||||||
|
unsigned FormatFlags;
|
||||||
|
unsigned FieldWidth;
|
||||||
|
char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
|
||||||
|
|
||||||
|
BufferDesc.pBuffer = acBuffer;
|
||||||
|
BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE;
|
||||||
|
BufferDesc.Cnt = 0u;
|
||||||
|
BufferDesc.RTTBufferIndex = BufferIndex;
|
||||||
|
BufferDesc.ReturnValue = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
c = *sFormat;
|
||||||
|
sFormat++;
|
||||||
|
if (c == 0u) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == '%') {
|
||||||
|
//
|
||||||
|
// Filter out flags
|
||||||
|
//
|
||||||
|
FormatFlags = 0u;
|
||||||
|
v = 1;
|
||||||
|
do {
|
||||||
|
c = *sFormat;
|
||||||
|
switch (c) {
|
||||||
|
case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
|
||||||
|
case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
|
||||||
|
case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
|
||||||
|
case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
|
||||||
|
default: v = 0; break;
|
||||||
|
}
|
||||||
|
} while (v);
|
||||||
|
//
|
||||||
|
// filter out field with
|
||||||
|
//
|
||||||
|
FieldWidth = 0u;
|
||||||
|
do {
|
||||||
|
c = *sFormat;
|
||||||
|
if ((c < '0') || (c > '9')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sFormat++;
|
||||||
|
FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Filter out precision (number of digits to display)
|
||||||
|
//
|
||||||
|
PrecisionSet = 0;
|
||||||
|
Precision = 0u;
|
||||||
|
c = *sFormat;
|
||||||
|
if (c == '.') {
|
||||||
|
sFormat++;
|
||||||
|
if (*sFormat == '*') {
|
||||||
|
sFormat++;
|
||||||
|
PrecisionSet = 1;
|
||||||
|
Precision = va_arg(*pParamList, int);
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
c = *sFormat;
|
||||||
|
if ((c < '0') || (c > '9')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PrecisionSet = 1;
|
||||||
|
sFormat++;
|
||||||
|
Precision = Precision * 10u + ((unsigned)c - '0');
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Filter out length modifier
|
||||||
|
//
|
||||||
|
c = *sFormat;
|
||||||
|
do {
|
||||||
|
if ((c == 'l') || (c == 'h')) {
|
||||||
|
sFormat++;
|
||||||
|
c = *sFormat;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
//
|
||||||
|
// Handle specifiers
|
||||||
|
//
|
||||||
|
switch (c) {
|
||||||
|
case 'c': {
|
||||||
|
char c0;
|
||||||
|
v = va_arg(*pParamList, int);
|
||||||
|
c0 = (char)v;
|
||||||
|
_StoreChar(&BufferDesc, c0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
v = va_arg(*pParamList, int);
|
||||||
|
_PrintInt(&BufferDesc, v, 10u, Precision, FieldWidth, FormatFlags);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
v = va_arg(*pParamList, int);
|
||||||
|
_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, Precision, FieldWidth, FormatFlags);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
v = va_arg(*pParamList, int);
|
||||||
|
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, Precision, FieldWidth, FormatFlags);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
const char * s = va_arg(*pParamList, const char *);
|
||||||
|
if (s == NULL) {
|
||||||
|
s = "(NULL)"; // Print (NULL) instead of crashing or breaking, as it is more informative to the user.
|
||||||
|
PrecisionSet = 0; // Make sure (NULL) is printed, even when precision was set.
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
c = *s;
|
||||||
|
s++;
|
||||||
|
if (c == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((PrecisionSet != 0) && (Precision == 0)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_StoreChar(&BufferDesc, c);
|
||||||
|
Precision--;
|
||||||
|
} while (BufferDesc.ReturnValue >= 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
v = va_arg(*pParamList, int);
|
||||||
|
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
_StoreChar(&BufferDesc, '%');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sFormat++;
|
||||||
|
} else {
|
||||||
|
_StoreChar(&BufferDesc, c);
|
||||||
|
}
|
||||||
|
} while (BufferDesc.ReturnValue >= 0);
|
||||||
|
|
||||||
|
if (BufferDesc.ReturnValue > 0) {
|
||||||
|
//
|
||||||
|
// Write remaining data, if any
|
||||||
|
//
|
||||||
|
if (BufferDesc.Cnt != 0u) {
|
||||||
|
SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
|
||||||
|
}
|
||||||
|
BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
|
||||||
|
}
|
||||||
|
return BufferDesc.ReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_printf
|
||||||
|
*
|
||||||
|
* Function description
|
||||||
|
* Stores a formatted string in SEGGER RTT control block.
|
||||||
|
* This data is read by the host.
|
||||||
|
*
|
||||||
|
* Parameters
|
||||||
|
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||||
|
* sFormat Pointer to format string, followed by the arguments for conversion
|
||||||
|
*
|
||||||
|
* Return values
|
||||||
|
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||||
|
* < 0: Error
|
||||||
|
*
|
||||||
|
* Notes
|
||||||
|
* (1) Conversion specifications have following syntax:
|
||||||
|
* %[flags][FieldWidth][.Precision]ConversionSpecifier
|
||||||
|
* (2) Supported flags:
|
||||||
|
* -: Left justify within the field width
|
||||||
|
* +: Always print sign extension for signed conversions
|
||||||
|
* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
|
||||||
|
* Supported conversion specifiers:
|
||||||
|
* c: Print the argument as one char
|
||||||
|
* d: Print the argument as a signed integer
|
||||||
|
* u: Print the argument as an unsigned integer
|
||||||
|
* x: Print the argument as an hexadecimal integer
|
||||||
|
* s: Print the string pointed to by the argument
|
||||||
|
* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
|
||||||
|
*/
|
||||||
|
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
|
||||||
|
int r;
|
||||||
|
va_list ParamList;
|
||||||
|
|
||||||
|
va_start(ParamList, sFormat);
|
||||||
|
r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
|
||||||
|
va_end(ParamList);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
/*************************** End of file ****************************/
|
||||||
+2
-2
@@ -101,7 +101,7 @@ void system_software_reset(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Debug output control */
|
/* Debug output control */
|
||||||
#ifdef COM_DEBUG
|
#if COM_DEBUG == CFG_ENABLE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define COMMAND_DEBUG(fmt, ...) printf("[COMMAND] " fmt "\n", ##__VA_ARGS__)
|
#define COMMAND_DEBUG(fmt, ...) printf("[COMMAND] " fmt "\n", ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
@@ -565,7 +565,7 @@ void command_process(void) {
|
|||||||
// 到帧尾,进行各项校验
|
// 到帧尾,进行各项校验
|
||||||
bool verification_status = true;
|
bool verification_status = true;
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
if (cmd_buf[0] != PROTOCOL_PACKAGE_HEADER) {
|
if (cmd_buf[0] != PROTOCOL_PACKAGE_HEADER) {
|
||||||
send_response(RESP_TYPE_HEADER_ERR, s_report_status_err, sizeof(s_report_status_err));
|
send_response(RESP_TYPE_HEADER_ERR, s_report_status_err, sizeof(s_report_status_err));
|
||||||
verification_status = false;
|
verification_status = false;
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ void USART0_IRQHandler(void) {
|
|||||||
g_usart_config.irq_handler(); // 通过函数指针调用对应的处理函数
|
g_usart_config.irq_handler(); // 通过函数指针调用对应的处理函数
|
||||||
}
|
}
|
||||||
// 作为调试口(第二串口)时也接收数据,便于模拟上位机命令
|
// 作为调试口(第二串口)时也接收数据,便于模拟上位机命令
|
||||||
#ifdef DEBUG_MODE
|
#if DEBUG_MODE == CFG_ENABLE
|
||||||
else {
|
else {
|
||||||
usart0_irq_handler();
|
usart0_irq_handler();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ i2c_result_t i2c_bus_reset(void) {
|
|||||||
i2c_disable(I2C0);
|
i2c_disable(I2C0);
|
||||||
i2c_deinit(I2C0);
|
i2c_deinit(I2C0);
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C bus reset\r\n");
|
printf("I2C bus reset\r\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -145,6 +145,7 @@ i2c_result_t i2c_bus_reset(void) {
|
|||||||
* 如果在某个地址上发现了设备,则会打印出该设备的地址。
|
* 如果在某个地址上发现了设备,则会打印出该设备的地址。
|
||||||
* 最后会打印出找到的设备总数。
|
* 最后会打印出找到的设备总数。
|
||||||
*/
|
*/
|
||||||
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
void i2c_scan(void) {
|
void i2c_scan(void) {
|
||||||
uint32_t timeout;
|
uint32_t timeout;
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
@@ -249,6 +250,7 @@ void i2c_scan(void) {
|
|||||||
while (usart_flag_get(UART_PHY, USART_FLAG_TC) == RESET) {}
|
while (usart_flag_get(UART_PHY, USART_FLAG_TC) == RESET) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 内部辅助函数:等待指定的I2C标志位被设置,带有超时。
|
* @brief 内部辅助函数:等待指定的I2C标志位被设置,带有超时。
|
||||||
@@ -260,7 +262,7 @@ static i2c_result_t _i2c_wait_flag_timeout(uint32_t flag)
|
|||||||
uint16_t timeout = 0;
|
uint16_t timeout = 0;
|
||||||
while(!i2c_flag_get(I2C0, flag)){
|
while(!i2c_flag_get(I2C0, flag)){
|
||||||
if(timeout++ > I2C_TIME_OUT){
|
if(timeout++ > I2C_TIME_OUT){
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
const char* fname = "UNKNOWN";
|
const char* fname = "UNKNOWN";
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
case I2C_FLAG_SBSEND: fname = "SBSEND"; break;
|
case I2C_FLAG_SBSEND: fname = "SBSEND"; break;
|
||||||
@@ -359,7 +361,7 @@ i2c_result_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data
|
|||||||
} else {
|
} else {
|
||||||
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
|
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
|
||||||
timeout =0;
|
timeout =0;
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("IIC write failed for Error Slave Address. \n");
|
printf("IIC write failed for Error Slave Address. \n");
|
||||||
#endif
|
#endif
|
||||||
return I2C_RESULT_NACK;
|
return I2C_RESULT_NACK;
|
||||||
@@ -438,7 +440,7 @@ i2c_result_t i2c_write_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t data
|
|||||||
retry_count ++;
|
retry_count ++;
|
||||||
if (retry_count >= I2C_MAX_RETRY)
|
if (retry_count >= I2C_MAX_RETRY)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("IIC write failed after %d retries\n", I2C_MAX_RETRY);
|
printf("IIC write failed after %d retries\n", I2C_MAX_RETRY);
|
||||||
#endif
|
#endif
|
||||||
return I2C_RESULT_ERROR;
|
return I2C_RESULT_ERROR;
|
||||||
@@ -612,7 +614,7 @@ i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data
|
|||||||
|
|
||||||
retry_count++;
|
retry_count++;
|
||||||
if (retry_count >= I2C_MAX_RETRY) {
|
if (retry_count >= I2C_MAX_RETRY) {
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("IIC read failed after %d retries\n", I2C_MAX_RETRY);
|
printf("IIC read failed after %d retries\n", I2C_MAX_RETRY);
|
||||||
#endif
|
#endif
|
||||||
return I2C_RESULT_ERROR;
|
return I2C_RESULT_ERROR;
|
||||||
@@ -638,13 +640,13 @@ i2c_result_t i2c_read_16bits(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data
|
|||||||
/*!
|
/*!
|
||||||
\brief write data to I2C device with configurable length
|
\brief write data to I2C device with configurable length
|
||||||
\param[in] slave_addr: slave device address (7-bit)
|
\param[in] slave_addr: slave device address (7-bit)
|
||||||
\param[in] reg_addr: register address
|
\param[in] reg_addr: register address (16-bit, high byte first)
|
||||||
\param[in] data: pointer to data buffer
|
\param[in] data: pointer to data buffer
|
||||||
\param[in] length: number of bytes to write (1-255)
|
\param[in] length: number of bytes to write (1-255)
|
||||||
\param[out] none
|
\param[out] none
|
||||||
\retval i2c_result_t: operation result
|
\retval i2c_result_t: operation result
|
||||||
*/
|
*/
|
||||||
i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length) {
|
i2c_result_t i2c_write(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uint8_t length) {
|
||||||
i2c_state_t state = I2C_STATE_START;
|
i2c_state_t state = I2C_STATE_START;
|
||||||
uint16_t timeout = 0;
|
uint16_t timeout = 0;
|
||||||
uint8_t retry_count = 0;
|
uint8_t retry_count = 0;
|
||||||
@@ -652,7 +654,7 @@ i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint
|
|||||||
|
|
||||||
/* parameter validation */
|
/* parameter validation */
|
||||||
if (data == NULL || slave_addr > 0x7F || length == 0) {
|
if (data == NULL || slave_addr > 0x7F || length == 0) {
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C read invalid param: slave=0x%02X, len=%u, data=%p\r\n", slave_addr, length, data);
|
printf("I2C read invalid param: slave=0x%02X, len=%u, data=%p\r\n", slave_addr, length, data);
|
||||||
#endif
|
#endif
|
||||||
return I2C_RESULT_INVALID_PARAM;
|
return I2C_RESULT_INVALID_PARAM;
|
||||||
@@ -712,7 +714,7 @@ i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint
|
|||||||
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
|
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
|
||||||
i2c_stop_on_bus(I2C0);
|
i2c_stop_on_bus(I2C0);
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C write failed for Error Slave Address. \n");
|
printf("I2C write failed for Error Slave Address. \n");
|
||||||
#endif
|
#endif
|
||||||
return I2C_RESULT_NACK;
|
return I2C_RESULT_NACK;
|
||||||
@@ -725,8 +727,18 @@ i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send register address */
|
/* send register address, high byte first */
|
||||||
i2c_data_transmit(I2C0, reg_addr);
|
if(_i2c_wait_flag_timeout(I2C_FLAG_TBE) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i2c_data_transmit(I2C0, (uint8_t)(reg_addr >> 8));
|
||||||
|
|
||||||
|
if(_i2c_wait_flag_timeout(I2C_FLAG_TBE) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i2c_data_transmit(I2C0, (uint8_t)(reg_addr & 0xFF));
|
||||||
state = I2C_STATE_TRANSMIT_DATA;
|
state = I2C_STATE_TRANSMIT_DATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -787,7 +799,7 @@ i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint
|
|||||||
|
|
||||||
retry_count++;
|
retry_count++;
|
||||||
if (retry_count >= I2C_MAX_RETRY) {
|
if (retry_count >= I2C_MAX_RETRY) {
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("IIC write failed after %d retries\n", I2C_MAX_RETRY);
|
printf("IIC write failed after %d retries\n", I2C_MAX_RETRY);
|
||||||
#endif
|
#endif
|
||||||
return I2C_RESULT_ERROR;
|
return I2C_RESULT_ERROR;
|
||||||
@@ -812,12 +824,12 @@ i2c_result_t i2c_write(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint
|
|||||||
/*!
|
/*!
|
||||||
\brief read data from I2C device with configurable length
|
\brief read data from I2C device with configurable length
|
||||||
\param[in] slave_addr: slave device address (7-bit)
|
\param[in] slave_addr: slave device address (7-bit)
|
||||||
\param[in] reg_addr: register address
|
\param[in] reg_addr: register address (16-bit, high byte first)
|
||||||
\param[out] data: pointer to data buffer
|
\param[out] data: pointer to data buffer
|
||||||
\param[in] length: number of bytes to read (1-255)
|
\param[in] length: number of bytes to read (1-255)
|
||||||
\retval i2c_result_t: operation result
|
\retval i2c_result_t: operation result
|
||||||
*/
|
*/
|
||||||
i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t length) {
|
i2c_result_t i2c_read(uint8_t slave_addr, uint16_t reg_addr, uint8_t *data, uint8_t length) {
|
||||||
i2c_state_t state = I2C_STATE_START;
|
i2c_state_t state = I2C_STATE_START;
|
||||||
uint16_t timeout = 0;
|
uint16_t timeout = 0;
|
||||||
uint8_t retry_count = 0;
|
uint8_t retry_count = 0;
|
||||||
@@ -832,7 +844,7 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
/* enable acknowledge */
|
/* enable acknowledge */
|
||||||
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C read start: slave=0x%02X reg=0x%02X len=%u\r\n", slave_addr, reg_addr, length);
|
printf("I2C read start: slave=0x%02X reg=0x%02X len=%u\r\n", slave_addr, reg_addr, length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -884,7 +896,7 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* debug: show address ack and error flags */
|
/* debug: show address ack and error flags */
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C CLEAR_ADDRESS: write_phase=%d ADDSEND=%d AERR=%d\r\n",
|
printf("I2C CLEAR_ADDRESS: write_phase=%d ADDSEND=%d AERR=%d\r\n",
|
||||||
(int)write_phase,
|
(int)write_phase,
|
||||||
(int)i2c_flag_get(I2C0, I2C_FLAG_ADDSEND),
|
(int)i2c_flag_get(I2C0, I2C_FLAG_ADDSEND),
|
||||||
@@ -902,19 +914,19 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
- length > 2: keep ACK enabled and clear ADDR; we'll handle N-2/BTF sequence later */
|
- length > 2: keep ACK enabled and clear ADDR; we'll handle N-2/BTF sequence later */
|
||||||
if (length == 1) {
|
if (length == 1) {
|
||||||
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C READ phase: length=1, disabling ACK before clearing ADDSEND\r\n");
|
printf("I2C READ phase: length=1, disabling ACK before clearing ADDSEND\r\n");
|
||||||
#endif
|
#endif
|
||||||
} else if (length == 2) {
|
} else if (length == 2) {
|
||||||
i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT);
|
i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT);
|
||||||
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C READ phase: length=2, set ACKPOS_NEXT and disabling ACK before clearing ADDSEND\r\n");
|
printf("I2C READ phase: length=2, set ACKPOS_NEXT and disabling ACK before clearing ADDSEND\r\n");
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* length > 2: keep ACK enabled so slave will clock out data */
|
/* length > 2: keep ACK enabled so slave will clock out data */
|
||||||
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C READ phase: length=%u (>2), keeping ACK enabled\r\n", length);
|
printf("I2C READ phase: length=%u (>2), keeping ACK enabled\r\n", length);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -935,8 +947,18 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send register address */
|
/* send register address, high byte first */
|
||||||
i2c_data_transmit(I2C0, reg_addr);
|
if(_i2c_wait_flag_timeout(I2C_FLAG_TBE) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i2c_data_transmit(I2C0, (uint8_t)(reg_addr >> 8));
|
||||||
|
|
||||||
|
if(_i2c_wait_flag_timeout(I2C_FLAG_TBE) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i2c_data_transmit(I2C0, (uint8_t)(reg_addr & 0xFF));
|
||||||
state = I2C_STATE_RESTART;
|
state = I2C_STATE_RESTART;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -947,7 +969,7 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C RESTART: after BTC, delay 5ms and issuing repeated START\r\n");
|
printf("I2C RESTART: after BTC, delay 5ms and issuing repeated START\r\n");
|
||||||
#endif
|
#endif
|
||||||
/* small delay to allow slave device to prepare multi-byte data before repeated start */
|
/* small delay to allow slave device to prepare multi-byte data before repeated start */
|
||||||
@@ -970,13 +992,13 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
write_phase = false;
|
write_phase = false;
|
||||||
state = I2C_STATE_CLEAR_ADDRESS;
|
state = I2C_STATE_CLEAR_ADDRESS;
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C addressing sent for read (slave=0x%02X)\r\n", slave_addr);
|
printf("I2C addressing sent for read (slave=0x%02X)\r\n", slave_addr);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case I2C_STATE_RECEIVE_DATA:
|
case I2C_STATE_RECEIVE_DATA:
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C RECEIVE_DATA: expecting %u bytes\r\n", length);
|
printf("I2C RECEIVE_DATA: expecting %u bytes\r\n", length);
|
||||||
#endif
|
#endif
|
||||||
if (length == 1) {
|
if (length == 1) {
|
||||||
@@ -1058,7 +1080,7 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
|
|
||||||
case I2C_STATE_ERROR:
|
case I2C_STATE_ERROR:
|
||||||
/* I2C bus error, try to reset the bus and retry */
|
/* I2C bus error, try to reset the bus and retry */
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C_STATE_ERROR: resetting bus and retrying (retry_count=%u)\r\n", retry_count);
|
printf("I2C_STATE_ERROR: resetting bus and retrying (retry_count=%u)\r\n", retry_count);
|
||||||
#endif
|
#endif
|
||||||
i2c_bus_reset();
|
i2c_bus_reset();
|
||||||
@@ -1069,7 +1091,7 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
|
|
||||||
retry_count++;
|
retry_count++;
|
||||||
if (retry_count >= I2C_MAX_RETRY) {
|
if (retry_count >= I2C_MAX_RETRY) {
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
/* Print diagnostic flags to help root-cause analysis */
|
/* Print diagnostic flags to help root-cause analysis */
|
||||||
printf("I2C read final failure after %d retries, last_state=%d\r\n", I2C_MAX_RETRY, state);
|
printf("I2C read final failure after %d retries, last_state=%d\r\n", I2C_MAX_RETRY, state);
|
||||||
printf(" FLAGS: AERR=%d BERR=%d LOSTARB=%d I2CBSY=%d\r\n",
|
printf(" FLAGS: AERR=%d BERR=%d LOSTARB=%d I2CBSY=%d\r\n",
|
||||||
@@ -1078,7 +1100,7 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
(int)i2c_flag_get(I2C0, I2C_FLAG_LOSTARB),
|
(int)i2c_flag_get(I2C0, I2C_FLAG_LOSTARB),
|
||||||
(int)i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
|
(int)i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C read failed after %d retries\n", I2C_MAX_RETRY);
|
printf("I2C read failed after %d retries\n", I2C_MAX_RETRY);
|
||||||
#endif
|
#endif
|
||||||
return I2C_RESULT_ERROR;
|
return I2C_RESULT_ERROR;
|
||||||
@@ -1099,7 +1121,7 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* timeout path: provide debug info */
|
/* timeout path: provide debug info */
|
||||||
#ifdef DEBUG_VERBOSE
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
printf("I2C read timeout (end state). slave=0x%02X, len=%u\r\n", slave_addr, length);
|
printf("I2C read timeout (end state). slave=0x%02X, len=%u\r\n", slave_addr, length);
|
||||||
printf(" FLAGS: AERR=%d BERR=%d LOSTARB=%d I2CBSY=%d\r\n",
|
printf(" FLAGS: AERR=%d BERR=%d LOSTARB=%d I2CBSY=%d\r\n",
|
||||||
(int)i2c_flag_get(I2C0, I2C_FLAG_AERR),
|
(int)i2c_flag_get(I2C0, I2C_FLAG_AERR),
|
||||||
@@ -1110,7 +1132,164 @@ i2c_result_t i2c_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8
|
|||||||
return I2C_RESULT_TIMEOUT;
|
return I2C_RESULT_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
/*!
|
||||||
|
\brief read data from I2C device without register/sub-address phase
|
||||||
|
\param[in] slave_addr: slave device address (7-bit)
|
||||||
|
\param[out] data: pointer to data buffer
|
||||||
|
\param[in] length: number of bytes to read (1-255)
|
||||||
|
\retval i2c_result_t: operation result
|
||||||
|
*/
|
||||||
|
i2c_result_t i2c_read_raw(uint8_t slave_addr, uint8_t *data, uint8_t length)
|
||||||
|
{
|
||||||
|
i2c_state_t state = I2C_STATE_START;
|
||||||
|
uint16_t timeout = 0;
|
||||||
|
uint8_t retry_count = 0;
|
||||||
|
uint8_t data_index = 0;
|
||||||
|
|
||||||
|
if (data == NULL || slave_addr > 0x7F || length == 0) {
|
||||||
|
return I2C_RESULT_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||||
|
|
||||||
|
while (retry_count < (uint8_t)I2C_MAX_RETRY) {
|
||||||
|
switch (state) {
|
||||||
|
case I2C_STATE_START:
|
||||||
|
timeout = 0;
|
||||||
|
data_index = 0;
|
||||||
|
|
||||||
|
if (_i2c_wait_flag_clear_timeout(I2C_FLAG_I2CBSY) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_start_on_bus(I2C0);
|
||||||
|
state = I2C_STATE_SEND_ADDRESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case I2C_STATE_SEND_ADDRESS:
|
||||||
|
if (_i2c_wait_flag_timeout(I2C_FLAG_SBSEND) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_master_addressing(I2C0, (slave_addr << 1), I2C_RECEIVER);
|
||||||
|
state = I2C_STATE_CLEAR_ADDRESS;
|
||||||
|
timeout = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case I2C_STATE_CLEAR_ADDRESS:
|
||||||
|
while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (!i2c_flag_get(I2C0, I2C_FLAG_AERR)) && (timeout < I2C_TIME_OUT)) {
|
||||||
|
timeout++;
|
||||||
|
}
|
||||||
|
if (timeout >= I2C_TIME_OUT) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) {
|
||||||
|
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
|
||||||
|
i2c_stop_on_bus(I2C0);
|
||||||
|
return I2C_RESULT_NACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 1) {
|
||||||
|
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||||
|
} else if (length == 2) {
|
||||||
|
i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT);
|
||||||
|
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||||
|
} else {
|
||||||
|
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
|
||||||
|
state = I2C_STATE_RECEIVE_DATA;
|
||||||
|
timeout = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case I2C_STATE_RECEIVE_DATA:
|
||||||
|
if (length == 1) {
|
||||||
|
if (_i2c_wait_flag_timeout(I2C_FLAG_RBNE) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data[0] = i2c_data_receive(I2C0);
|
||||||
|
state = I2C_STATE_STOP;
|
||||||
|
} else if (length == 2) {
|
||||||
|
if (_i2c_wait_flag_timeout(I2C_FLAG_BTC) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i2c_stop_on_bus(I2C0);
|
||||||
|
data[0] = i2c_data_receive(I2C0);
|
||||||
|
data[1] = i2c_data_receive(I2C0);
|
||||||
|
state = I2C_STATE_STOP;
|
||||||
|
} else {
|
||||||
|
while (data_index < length) {
|
||||||
|
if (data_index < length - 2) {
|
||||||
|
if (_i2c_wait_flag_timeout(I2C_FLAG_RBNE) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data[data_index++] = i2c_data_receive(I2C0);
|
||||||
|
} else if (data_index == length - 2) {
|
||||||
|
if (_i2c_wait_flag_timeout(I2C_FLAG_BTC) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
|
||||||
|
i2c_stop_on_bus(I2C0);
|
||||||
|
data[data_index++] = i2c_data_receive(I2C0);
|
||||||
|
} else {
|
||||||
|
if (_i2c_wait_flag_timeout(I2C_FLAG_RBNE) != I2C_RESULT_SUCCESS) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data[data_index++] = i2c_data_receive(I2C0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state == I2C_STATE_ERROR) break;
|
||||||
|
state = I2C_STATE_STOP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case I2C_STATE_STOP:
|
||||||
|
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) {
|
||||||
|
timeout++;
|
||||||
|
}
|
||||||
|
if (timeout >= I2C_TIME_OUT) {
|
||||||
|
state = I2C_STATE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||||
|
i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT);
|
||||||
|
return I2C_RESULT_SUCCESS;
|
||||||
|
|
||||||
|
case I2C_STATE_ERROR:
|
||||||
|
i2c_bus_reset();
|
||||||
|
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
|
||||||
|
i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT);
|
||||||
|
|
||||||
|
retry_count++;
|
||||||
|
if (retry_count >= I2C_MAX_RETRY) {
|
||||||
|
return I2C_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = I2C_STATE_START;
|
||||||
|
timeout = 0;
|
||||||
|
delay_10us(10);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
state = I2C_STATE_START;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return I2C_RESULT_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
/*!
|
/*!
|
||||||
\brief get status string for debugging
|
\brief get status string for debugging
|
||||||
\param[in] status: i2c_status_t value
|
\param[in] status: i2c_status_t value
|
||||||
|
|||||||
+6
-2
@@ -62,11 +62,15 @@ int main(void)
|
|||||||
|
|
||||||
i2c_config();
|
i2c_config();
|
||||||
|
|
||||||
#ifdef DEBUG_MODE
|
#if DEBUG_MODE == CFG_ENABLE
|
||||||
printf("Hello World!\r\n");
|
printf("Hello World!\r\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#if SEGGER_RTT_DETECTION == CFG_ENABLE
|
||||||
|
RTT_printf(0, "Hello World!\r\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG_VERBOSE == CFG_ENABLE
|
||||||
i2c_scan();
|
i2c_scan();
|
||||||
|
|
||||||
i2c_bus_reset();
|
i2c_bus_reset();
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
It is strongly recommended to include it to avoid issues caused by self-removal.
|
It is strongly recommended to include it to avoid issues caused by self-removal.
|
||||||
*/
|
*/
|
||||||
#define RCU_MODIFY(__delay) do{ \
|
#define RCU_MODIFY(__delay) do{ \
|
||||||
volatile uint32_t i,reg; \
|
__IO uint32_t i,reg; \
|
||||||
if(0 != __delay){ \
|
if(0 != __delay){ \
|
||||||
reg = RCU_CFG0; \
|
reg = RCU_CFG0; \
|
||||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||||
|
|||||||
+4
-4
@@ -12,7 +12,7 @@
|
|||||||
#include "gd32e23x.h"
|
#include "gd32e23x.h"
|
||||||
#include "systick.h"
|
#include "systick.h"
|
||||||
|
|
||||||
volatile static uint32_t delay_count = 0;
|
static __IO uint32_t delay_count = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ************************************************************************
|
* ************************************************************************
|
||||||
@@ -47,7 +47,7 @@ void delay_10us(uint32_t count)
|
|||||||
uint32_t loops_per_10us = SystemCoreClock / 1700000; // 粗略估计,每10微秒的循环次数
|
uint32_t loops_per_10us = SystemCoreClock / 1700000; // 粗略估计,每10微秒的循环次数
|
||||||
|
|
||||||
for(uint32_t i = 0; i < count; i++) {
|
for(uint32_t i = 0; i < count; i++) {
|
||||||
for(volatile uint32_t j = 0; j < loops_per_10us; j++);
|
for(__IO uint32_t j = 0; j < loops_per_10us; j++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ void delay_decrement(void)
|
|||||||
// uint32_t loops_per_ms = SystemCoreClock / 14000; // 粗略估计
|
// uint32_t loops_per_ms = SystemCoreClock / 14000; // 粗略估计
|
||||||
|
|
||||||
// for(uint32_t i = 0; i < count; i++) {
|
// for(uint32_t i = 0; i < count; i++) {
|
||||||
// for(volatile uint32_t j = 0; j < loops_per_ms; j++);
|
// for(__IO uint32_t j = 0; j < loops_per_ms; j++);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -113,6 +113,6 @@ void delay_decrement(void)
|
|||||||
// uint32_t loops_per_us = SystemCoreClock / 22000000; // 粗略估计,每微秒的循环次数
|
// uint32_t loops_per_us = SystemCoreClock / 22000000; // 粗略估计,每微秒的循环次数
|
||||||
|
|
||||||
// for(uint32_t i = 0; i < count; i++) {
|
// for(uint32_t i = 0; i < count; i++) {
|
||||||
// for(volatile uint32_t j = 0; j < loops_per_us; j++);
|
// for(__IO uint32_t j = 0; j < loops_per_us; j++);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
+15
@@ -17,6 +17,14 @@ void uart_init(void) {
|
|||||||
gpio_mode_set(UART_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART_TX_PIN | UART_RX_PIN);
|
gpio_mode_set(UART_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART_TX_PIN | UART_RX_PIN);
|
||||||
gpio_output_options_set(UART_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART_TX_PIN | UART_RX_PIN);
|
gpio_output_options_set(UART_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART_TX_PIN | UART_RX_PIN);
|
||||||
|
|
||||||
|
#if RS485_MODE == CFG_ENABLE
|
||||||
|
/* 配置 RS485 DE 引脚 */
|
||||||
|
rcu_periph_clock_enable(RS485_DE_RCU);
|
||||||
|
gpio_af_set(RS485_DE_PORT, GPIO_AF_1, RS485_DE_PIN);
|
||||||
|
gpio_mode_set(RS485_DE_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, RS485_DE_PIN);
|
||||||
|
gpio_output_options_set(RS485_DE_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RS485_DE_PIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 配置波特率、数据位、停止位等 */
|
/* 配置波特率、数据位、停止位等 */
|
||||||
usart_deinit(UART_PHY);
|
usart_deinit(UART_PHY);
|
||||||
usart_word_length_set(UART_PHY, USART_WL_8BIT);
|
usart_word_length_set(UART_PHY, USART_WL_8BIT);
|
||||||
@@ -26,6 +34,13 @@ void uart_init(void) {
|
|||||||
usart_receive_config(UART_PHY, USART_RECEIVE_ENABLE);
|
usart_receive_config(UART_PHY, USART_RECEIVE_ENABLE);
|
||||||
usart_transmit_config(UART_PHY, USART_TRANSMIT_ENABLE);
|
usart_transmit_config(UART_PHY, USART_TRANSMIT_ENABLE);
|
||||||
|
|
||||||
|
#if RS485_MODE == CFG_ENABLE
|
||||||
|
// 配置 RS485 模式
|
||||||
|
usart_rs485_driver_enable(UART_PHY);
|
||||||
|
usart_driver_assertime_config(UART_PHY, 10);
|
||||||
|
usart_driver_deassertime_config(UART_PHY, 10);
|
||||||
|
|
||||||
|
#endif
|
||||||
usart_enable(UART_PHY);
|
usart_enable(UART_PHY);
|
||||||
|
|
||||||
nvic_irq_enable(UART_IRQ, 0);
|
nvic_irq_enable(UART_IRQ, 0);
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
#include "uart_ring_buffer.h"
|
#include "uart_ring_buffer.h"
|
||||||
#include "gd32e23x.h"
|
#include "gd32e23x.h"
|
||||||
|
|
||||||
static volatile uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE];
|
static __IO uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE];
|
||||||
static volatile uint8_t write_index = 0;
|
static __IO uint8_t write_index = 0;
|
||||||
static volatile uint8_t read_index = 0;
|
static __IO uint8_t read_index = 0;
|
||||||
static volatile uint32_t dropped_bytes = 0;
|
static __IO uint32_t dropped_bytes = 0;
|
||||||
|
|
||||||
static inline uint32_t irq_save(void) {
|
static inline uint32_t irq_save(void) {
|
||||||
uint32_t primask = __get_PRIMASK();
|
uint32_t primask = __get_PRIMASK();
|
||||||
@@ -20,7 +20,7 @@ static inline uint32_t irq_save(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void irq_restore(uint32_t primask) {
|
static inline void irq_restore(uint32_t primask) {
|
||||||
if (primask == 0U) {
|
if ((primask & 0x1) == 0) {
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,9 +44,9 @@ static void uart_ring_buffer_reset_state(void) {
|
|||||||
* @ingroup RingBuffer
|
* @ingroup RingBuffer
|
||||||
*/
|
*/
|
||||||
void uart_ring_buffer_init(void) {
|
void uart_ring_buffer_init(void) {
|
||||||
uint32_t irq_key = irq_save();
|
uint32_t primask = irq_save();
|
||||||
uart_ring_buffer_reset_state();
|
uart_ring_buffer_reset_state();
|
||||||
irq_restore(irq_key);
|
irq_restore(primask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,9 +105,9 @@ bool uart_ring_buffer_put(uint8_t data) {
|
|||||||
* @ingroup RingBuffer
|
* @ingroup RingBuffer
|
||||||
*/
|
*/
|
||||||
void uart_ring_buffer_clear(void) {
|
void uart_ring_buffer_clear(void) {
|
||||||
uint32_t irq_key = irq_save();
|
uint32_t primask = irq_save();
|
||||||
uart_ring_buffer_reset_state();
|
uart_ring_buffer_reset_state();
|
||||||
irq_restore(irq_key);
|
irq_restore(primask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,23 +1,61 @@
|
|||||||
# You can change TOOLCHAIN_DIRECTORY if you want to use different toolchain.
|
# The project never stores a compiler package. Each machine supplies a path.
|
||||||
# set(TOOLCHAIN_DIRECTORY "${CMAKE_SOURCE_DIR}/Toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin")
|
# TOOLCHAIN_DIRECTORY (CMake cache) has priority over the environment variable.
|
||||||
|
# GD32_GCC_ENV_VAR lets a workstation use a different variable name if needed.
|
||||||
set(TOOLCHAIN_DIRECTORY "" CACHE PATH "Path to arm-none-eabi toolchain bin directory")
|
set(TOOLCHAIN_DIRECTORY "" CACHE PATH "Path to arm-none-eabi toolchain bin directory")
|
||||||
|
set(GD32_GCC_ENV_VAR "GD32_GCC_BIN" CACHE STRING "Environment variable containing the ARM GCC path")
|
||||||
|
set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES TOOLCHAIN_DIRECTORY GD32_GCC_ENV_VAR)
|
||||||
|
|
||||||
|
if(GD32_GCC_ENV_VAR AND NOT GD32_GCC_ENV_VAR MATCHES "^GD32_[A-Za-z0-9_]+$")
|
||||||
|
message(FATAL_ERROR "GD32_GCC_ENV_VAR must use the GD32_ prefix: ${GD32_GCC_ENV_VAR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TOOLCHAIN_DIRECTORY AND GD32_GCC_ENV_VAR)
|
||||||
|
if(DEFINED ENV{${GD32_GCC_ENV_VAR}} AND NOT "$ENV{${GD32_GCC_ENV_VAR}}" STREQUAL "")
|
||||||
|
file(TO_CMAKE_PATH "$ENV{${GD32_GCC_ENV_VAR}}" TOOLCHAIN_DIRECTORY)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT TOOLCHAIN_DIRECTORY)
|
if(NOT TOOLCHAIN_DIRECTORY)
|
||||||
# Add extra auto-detect paths in this list when using another machine.
|
message(FATAL_ERROR
|
||||||
# Example: "C:/your/path/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
|
"Cannot find ARM GCC toolchain. Set ${GD32_GCC_ENV_VAR} in the machine environment "
|
||||||
set(_TOOLCHAIN_CANDIDATES
|
"or pass -DTOOLCHAIN_DIRECTORY=<toolchain-bin>.")
|
||||||
"D:/toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
|
endif()
|
||||||
"C:/toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
|
|
||||||
"${CMAKE_SOURCE_DIR}/Toolchain/xpack-arm-none-eabi-gcc-11.3.1-1.1/bin"
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach(_candidate IN LISTS _TOOLCHAIN_CANDIDATES)
|
file(TO_CMAKE_PATH "${TOOLCHAIN_DIRECTORY}" TOOLCHAIN_DIRECTORY)
|
||||||
if(EXISTS "${_candidate}/arm-none-eabi-gcc.exe" OR EXISTS "${_candidate}/arm-none-eabi-gcc")
|
get_filename_component(TOOLCHAIN_DIRECTORY "${TOOLCHAIN_DIRECTORY}" ABSOLUTE)
|
||||||
set(TOOLCHAIN_DIRECTORY "${_candidate}")
|
|
||||||
break()
|
if(WIN32)
|
||||||
|
set(TOOLCHAIN_SUFFIX ".exe")
|
||||||
|
else()
|
||||||
|
set(TOOLCHAIN_SUFFIX "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Accept either the package root or its bin directory.
|
||||||
|
if(NOT EXISTS "${TOOLCHAIN_DIRECTORY}/arm-none-eabi-gcc${TOOLCHAIN_SUFFIX}" AND
|
||||||
|
EXISTS "${TOOLCHAIN_DIRECTORY}/bin/arm-none-eabi-gcc${TOOLCHAIN_SUFFIX}")
|
||||||
|
set(TOOLCHAIN_DIRECTORY "${TOOLCHAIN_DIRECTORY}/bin")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_ARM_GCC_EXECUTABLE "${TOOLCHAIN_DIRECTORY}/arm-none-eabi-gcc${TOOLCHAIN_SUFFIX}")
|
||||||
|
|
||||||
|
set(_TOOLCHAIN_BINARIES
|
||||||
|
arm-none-eabi-gcc
|
||||||
|
arm-none-eabi-g++
|
||||||
|
arm-none-eabi-gdb
|
||||||
|
arm-none-eabi-ar
|
||||||
|
arm-none-eabi-ranlib
|
||||||
|
arm-none-eabi-as
|
||||||
|
arm-none-eabi-ld
|
||||||
|
arm-none-eabi-objcopy
|
||||||
|
arm-none-eabi-objdump
|
||||||
|
arm-none-eabi-size
|
||||||
|
)
|
||||||
|
foreach(_binary IN LISTS _TOOLCHAIN_BINARIES)
|
||||||
|
if(NOT EXISTS "${TOOLCHAIN_DIRECTORY}/${_binary}${TOOLCHAIN_SUFFIX}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"ARM GCC toolchain is incomplete; missing ${_binary}${TOOLCHAIN_SUFFIX} in ${TOOLCHAIN_DIRECTORY}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS_DEBUG "")
|
set(CMAKE_C_FLAGS_DEBUG "")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "")
|
set(CMAKE_CXX_FLAGS_DEBUG "")
|
||||||
@@ -30,10 +68,6 @@ set(CMAKE_COLOR_DIAGNOSTICS ON)
|
|||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
set(TOOLCHAIN_SUFFIX ".exe")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_NAME Generic)
|
set(CMAKE_SYSTEM_NAME Generic)
|
||||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
@@ -46,18 +80,45 @@ set(FLAGS "-mcpu=cortex-m23 -std=gnu11 -fstack-usage -
|
|||||||
set(ASM_FLAGS "-x assembler-with-cpp")
|
set(ASM_FLAGS "-x assembler-with-cpp")
|
||||||
set(CPP_FLAGS "-fno-rtti -fno-exceptions -fno-threadsafe-statics")
|
set(CPP_FLAGS "-fno-rtti -fno-exceptions -fno-threadsafe-statics")
|
||||||
|
|
||||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX})
|
set(_REQUESTED_C_COMPILER "${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX}")
|
||||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++${TOOLCHAIN_SUFFIX})
|
if(DEFINED CMAKE_C_COMPILER AND CMAKE_C_COMPILER AND
|
||||||
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX})
|
IS_ABSOLUTE "${CMAKE_C_COMPILER}" AND
|
||||||
|
NOT CMAKE_C_COMPILER STREQUAL "${_REQUESTED_C_COMPILER}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"The build directory is already configured for a different ARM GCC compiler:\n"
|
||||||
|
" cached: ${CMAKE_C_COMPILER}\n"
|
||||||
|
" selected: ${_REQUESTED_C_COMPILER}\n"
|
||||||
|
"Delete the build directory or run CMake Tools 'Delete Cache and Reconfigure'.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER "${_REQUESTED_C_COMPILER}")
|
||||||
|
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++${TOOLCHAIN_SUFFIX}")
|
||||||
|
set(CMAKE_ASM_COMPILER "${TOOLCHAIN_PREFIX}gcc${TOOLCHAIN_SUFFIX}")
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS} ${CPP_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS} ${CPP_FLAGS}")
|
||||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${FLAGS} ${ASM_FLAGS}")
|
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${FLAGS} ${ASM_FLAGS}")
|
||||||
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy${TOOLCHAIN_SUFFIX})
|
set(CMAKE_AR "${TOOLCHAIN_PREFIX}ar${TOOLCHAIN_SUFFIX}")
|
||||||
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size${TOOLCHAIN_SUFFIX})
|
set(CMAKE_RANLIB "${TOOLCHAIN_PREFIX}ranlib${TOOLCHAIN_SUFFIX}")
|
||||||
set(CMAKE_OBJDUMP ${TOOLCHAIN_PREFIX}objdump${TOOLCHAIN_SUFFIX})
|
set(CMAKE_OBJCOPY "${TOOLCHAIN_PREFIX}objcopy${TOOLCHAIN_SUFFIX}")
|
||||||
set(CMAKE_AS ${TOOLCHAIN_PREFIX}as${TOOLCHAIN_SUFFIX})
|
set(CMAKE_SIZE "${TOOLCHAIN_PREFIX}size${TOOLCHAIN_SUFFIX}")
|
||||||
set(CMAKE_LD ${TOOLCHAIN_PREFIX}ld${TOOLCHAIN_SUFFIX})
|
set(CMAKE_OBJDUMP "${TOOLCHAIN_PREFIX}objdump${TOOLCHAIN_SUFFIX}")
|
||||||
|
set(CMAKE_AS "${TOOLCHAIN_PREFIX}as${TOOLCHAIN_SUFFIX}")
|
||||||
|
set(CMAKE_LD "${TOOLCHAIN_PREFIX}ld${TOOLCHAIN_SUFFIX}")
|
||||||
|
set(CMAKE_LINKER "${TOOLCHAIN_PREFIX}ld${TOOLCHAIN_SUFFIX}")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${_ARM_GCC_EXECUTABLE}" --version
|
||||||
|
OUTPUT_VARIABLE _ARM_GCC_VERSION_OUTPUT
|
||||||
|
ERROR_VARIABLE _ARM_GCC_VERSION_ERROR
|
||||||
|
RESULT_VARIABLE _ARM_GCC_VERSION_RESULT
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
if(NOT _ARM_GCC_VERSION_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Unable to execute ${_ARM_GCC_EXECUTABLE}: ${_ARM_GCC_VERSION_ERROR}")
|
||||||
|
endif()
|
||||||
|
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" _ARM_GCC_VERSION "${_ARM_GCC_VERSION_OUTPUT}")
|
||||||
|
message(STATUS "Using ARM GCC ${_ARM_GCC_VERSION} from ${TOOLCHAIN_DIRECTORY}")
|
||||||
|
|
||||||
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf")
|
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf")
|
||||||
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
|
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
|
||||||
|
|||||||
Reference in New Issue
Block a user