Compare commits
24 Commits
39654926be
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b8700ac88b | |||
| 3c54795451 | |||
| 6d8133489b | |||
| 040b9be6b9 | |||
| fd68396b30 | |||
| 23116b7e3d | |||
| 3709d3d284 | |||
| 58ead967ff | |||
| 68d2ce3205 | |||
| 18e6cf26be | |||
| 7dd4268210 | |||
| d93df1d303 | |||
| 8961896c0d | |||
| 9d10e34746 | |||
| a0783abd1a | |||
| a1176112ce | |||
| 8f7f72712c | |||
| 6c9a999c71 | |||
| fbc054d999 | |||
| d2e5789476 | |||
| 4e53f936d8 | |||
| 919a9ed1a7 | |||
| 3334f19eb4 | |||
| 11600e4153 |
@@ -1,4 +1,5 @@
|
||||
/cmake-build-debug/
|
||||
/build/
|
||||
/.idea/
|
||||
/.venv/
|
||||
/lvgl/
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "SDL3"]
|
||||
path = SDL3
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) 启动",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/HW_Lib",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/build",
|
||||
"preLaunchTask": "CMake Build",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "为 gdb 启用整齐打印",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "将反汇编风格设置为 Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"C_Cpp.default.cppStandard": "c++23",
|
||||
"C_Cpp.default.cStandard": "c99",
|
||||
"C_Cpp.default.customConfigurationVariables": {
|
||||
},
|
||||
"C_Cpp.inlayHints.autoDeclarationTypes.enabled": false,
|
||||
"C_Cpp.inlayHints.parameterNames.enabled": true,
|
||||
"files.associations": {
|
||||
"*.dpf": "yaml",
|
||||
"compare": "cpp",
|
||||
"cstdint": "cpp"
|
||||
}
|
||||
}
|
||||
Vendored
+91
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Create Build Directories",
|
||||
"type": "shell",
|
||||
"command": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"mkdir -p build"
|
||||
],
|
||||
"problemMatcher": [],
|
||||
"detail": "Create necessary directories for builds.",
|
||||
"windows": {
|
||||
"command": "cmd.exe",
|
||||
"args": [
|
||||
"/C",
|
||||
"if not exist build (mkdir build)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "CMake Configure",
|
||||
"type": "shell",
|
||||
"command": "cmake",
|
||||
"dependsOn": [
|
||||
"Create Build Directories"
|
||||
],
|
||||
"args": [
|
||||
"-S",
|
||||
".",
|
||||
"-B",
|
||||
"build",
|
||||
"-G",
|
||||
"${input:cmakeGenerator}"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"detail": "Configure the project using CMake."
|
||||
},
|
||||
{
|
||||
"label": "CMake Build",
|
||||
"type": "shell",
|
||||
"command": "cmake",
|
||||
"dependsOn": [
|
||||
"CMake Configure"
|
||||
],
|
||||
"args": [
|
||||
"--build",
|
||||
"build",
|
||||
"--target",
|
||||
"all",
|
||||
"--",
|
||||
"-j${input:threadCount}"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"detail": "Build the project using CMake with parallel compilation."
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"type": "pickString",
|
||||
"id": "cmakeGenerator",
|
||||
"options": [
|
||||
"Ninja",
|
||||
"Unix Makefiles",
|
||||
"MinGW Makefiles",
|
||||
"Xcode"
|
||||
],
|
||||
"default": "Ninja",
|
||||
"description": "The CMake generator to use."
|
||||
},
|
||||
{
|
||||
"type": "promptString",
|
||||
"id": "threadCount",
|
||||
"description": "Number of parallel compilation threads",
|
||||
"default": "8"
|
||||
}
|
||||
]
|
||||
}
|
||||
+22
-7
@@ -6,29 +6,44 @@ SET(CMAKE_CXX_FLAGS "-O3")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++23")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
|
||||
|
||||
file(GLOB DEMO_SUBDIRS "demo/*")
|
||||
file(GLOB DEMO_SUBDIRS "demo/*/")
|
||||
foreach (DEMO_SUBDIR ${DEMO_SUBDIRS})
|
||||
include_directories(${DEMO_SUBDIR})
|
||||
endforeach ()
|
||||
|
||||
#include_directories("demo/tft")
|
||||
|
||||
file(GLOB SIM_SUBDIRS "sim/*")
|
||||
foreach (SIM_SUBDIR ${SIM_SUBDIRS})
|
||||
include_directories(${SIM_SUBDIR})
|
||||
endforeach ()
|
||||
|
||||
file(GLOB LVGL_SUBDIRS "lvgl/demos/*" "lvgl/*" "lvgl/src/*")
|
||||
foreach (LVGL_SUBDIR ${LVGL_SUBDIRS})
|
||||
include_directories(${LVGL_SUBDIR})
|
||||
endforeach ()
|
||||
set(LVGL_ROOT_DIR lvgl)
|
||||
|
||||
include(lvgl/env_support/cmake/custom.cmake)
|
||||
|
||||
include_directories(easyx/include)
|
||||
link_directories(easyx/lib64)
|
||||
file(GLOB_RECURSE SOURCES "demo/*/*.*" "sim/*/*.*" "lvgl/src/*/*.*" "lvgl/demos/*/*.*")
|
||||
|
||||
|
||||
file(GLOB_RECURSE SOURCES "demo/*/*.*" "sim/*/*.*")
|
||||
#message(${SOURCES})
|
||||
add_subdirectory(SDL3 EXCLUDE_FROM_ALL)
|
||||
link_libraries(SDL3::SDL3)
|
||||
|
||||
link_libraries(libeasyx.a libgdi32.a libole32.a)
|
||||
|
||||
add_executable(HW_Lib main.c ${SOURCES})
|
||||
|
||||
#导入库
|
||||
add_subdirectory(lib)
|
||||
|
||||
target_link_libraries(HW_Lib HW_LIB_List HW_LIB_Task HW_LIB_Printf HW_LIB_Utils HW_LIB_Iic
|
||||
HW_LIB_Spi HW_LIB_Key HW_LIB_Oled HW_LIB_Font HW_LIB_Tft
|
||||
HW_LIB_Spi HW_LIB_Key HW_LIB_Oled HW_LIB_Font HW_LIB_Tft lvgl::lvgl HW_LIB_Lui
|
||||
)
|
||||
|
||||
add_custom_command(TARGET HW_Lib POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:SDL3::SDL3>
|
||||
$<TARGET_FILE_DIR:HW_Lib>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Conf.h
|
||||
Purpose : Implementation of SEGGER real-time transfer (RTT) which
|
||||
allows real-time communication on targets which support
|
||||
debugger memory accesses while the CPU is running.
|
||||
Revision: $Rev: 24316 $
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_CONF_H
|
||||
#define SEGGER_RTT_CONF_H
|
||||
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* 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
|
||||
//
|
||||
// Most common case:
|
||||
// Up-channel 0: RTT
|
||||
// Up-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3)
|
||||
#endif
|
||||
//
|
||||
// Most common case:
|
||||
// Down-channel 0: RTT
|
||||
// Down-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3)
|
||||
#endif
|
||||
|
||||
#ifndef BUFFER_SIZE_UP
|
||||
#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k)
|
||||
#endif
|
||||
|
||||
#ifndef BUFFER_SIZE_DOWN
|
||||
#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_MODE_DEFAULT
|
||||
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
|
||||
#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(__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" \
|
||||
); \
|
||||
}
|
||||
#else
|
||||
#define SEGGER_RTT_LOCK()
|
||||
#define SEGGER_RTT_UNLOCK()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR EWARM
|
||||
*/
|
||||
#ifdef __ICCARM__
|
||||
#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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR RX
|
||||
*/
|
||||
#ifdef __ICCRX__
|
||||
#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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR RL78
|
||||
*/
|
||||
#ifdef __ICCRL78__
|
||||
#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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for KEIL ARM
|
||||
*/
|
||||
#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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for TI ARM
|
||||
*/
|
||||
#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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for CCRX
|
||||
*/
|
||||
#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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for embOS Simulation on Windows
|
||||
* (Can also be used for generic RTT locking with embOS)
|
||||
*/
|
||||
#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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* 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
|
||||
|
||||
#endif
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,80 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_MenuApp.c
|
||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
||||
*/
|
||||
|
||||
#define MAIN_C
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
volatile int _Cnt;
|
||||
volatile int _Delay;
|
||||
|
||||
static char r;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*/
|
||||
void main(void) {
|
||||
|
||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
|
||||
do {
|
||||
r = SEGGER_RTT_WaitKey();
|
||||
SEGGER_RTT_Write(0, &r, 1);
|
||||
r++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,108 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_MenuApp.c
|
||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
||||
*/
|
||||
|
||||
#define MAIN_C
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
volatile int _Cnt;
|
||||
volatile int _Delay;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*/
|
||||
void main(void) {
|
||||
int r;
|
||||
int CancelOp;
|
||||
|
||||
do {
|
||||
_Cnt = 0;
|
||||
|
||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
|
||||
SEGGER_RTT_WriteString(0, "Press <1> to continue in blocking mode (Application waits if necessary, no data lost)\r\n");
|
||||
SEGGER_RTT_WriteString(0, "Press <2> to continue in non-blocking mode (Application does not wait, data lost if fifo full)\r\n");
|
||||
do {
|
||||
r = SEGGER_RTT_WaitKey();
|
||||
} while ((r != '1') && (r != '2'));
|
||||
if (r == '1') {
|
||||
SEGGER_RTT_WriteString(0, "\r\nSelected <1>. Configuring RTT and starting...\r\n");
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
|
||||
} else {
|
||||
SEGGER_RTT_WriteString(0, "\r\nSelected <2>. Configuring RTT and starting...\r\n");
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
|
||||
}
|
||||
CancelOp = 0;
|
||||
do {
|
||||
//for (_Delay = 0; _Delay < 10000; _Delay++);
|
||||
SEGGER_RTT_printf(0, "Count: %d. Press <Space> to get back to menu.\r\n", _Cnt++);
|
||||
r = SEGGER_RTT_HasKey();
|
||||
if (r) {
|
||||
CancelOp = (SEGGER_RTT_GetKey() == ' ') ? 1 : 0;
|
||||
}
|
||||
//
|
||||
// Check if user selected to cancel the current operation
|
||||
//
|
||||
if (CancelOp) {
|
||||
SEGGER_RTT_WriteString(0, "Operation cancelled, going back to menu...\r\n");
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
SEGGER_RTT_GetKey();
|
||||
SEGGER_RTT_WriteString(0, "\r\n");
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,155 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_MenuApp.c
|
||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
||||
*/
|
||||
|
||||
#define MAIN_C
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
volatile int _Cnt;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*/
|
||||
void main(void) {
|
||||
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
|
||||
|
||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n");
|
||||
SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n");
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%c, 'S' : %c.\r\n", 'S');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%5c, 'E' : %5c.\r\n", 'E');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-5c, 'G' : %-5c.\r\n", 'G');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%5.3c, 'G' : %-5c.\r\n", 'G');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3c, 'E' : %-5c.\r\n", 'E');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%c, 'R' : %c.\r\n", 'R');
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\" : %s.\r\n", "RTT");
|
||||
SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks.");
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%u, 12345 : %u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+u, 12345 : %+u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3u, 12345 : %.3u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6u, 12345 : %.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3u, 12345 : %6.3u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6u, 12345 : %8.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08u, 12345 : %08u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6u, 12345 : %08.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0u, 12345 : %0u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6u, 12345 : %-.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3u, 12345 : %-6.3u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6u, 12345 : %-8.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08u, 12345 : %-08u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6u, 12345 : %-08.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0u, 12345 : %-0u.\r\n", 12345);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%u, -12345 : %u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+u, -12345 : %+u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3u, -12345 : %.3u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6u, -12345 : %.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3u, -12345 : %6.3u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6u, -12345 : %8.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08u, -12345 : %08u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6u, -12345 : %08.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0u, -12345 : %0u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6u, -12345 : %-.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3u, -12345 : %-6.3u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6u, -12345 : %-8.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08u, -12345 : %-08u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0u, -12345 : %-0u.\r\n", -12345);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%d, -12345 : %d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+d, -12345 : %+d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3d, -12345 : %.3d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6d, -12345 : %.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3d, -12345 : %6.3d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6d, -12345 : %8.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08d, -12345 : %08d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6d, -12345 : %08.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0d, -12345 : %0d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6d, -12345 : %-.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3d, -12345 : %-6.3d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6d, -12345 : %-8.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08d, -12345 : %-08d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0d, -12345 : %-0d.\r\n", -12345);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%x, 0x1234ABC : %x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+x, 0x1234ABC : %+x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3x, 0x1234ABC : %.3x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6x, 0x1234ABC : %.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3x, 0x1234ABC : %6.3x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6x, 0x1234ABC : %8.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08x, 0x1234ABC : %08x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6x, 0x1234ABC : %08.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0x, 0x1234ABC : %0x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6x, 0x1234ABC : %-.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3x, 0x1234ABC : %-6.3x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6x, 0x1234ABC : %-8.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08x, 0x1234ABC : %-08x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0x, 0x1234ABC : %-0x.\r\n", 0x1234ABC);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%p, &_Cnt : %p.\r\n", &_Cnt);
|
||||
|
||||
SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n");
|
||||
do {
|
||||
_Cnt++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,106 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_SpeedTestApp.c
|
||||
Purpose : Sample program for measuring RTT performance.
|
||||
*/
|
||||
|
||||
#include "RTOS.h"
|
||||
#include "BSP.h"
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#include <stdio.h>
|
||||
|
||||
OS_STACKPTR int StackHP[128], StackLP[128]; /* Task stacks */
|
||||
OS_TASK TCBHP, TCBLP; /* Task-control-blocks */
|
||||
|
||||
static void HPTask(void) {
|
||||
while (1) {
|
||||
//
|
||||
// Measure time needed for RTT output
|
||||
// Perform dummy write with 0 characters, so we know the overhead of toggling LEDs and RTT in general
|
||||
//
|
||||
// Set BP here. Then start sampling on scope
|
||||
BSP_ClrLED(0);
|
||||
SEGGER_RTT_Write(0, 0, 0);
|
||||
BSP_SetLED(0);
|
||||
BSP_ClrLED(0);
|
||||
SEGGER_RTT_Write(0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n", 82);
|
||||
BSP_SetLED(0);
|
||||
// Set BP here. Then stop sampling on scope
|
||||
OS_Delay(200);
|
||||
}
|
||||
}
|
||||
|
||||
static void LPTask(void) {
|
||||
while (1) {
|
||||
BSP_ToggleLED(1);
|
||||
OS_Delay (500);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int main(void) {
|
||||
OS_IncDI(); /* Initially disable interrupts */
|
||||
OS_InitKern(); /* Initialize OS */
|
||||
OS_InitHW(); /* Initialize Hardware for OS */
|
||||
BSP_Init(); /* Initialize LED ports */
|
||||
BSP_SetLED(0);
|
||||
/* You need to create at least one task before calling OS_Start() */
|
||||
OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
|
||||
OS_CREATETASK(&TCBLP, "LP Task", LPTask, 50, StackLP);
|
||||
OS_Start(); /* Start multitasking */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
### 脚本自动更新RTT地址并启动
|
||||
|
||||
```powershell
|
||||
param (
|
||||
[string]$projectRoot
|
||||
[string]$projectName
|
||||
)
|
||||
|
||||
# 自动获取 OpenOCD 的路径
|
||||
$openOcdPath = (Get-Command openocd).Source
|
||||
if (-not $openOcdPath) {
|
||||
Write-Host "未找到 OpenOCD,请确保已正确安装并在 PATH 中。"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 获取 OpenOCD 的目录并构建 scriptsPath
|
||||
$openOcdDir = Split-Path (Split-Path $openOcdPath)
|
||||
$scriptsPath = Join-Path $openOcdDir "share/openocd/scripts"
|
||||
|
||||
# 定义文件路径
|
||||
$mapFilePath = Join-Path $projectRoot "cmake-build-debug/$projectName.map"
|
||||
$rttCfgPath = Join-Path $projectRoot "rtt.cfg"
|
||||
|
||||
# 读取 .map 文件内容
|
||||
$content = Get-Content $mapFilePath
|
||||
|
||||
# 使用 Select-String 提取地址
|
||||
$match = $content | Select-String -Pattern '^\s*0x([0-9a-fA-F]+)\s+.*_SEGGER_RTT'
|
||||
|
||||
# 获取地址
|
||||
if ($match) {
|
||||
$address = $match.Matches.Groups[1].Value
|
||||
$newRttLine = "rtt setup 0x$address 1024 ""SEGGER RTT"""
|
||||
|
||||
# 读取 rtt.cfg 内容
|
||||
$rttContent = Get-Content $rttCfgPath
|
||||
|
||||
# 查找并替换旧的 rtt setup 行
|
||||
$updatedContent = $rttContent -replace 'rtt setup 0x[0-9a-fA-F]+ 1024 "SEGGER RTT"', $newRttLine
|
||||
|
||||
# 将更新后的内容写回文件
|
||||
Set-Content $rttCfgPath $updatedContent
|
||||
|
||||
Write-Host "已更新 rtt.cfg 中的 RTT 地址为: 0x$address"
|
||||
|
||||
# 启动 OpenOCD
|
||||
Start-Process -FilePath $openOcdPath -ArgumentList "-s $scriptsPath -f $rttCfgPath" -WorkingDirectory $projectRoot
|
||||
} else {
|
||||
Write-Host "未找到 SEGGER RTT 地址,未进行更新"
|
||||
}
|
||||
```
|
||||
|
||||
### 代码说明:
|
||||
|
||||
1. **获取 OpenOCD 路径**:使用 `Get-Command openocd` 获取 OpenOCD 的可执行文件路径。
|
||||
2. **构建 `scriptsPath`**:
|
||||
- 使用 `Split-Path` 从 `openOcdPath` 中提取目录。
|
||||
- 使用 `Join-Path` 构建 `scriptsPath`,假设脚本目录位于 OpenOCD 安装目录的 `share/openocd/scripts` 子目录下。
|
||||
3. **其他部分**:保持不变,继续读取 `.map` 文件、更新 `rtt.cfg` 文件并启动 OpenOCD。
|
||||
|
||||
### 外部工具的配置
|
||||
|
||||
在 CLion 中配置外部工具以运行此脚本并传递项目根路径作为参数,步骤如下:
|
||||
|
||||
1. **打开 CLion 设置**:
|
||||
- 点击菜单栏的 `File` -> `Settings`(在 macOS 上是 `CLion` -> `Preferences`)。
|
||||
|
||||
2. **添加外部工具**:
|
||||
- 在设置窗口中,找到 `Tools` -> `External Tools`。
|
||||
- 点击右侧的 `+` 按钮以添加新的外部工具。
|
||||
|
||||
3. **配置外部工具**:
|
||||
- **Name**: `Update RTT and Run OpenOCD`
|
||||
- **Program**: `powershell`
|
||||
- **Parameters**:
|
||||
```plaintext
|
||||
-ExecutionPolicy Bypass -File "C:\Users\lydxh\Documents\WindowsPowerShell\UpdateAndRunOpenOCD.ps1" -projectRoot "$ProjectFileDir$" -projectName "$ProjectName$"
|
||||
```
|
||||
- **Working directory**: `$ProjectFileDir$`
|
||||
|
||||
4. **保存配置**:
|
||||
- 点击 `OK` 保存配置。
|
||||
- 关闭设置窗口。
|
||||
|
||||
### 使用方法
|
||||
|
||||
1. 将更新后的 PowerShell 脚本保存为 `UpdateAndRunOpenOCD.ps1`,并放在项目根目录下。
|
||||
2. 在 CLion 中,您可以通过 `Tools` 菜单找到您刚刚创建的 `Update RTT and Run OpenOCD` 工具。
|
||||
3. 点击它以执行脚本,更新 RTT 地址并启动 OpenOCD。
|
||||
4. 终端输入telnet 127.0.0.1 9000即可连接到日志输出
|
||||
@@ -0,0 +1,47 @@
|
||||
param (
|
||||
[string]$projectRoot
|
||||
[string]$projectName
|
||||
)
|
||||
|
||||
# 自动获取 OpenOCD 的路径
|
||||
$openOcdPath = (Get-Command openocd).Source
|
||||
if (-not $openOcdPath) {
|
||||
Write-Host "未找到 OpenOCD,请确保已正确安装并在 PATH 中。"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 获取 OpenOCD 的目录并构建 scriptsPath
|
||||
$openOcdDir = Split-Path (Split-Path $openOcdPath)
|
||||
$scriptsPath = Join-Path $openOcdDir "share/openocd/scripts"
|
||||
|
||||
# 定义文件路径
|
||||
$mapFilePath = Join-Path $projectRoot "cmake-build-debug/$projectName.map"
|
||||
$rttCfgPath = Join-Path $projectRoot "rtt.cfg"
|
||||
|
||||
# 读取 .map 文件内容
|
||||
$content = Get-Content $mapFilePath
|
||||
|
||||
# 使用 Select-String 提取地址
|
||||
$match = $content | Select-String -Pattern '^\s*0x([0-9a-fA-F]+)\s+.*_SEGGER_RTT'
|
||||
|
||||
# 获取地址
|
||||
if ($match) {
|
||||
$address = $match.Matches.Groups[1].Value
|
||||
$newRttLine = "rtt setup 0x$address 1024 ""SEGGER RTT"""
|
||||
|
||||
# 读取 rtt.cfg 内容
|
||||
$rttContent = Get-Content $rttCfgPath
|
||||
|
||||
# 查找并替换旧的 rtt setup 行
|
||||
$updatedContent = $rttContent -replace 'rtt setup 0x[0-9a-fA-F]+ 1024 "SEGGER RTT"', $newRttLine
|
||||
|
||||
# 将更新后的内容写回文件
|
||||
Set-Content $rttCfgPath $updatedContent
|
||||
|
||||
Write-Host "已更新 rtt.cfg 中的 RTT 地址为: 0x$address"
|
||||
|
||||
# 启动 OpenOCD
|
||||
Start-Process -FilePath $openOcdPath -ArgumentList "-s $scriptsPath -f $rttCfgPath" -WorkingDirectory $projectRoot
|
||||
} else {
|
||||
Write-Host "未找到 SEGGER RTT 地址,未进行更新"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
source [find interface/cmsis-dap.cfg]
|
||||
transport select swd
|
||||
source [find target/stm32h7x.cfg]
|
||||
# reset_config none
|
||||
|
||||
|
||||
init
|
||||
#
|
||||
rtt setup 0x24000db0 1024 "SEGGER RTT"
|
||||
rtt start
|
||||
|
||||
rtt server start 9000 0
|
||||
@@ -0,0 +1,35 @@
|
||||
SEGGER Microcontroller GmbH
|
||||
The Embedded Experts
|
||||
|
||||
(c) 1995 - 2021 SEGGER Microcontroller GmbH
|
||||
www.segger.com Support: support@segger.com
|
||||
|
||||
SEGGER RTT Real Time Transfer for embedded targets
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, are permitted provided that the following
|
||||
condition is met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this condition and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
@@ -0,0 +1,25 @@
|
||||
RTT
|
||||
===
|
||||
|
||||
SEGGER RTT Sources
|
||||
|
||||
https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer
|
||||
https://wiki.segger.com/RTT
|
||||
|
||||
## Included files
|
||||
|
||||
* `RTT/`
|
||||
* `SEGGER_RTT.c` - Main module for RTT.
|
||||
* `SEGGER_RTT.h` - Main header for RTT.
|
||||
* `SEGGER_RTT_ASM_ARMv7M.S` - Assembly-optimized implementation of RTT functions for ARMv7M processors.
|
||||
* `SEGGER_RTT_Printf.c` - Simple implementation of printf (`SEGGER_RTT_Printf()`) to write formatted strings
|
||||
via RTT.
|
||||
* `Syscalls/`
|
||||
* `SEGGER_RTT_Syscalls_*.c` - Low-level syscalls to retarget `printf()` to RTT with different toolchains.
|
||||
* `Config/`
|
||||
* `SEGGER_RTT_Conf.h` - RTT configuration file.
|
||||
* `Examples/`
|
||||
* `Main_RTT_InputEchoApp.c` - Example application which echoes input on Channel 0.
|
||||
* `Main_RTT_MenuApp.c` - Example application to demonstrate RTT bi-directional functionality.
|
||||
* `Main_RTT_PrintfTest.c` - Example application to test RTT's simple printf implementation.
|
||||
* `Main_RTT_SpeedTestApp.c` - Example application to measure RTT performance. (Requires embOS)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,513 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT.h
|
||||
Purpose : Implementation of SEGGER real-time transfer which allows
|
||||
real-time communication on targets which support debugger
|
||||
memory accesses while the CPU is running.
|
||||
Revision: $Rev: 25842 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_H
|
||||
#define SEGGER_RTT_H
|
||||
|
||||
#include "SEGGER_RTT_Conf.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__)) // Cortex-A/R 32-bit ARMv7-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__)) // Cortex-A/R 32-bit ARMv7-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__)
|
||||
#if (__CORE__ == __ARM7A__) // Cortex-A 32-bit ARMv7-A
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7R__)
|
||||
#if (__CORE__ == __ARM7R__) // Cortex-R 32-bit ARMv7-R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
// TBD: __ARM8A__ => Cortex-A 64-bit ARMv8-A
|
||||
// TBD: __ARM8R__ => Cortex-R 64-bit ARMv8-R
|
||||
#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,242 @@
|
||||
/*********************************************************************
|
||||
* (c) SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
* www.segger.com *
|
||||
**********************************************************************
|
||||
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : SEGGER_RTT_ASM_ARMv7M.S
|
||||
Purpose : Assembler implementation of RTT functions for ARMv7M
|
||||
|
||||
Additional information:
|
||||
This module is written to be assembler-independent and works with
|
||||
GCC and clang (Embedded Studio) and IAR.
|
||||
*/
|
||||
|
||||
#define SEGGER_RTT_ASM // Used to control processed input from header file
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#define _CCIAR 0
|
||||
#define _CCCLANG 1
|
||||
|
||||
#if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__)
|
||||
#define _CC_TYPE _CCCLANG
|
||||
#define _PUB_SYM .global
|
||||
#define _EXT_SYM .extern
|
||||
#define _END .end
|
||||
#define _WEAK .weak
|
||||
#define _THUMB_FUNC .thumb_func
|
||||
#define _THUMB_CODE .code 16
|
||||
#define _WORD .word
|
||||
#define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax"
|
||||
#define _ALIGN(Exp) .align Exp
|
||||
#define _PLACE_LITS .ltorg
|
||||
#define _DATA_SECT_START
|
||||
#define _C_STARTUP _start
|
||||
#define _STACK_END __stack_end__
|
||||
#define _RAMFUNC
|
||||
//
|
||||
// .text => Link to flash
|
||||
// .fast => Link to RAM
|
||||
// OtherSect => Usually link to RAM
|
||||
// Alignment is 2^x
|
||||
//
|
||||
#elif defined (__IASMARM__)
|
||||
#define _CC_TYPE _CCIAR
|
||||
#define _PUB_SYM PUBLIC
|
||||
#define _EXT_SYM EXTERN
|
||||
#define _END END
|
||||
#define _WEAK _WEAK
|
||||
#define _THUMB_FUNC
|
||||
#define _THUMB_CODE THUMB
|
||||
#define _WORD DCD
|
||||
#define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp)
|
||||
#define _ALIGN(Exp) alignrom Exp
|
||||
#define _PLACE_LITS
|
||||
#define _DATA_SECT_START DATA
|
||||
#define _C_STARTUP __iar_program_start
|
||||
#define _STACK_END sfe(CSTACK)
|
||||
#define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
|
||||
//
|
||||
// .text => Link to flash
|
||||
// .textrw => Link to RAM
|
||||
// OtherSect => Usually link to RAM
|
||||
// NOROOT => Allows linker to throw away the function, if not referenced
|
||||
// Alignment is 2^x
|
||||
//
|
||||
#endif
|
||||
|
||||
#if (_CC_TYPE == _CCIAR)
|
||||
NAME SEGGER_RTT_ASM_ARMv7M
|
||||
#else
|
||||
.syntax unified
|
||||
#endif
|
||||
|
||||
#if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
|
||||
#define SHT_PROGBITS 0x1
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public / external symbols
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
_EXT_SYM __aeabi_memcpy
|
||||
_EXT_SYM __aeabi_memcpy4
|
||||
_EXT_SYM _SEGGER_RTT
|
||||
|
||||
_PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_WriteSkipNoLock
|
||||
*
|
||||
* Function description
|
||||
* Stores a specified number of characters in SEGGER RTT
|
||||
* control block which is then read by the host.
|
||||
* SEGGER_RTT_WriteSkipNoLock does not lock the application and
|
||||
* skips all data, if the data does not fit into the buffer.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
|
||||
* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
|
||||
* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
|
||||
* MUST be > 0!!!
|
||||
* This is done for performance reasons, so no initial check has do be done.
|
||||
*
|
||||
* Return value
|
||||
* 1: Data has been copied
|
||||
* 0: No space, data has not been copied
|
||||
*
|
||||
* Notes
|
||||
* (1) If there is not enough space in the "Up"-buffer, all data is dropped.
|
||||
* (2) For performance reasons this function does not call Init()
|
||||
* and may only be called after RTT has been initialized.
|
||||
* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
|
||||
*/
|
||||
_SECTION(.text, CODE, 2)
|
||||
_ALIGN(2)
|
||||
_THUMB_FUNC
|
||||
SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) {
|
||||
//
|
||||
// Cases:
|
||||
// 1) RdOff <= WrOff => Space until wrap-around is sufficient
|
||||
// 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
|
||||
// 3) RdOff < WrOff => No space in buf
|
||||
// 4) RdOff > WrOff => Space is sufficient
|
||||
// 5) RdOff > WrOff => No space in buf
|
||||
//
|
||||
// 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
|
||||
//
|
||||
// Register usage:
|
||||
// R0 Temporary needed as RdOff, <Tmp> register later on
|
||||
// R1 pData
|
||||
// R2 <NumBytes>
|
||||
// R3 <Tmp> register. Hold free for subroutine calls
|
||||
// R4 <Rem>
|
||||
// R5 pRing->pBuffer
|
||||
// R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN)
|
||||
// R7 WrOff
|
||||
//
|
||||
PUSH {R4-R7}
|
||||
ADD R3,R0,R0, LSL #+1
|
||||
LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex];
|
||||
ADD R0,R0,R3, LSL #+3
|
||||
ADD R6,R0,#+24
|
||||
LDR R0,[R6, #+16] // RdOff = pRing->RdOff;
|
||||
LDR R7,[R6, #+12] // WrOff = pRing->WrOff;
|
||||
LDR R5,[R6, #+4] // pRing->pBuffer
|
||||
CMP R7,R0
|
||||
BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3)
|
||||
//
|
||||
// Handling for case 1, later on identical to case 4
|
||||
//
|
||||
LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
|
||||
SUBS R4,R3,R7 // <Rem> (Used in case we jump into case 2 afterwards)
|
||||
SUBS R3,R4,#+1 // <Avail>
|
||||
CMP R3,R2
|
||||
BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)?
|
||||
_Case4:
|
||||
ADDS R5,R7,R5 // pBuffer += WrOff
|
||||
ADDS R0,R2,R7 // v = WrOff + NumBytes
|
||||
//
|
||||
// 2x unrolling for the copy loop that is used most of the time
|
||||
// This is a special optimization for small SystemView packets and makes them even faster
|
||||
//
|
||||
_ALIGN(2)
|
||||
_LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
||||
LDRB R3,[R1], #+1
|
||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R2,R2,#+1
|
||||
BEQ _CSDone
|
||||
LDRB R3,[R1], #+1
|
||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R2,R2,#+1
|
||||
BNE _LoopCopyStraight
|
||||
_CSDone:
|
||||
#if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here
|
||||
DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the <WrOff> in the struct
|
||||
#endif
|
||||
STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes;
|
||||
MOVS R0,#+1
|
||||
POP {R4-R7}
|
||||
BX LR // Return 1
|
||||
_CheckCase2:
|
||||
ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around
|
||||
CMP R0,R2
|
||||
BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit)
|
||||
//
|
||||
// Handling for case 2
|
||||
//
|
||||
ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value
|
||||
SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer)
|
||||
_LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk
|
||||
LDRB R3,[R1], #+1
|
||||
STRB R3,[R0], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R4,R4,#+1
|
||||
BNE _LoopCopyBeforeWrapAround
|
||||
//
|
||||
// Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
|
||||
// But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
|
||||
// In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
|
||||
// Therefore, check if 2nd memcpy is necessary at all
|
||||
//
|
||||
ADDS R4,R2,#+0 // Save <NumBytes> (needed as counter in loop but must be written to <WrOff> after the loop). Also use this inst to update the flags to skip 2nd loop if possible
|
||||
BEQ.N _No2ChunkNeeded // if (NumBytes) {
|
||||
_LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes);
|
||||
LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop
|
||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R2,R2,#+1
|
||||
BNE _LoopCopyAfterWrapAround
|
||||
_No2ChunkNeeded:
|
||||
#if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here
|
||||
DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the <WrOff> in the struct
|
||||
#endif
|
||||
STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer
|
||||
MOVS R0,#+1
|
||||
POP {R4-R7}
|
||||
BX LR // Return 1
|
||||
_CheckCase4:
|
||||
SUBS R0,R0,R7
|
||||
SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u;
|
||||
CMP R0,R2
|
||||
BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit)
|
||||
_Case3:
|
||||
MOVS R0,#+0
|
||||
POP {R4-R7}
|
||||
BX LR // Return 0
|
||||
_PLACE_LITS
|
||||
|
||||
#endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
|
||||
_END
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,605 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_printf.c
|
||||
Purpose : Replacement for printf to write formatted data via RTT
|
||||
Revision: $Rev: 17697 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.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 NumDigits;
|
||||
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)
|
||||
//
|
||||
NumDigits = 0u;
|
||||
c = *sFormat;
|
||||
if (c == '.')
|
||||
{
|
||||
sFormat++;
|
||||
do
|
||||
{
|
||||
c = *sFormat;
|
||||
if ((c < '0') || (c > '9'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
NumDigits = NumDigits * 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, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'u':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, 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.
|
||||
}
|
||||
do
|
||||
{
|
||||
c = *s;
|
||||
s++;
|
||||
if (c == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
_StoreChar(&BufferDesc, c);
|
||||
}
|
||||
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 ****************************/
|
||||
@@ -0,0 +1,132 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_GCC.c
|
||||
Purpose : Low-level functions for using printf() via RTT in GCC.
|
||||
To use RTT for printf output, include this file in your
|
||||
application.
|
||||
Revision: $Rev: 24316 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) && !(defined __ARMCC_VERSION) && !(defined __CC_ARM)
|
||||
|
||||
#include <reent.h> // required for _write_r
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// If necessary define the _reent struct
|
||||
// to match the one passed by the used standard library.
|
||||
//
|
||||
struct _reent;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
_ssize_t _write (int file, const void *ptr, size_t len);
|
||||
_ssize_t _write_r(struct _reent *r, int file, const void *ptr, size_t len);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _write()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* libc subroutines will use this system routine for output to all files,
|
||||
* including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
_ssize_t _write(int file, const void *ptr, size_t len) {
|
||||
(void) file; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _write_r()
|
||||
*
|
||||
* Function description
|
||||
* Low-level reentrant write function.
|
||||
* libc subroutines will use this system routine for output to all files,
|
||||
* including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
_ssize_t _write_r(struct _reent *r, int file, const void *ptr, size_t len) {
|
||||
(void) file; /* Not used, avoid warning */
|
||||
(void) r; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void _putchar(char character)
|
||||
{
|
||||
SEGGER_RTT_PutChar(0, character);
|
||||
}
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
||||
@@ -0,0 +1,120 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_IAR.c
|
||||
Purpose : Low-level functions for using printf() via RTT in IAR.
|
||||
To use RTT for printf output, include this file in your
|
||||
application and set the Library Configuration to Normal.
|
||||
Revision: $Rev: 24316 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
|
||||
//
|
||||
// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h
|
||||
// shall be used instead. To not break any compatibility with older compiler versions, we have a
|
||||
// version check in here.
|
||||
//
|
||||
#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400))
|
||||
#include <LowLevelIOInterface.h>
|
||||
#else
|
||||
#include <yfuns.h>
|
||||
#endif
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#pragma module_name = "?__write"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* __write()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* Standard library subroutines will use this system routine
|
||||
* for output to all files, including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size) {
|
||||
(void) handle; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __write_buffered()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* Standard library subroutines will use this system routine
|
||||
* for output to all files, including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) {
|
||||
(void) handle; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
||||
@@ -0,0 +1,405 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : RTT_Syscalls_KEIL.c
|
||||
Purpose : Retargeting module for KEIL MDK-CM3.
|
||||
Low-level functions for using printf() via RTT
|
||||
Revision: $Rev: 29653 $
|
||||
Notes : (1) https://wiki.segger.com/Keil_MDK-ARM#RTT_in_uVision
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __CC_ARM) || (defined __ARMCC_VERSION)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rt_sys.h>
|
||||
#include <rt_misc.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
/*********************************************************************
|
||||
*
|
||||
* #pragmas
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#if __ARMCC_VERSION < 6000000
|
||||
#pragma import(__use_no_semihosting)
|
||||
#endif
|
||||
|
||||
#ifdef _MICROLIB
|
||||
#pragma import(__use_full_stdio)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines non-configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/* Standard IO device handles - arbitrary, but any real file system handles must be
|
||||
less than 0x8000. */
|
||||
#define STDIN 0x8001 // Standard Input Stream
|
||||
#define STDOUT 0x8002 // Standard Output Stream
|
||||
#define STDERR 0x8003 // Standard Error Stream
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public const
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#if __ARMCC_VERSION < 5000000
|
||||
//const char __stdin_name[] = "STDIN";
|
||||
const char __stdout_name[] = "STDOUT";
|
||||
const char __stderr_name[] = "STDERR";
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _ttywrch
|
||||
*
|
||||
* Function description:
|
||||
* Outputs a character to the console
|
||||
*
|
||||
* Parameters:
|
||||
* c - character to output
|
||||
*
|
||||
*/
|
||||
void _ttywrch(int c) {
|
||||
fputc(c, stdout); // stdout
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_open
|
||||
*
|
||||
* Function description:
|
||||
* Opens the device/file in order to do read/write operations
|
||||
*
|
||||
* Parameters:
|
||||
* sName - sName of the device/file to open
|
||||
* OpenMode - This parameter is currently ignored
|
||||
*
|
||||
* Return value:
|
||||
* != 0 - Handle to the object to open, otherwise
|
||||
* == 0 -"device" is not handled by this module
|
||||
*
|
||||
*/
|
||||
FILEHANDLE _sys_open(const char * sName, int OpenMode) {
|
||||
(void)OpenMode;
|
||||
// Register standard Input Output devices.
|
||||
if (strcmp(sName, __stdout_name) == 0) {
|
||||
return (STDOUT);
|
||||
} else if (strcmp(sName, __stderr_name) == 0) {
|
||||
return (STDERR);
|
||||
} else
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_close
|
||||
*
|
||||
* Function description:
|
||||
* Closes the handle to the open device/file
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* 0 - device/file closed
|
||||
*
|
||||
*/
|
||||
int _sys_close(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return 0; // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_write
|
||||
*
|
||||
* Function description:
|
||||
* Writes the data to an open handle.
|
||||
* Currently this function only outputs data to the console
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* pBuffer - Pointer to the data that shall be written
|
||||
* NumBytes - Number of bytes to write
|
||||
* Mode - The Mode that shall be used
|
||||
*
|
||||
* Return value:
|
||||
* Number of bytes *not* written to the file/device
|
||||
*
|
||||
*/
|
||||
int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
||||
int r = 0;
|
||||
|
||||
(void)Mode;
|
||||
if (hFile == STDOUT) {
|
||||
SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes);
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_istty
|
||||
*
|
||||
* Function description:
|
||||
* This function shall return whether the opened file
|
||||
* is a console device or not.
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* 1 - Device is a console
|
||||
* 0 - Device is not a console
|
||||
*
|
||||
*/
|
||||
int _sys_istty(FILEHANDLE hFile) {
|
||||
if (hFile > 0x8000) {
|
||||
return (1);
|
||||
}
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_seek
|
||||
*
|
||||
* Function description:
|
||||
* Seeks via the file to a specific position
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* Pos -
|
||||
*
|
||||
* Return value:
|
||||
* int -
|
||||
*
|
||||
*/
|
||||
int _sys_seek(FILEHANDLE hFile, long Pos) {
|
||||
(void)hFile;
|
||||
(void)Pos;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_flen
|
||||
*
|
||||
* Function description:
|
||||
* Returns the length of the opened file handle
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* Length of the file
|
||||
*
|
||||
*/
|
||||
long _sys_flen(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
#if (__ARMCC_VERSION <= 6000000) // The following functions are not required to be implemented for CC version > 6.
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_read
|
||||
*
|
||||
* Function description:
|
||||
* Reads data from an open handle.
|
||||
* Currently this modules does nothing.
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* pBuffer - Pointer to buffer to store the read data
|
||||
* NumBytes - Number of bytes to read
|
||||
* Mode - The Mode that shall be used
|
||||
*
|
||||
* Return value:
|
||||
* Number of bytes read from the file/device
|
||||
*
|
||||
*/
|
||||
int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
||||
(void)hFile;
|
||||
(void)pBuffer;
|
||||
(void)NumBytes;
|
||||
(void)Mode;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_ensure
|
||||
*
|
||||
* Function description:
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* int -
|
||||
*
|
||||
*/
|
||||
int _sys_ensure(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return (-1); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_tmpnam
|
||||
*
|
||||
* Function description:
|
||||
* This function converts the file number fileno for a temporary
|
||||
* file to a unique filename, for example, tmp0001.
|
||||
*
|
||||
* Parameters:
|
||||
* pBuffer - Pointer to a buffer to store the name
|
||||
* FileNum - file number to convert
|
||||
* MaxLen - Size of the buffer
|
||||
*
|
||||
* Return value:
|
||||
* 1 - Error
|
||||
* 0 - Success
|
||||
*
|
||||
*/
|
||||
#if __ARMCC_VERSION >= 6190000
|
||||
void _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) {
|
||||
(void)pBuffer;
|
||||
(void)FileNum;
|
||||
(void)MaxLen;
|
||||
return; // Not implemented
|
||||
}
|
||||
#else
|
||||
int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) {
|
||||
(void)pBuffer;
|
||||
(void)FileNum;
|
||||
(void)MaxLen;
|
||||
return (1); // Not implemented
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_command_string
|
||||
*
|
||||
* Function description:
|
||||
* This function shall execute a system command.
|
||||
*
|
||||
* Parameters:
|
||||
* cmd - Pointer to the command string
|
||||
* len - Length of the string
|
||||
*
|
||||
* Return value:
|
||||
* == NULL - Command was not successfully executed
|
||||
* == sCmd - Command was passed successfully
|
||||
*
|
||||
*/
|
||||
char * _sys_command_string(char * cmd, int len) {
|
||||
(void)len;
|
||||
return cmd; // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_exit
|
||||
*
|
||||
* Function description:
|
||||
* This function is called when the application returns from main
|
||||
*
|
||||
* Parameters:
|
||||
* ReturnCode - Return code from the main function
|
||||
*
|
||||
*
|
||||
*/
|
||||
void _sys_exit(int ReturnCode) {
|
||||
(void)ReturnCode;
|
||||
while (1); // Not implemented
|
||||
}
|
||||
|
||||
#if __ARMCC_VERSION >= 5000000
|
||||
/*********************************************************************
|
||||
*
|
||||
* stdout_putchar
|
||||
*
|
||||
* Function description:
|
||||
* Put a character to the stdout
|
||||
*
|
||||
* Parameters:
|
||||
* ch - Character to output
|
||||
*
|
||||
*
|
||||
*/
|
||||
int stdout_putchar(int ch) {
|
||||
(void)ch;
|
||||
return ch; // Not implemented
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #if __ARMCC_VERSION <= 6000000
|
||||
#endif // #if (defined __CC_ARM) || (defined __ARMCC_VERSION)
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,252 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.98i *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_SES.c
|
||||
Purpose : Reimplementation of printf, puts and __getchar using RTT
|
||||
in SEGGER Embedded Studio.
|
||||
To use RTT for printf output, include this file in your
|
||||
application.
|
||||
Revision: $Rev: 24316 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM)
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "limits.h"
|
||||
#include "__libc.h"
|
||||
#include "__vfprintf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// Select string formatting implementation.
|
||||
//
|
||||
// RTT printf formatting
|
||||
// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h)
|
||||
// - No maximum string length.
|
||||
// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c)
|
||||
// Standard library printf formatting
|
||||
// - Configurable formatting capabilities.
|
||||
// - Full conversion specifier and flag support.
|
||||
// - Maximum string length has to be known or (slightly) slower character-wise output.
|
||||
//
|
||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting
|
||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting
|
||||
//
|
||||
#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING
|
||||
#define PRINTF_USE_SEGGER_RTT_FORMATTING 0
|
||||
#endif
|
||||
//
|
||||
// If using standard library formatting,
|
||||
// select maximum output string buffer size or character-wise output.
|
||||
//
|
||||
// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output
|
||||
// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length
|
||||
//
|
||||
#ifndef PRINTF_BUFFER_SIZE
|
||||
#define PRINTF_BUFFER_SIZE 128
|
||||
#endif
|
||||
|
||||
#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string using RTT and SEGGER RTT formatting.
|
||||
*/
|
||||
int printf(const char *fmt,...) {
|
||||
int n;
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
n = SEGGER_RTT_vprintf(0, fmt, &args);
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Static functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
static int _putchar(int x, __printf_tag_ptr ctx) {
|
||||
(void)ctx;
|
||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string character-wise, using RTT and standard
|
||||
* library formatting.
|
||||
*/
|
||||
int printf(const char *fmt, ...) {
|
||||
int n;
|
||||
va_list args;
|
||||
__printf_t iod;
|
||||
|
||||
va_start(args, fmt);
|
||||
iod.string = 0;
|
||||
iod.maxchars = INT_MAX;
|
||||
iod.output_fn = _putchar;
|
||||
SEGGER_RTT_LOCK();
|
||||
n = __vfprintf(&iod, fmt, args);
|
||||
SEGGER_RTT_UNLOCK();
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
#else // Use standard library formatting with static buffer
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string using RTT and standard library formatting.
|
||||
*/
|
||||
int printf(const char *fmt,...) {
|
||||
int n;
|
||||
char aBuffer[PRINTF_BUFFER_SIZE];
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args);
|
||||
if (n > (int)sizeof(aBuffer)) {
|
||||
SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer));
|
||||
} else if (n > 0) {
|
||||
SEGGER_RTT_Write(0, aBuffer, n);
|
||||
}
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* puts()
|
||||
*
|
||||
* Function description
|
||||
* print a string using RTT.
|
||||
*/
|
||||
int puts(const char *s) {
|
||||
return SEGGER_RTT_WriteString(0, s);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __putchar()
|
||||
*
|
||||
* Function description
|
||||
* Write one character via RTT.
|
||||
*/
|
||||
int __putchar(int x, __printf_tag_ptr ctx) {
|
||||
(void)ctx;
|
||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __getchar()
|
||||
*
|
||||
* Function description
|
||||
* Wait for and get a character via RTT.
|
||||
*/
|
||||
int __getchar() {
|
||||
return SEGGER_RTT_WaitKey();
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
||||
Submodule
+1
Submodule SDL3 added at 89c6bc5f50
+1
-1
@@ -5,6 +5,6 @@
|
||||
#ifndef HW_LIB_T_ARG_H
|
||||
#define HW_LIB_T_ARG_H
|
||||
|
||||
void Test_argpase();
|
||||
int Test_argpase(void *pVoid);
|
||||
|
||||
#endif //HW_LIB_T_ARG_H
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ Option Opts[6] = {{"T0", T0},
|
||||
{"T4", T4},
|
||||
{"T5", T5}};
|
||||
|
||||
void Test_argpase() {
|
||||
int Test_argpase(void *pVoid) {
|
||||
OptList *Head = Options_Creat("Head", -1);
|
||||
OptList *t;
|
||||
int i;
|
||||
@@ -46,4 +46,4 @@ void Test_argpase() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,6 +5,6 @@
|
||||
#ifndef HW_LIB_T_IIC_H
|
||||
#define HW_LIB_T_IIC_H
|
||||
|
||||
void Test_iic();
|
||||
int Test_iic(void *pVoid);
|
||||
|
||||
#endif //HW_LIB_T_IIC_H
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ uint8_t SDA_Read() {
|
||||
return l;
|
||||
}
|
||||
|
||||
void Test_iic() {
|
||||
int Test_iic(void *pVoid) {
|
||||
SW_Dev_IIC dev = {
|
||||
.CLK_SET = CLK_Pin,
|
||||
.SDA_SET = SDA_Set,
|
||||
@@ -57,4 +57,4 @@ void Test_iic() {
|
||||
SW_IIC_WL(dev, internalAddress, writeData, len);
|
||||
SW_IIC_RL(dev, internalAddress, readData, len, 1);
|
||||
BufPrint("<IIC> RX", readData, TYPE_T(readData), len, 16);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#ifndef HW_LIB_T_KEY_H
|
||||
#define HW_LIB_T_KEY_H
|
||||
|
||||
void Test_Key();
|
||||
int Test_Key(void *pVoid);
|
||||
|
||||
#endif //HW_LIB_T_KEY_H
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ void Key_Call(Key_t *key) {
|
||||
}
|
||||
}
|
||||
|
||||
void Test_Key() {
|
||||
int Test_Key(void *pVoid) {
|
||||
Key_t k1, k2, k3, k4, k5, k6, ks;
|
||||
key_init(&k1, SIM_KEY_UP, 1, SIM_Key_UP);
|
||||
key_init(&k2, SIM_KEY_DOWN, 1, SIM_Key_DOWN);
|
||||
@@ -61,4 +61,4 @@ void Test_Key() {
|
||||
key_ticks();
|
||||
Sleep(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -5,7 +5,9 @@
|
||||
#ifndef HW_LIB_T_LIST_H
|
||||
#define HW_LIB_T_LIST_H
|
||||
|
||||
extern void Test_List();
|
||||
extern int Test_List(void *pVoid);
|
||||
|
||||
extern void Test_Queue();
|
||||
extern int Test_Queue(void *pVoid1);
|
||||
|
||||
extern int Test_Hash(void* pVoid);
|
||||
#endif //HW_LIB_T_LIST_H
|
||||
|
||||
+17
-3
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "list.h"
|
||||
#include "queue.h"
|
||||
#include "hash_table.h"
|
||||
|
||||
typedef struct test {
|
||||
int val1;
|
||||
@@ -38,7 +39,7 @@ void print(List_t *list) {
|
||||
}
|
||||
}
|
||||
|
||||
void Test_List() {
|
||||
int Test_List(void *pVoid) {
|
||||
List_t list;
|
||||
list_init(&list); // 初始化链表
|
||||
|
||||
@@ -100,9 +101,10 @@ void Test_List() {
|
||||
// 测试销毁操作
|
||||
printf("-----destroy----\n");
|
||||
list_destroy(&list, NULL); // 销毁链表
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Test_Queue() {
|
||||
int Test_Queue(void *pVoid) {
|
||||
Queue_List_t *deque = newQueue_List(sizeof(int)); // 创建一个int类型的双端队列
|
||||
|
||||
// 测试入队操作
|
||||
@@ -141,4 +143,16 @@ void Test_Queue() {
|
||||
printf("Pop value from front: %d\n", *popVal);
|
||||
}
|
||||
delQueue_List(deque);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Test_Hash(void* pVoid) {
|
||||
Hash_Table_t* ht = ht_new();
|
||||
ht_insert(ht, "name", "lydxh");
|
||||
ht_insert(ht, "age", "18");
|
||||
printf("Name:%s\nAge:%s", ht_search(ht, "name"), ht_search(ht, "age"));
|
||||
ht_delete(ht, "name");
|
||||
ht_delete(ht, "age");
|
||||
ht_del_hash_table(ht);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by lydxh on 2024/5/10.
|
||||
//
|
||||
|
||||
#ifndef HW_LIB_T_LVGL_H
|
||||
#define HW_LIB_T_LVGL_H
|
||||
|
||||
int Test_lvgl(void *pVoid);
|
||||
|
||||
#endif //HW_LIB_T_LVGL_H
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "stdio.h"
|
||||
#include "lv_port_disp.h"
|
||||
#include "lv_port_indev.h"
|
||||
#include "lvgl.h"
|
||||
#include "demos/lv_demos.h"
|
||||
#include <windows.h>
|
||||
//#include <widgets/lv_demo_widgets.h>
|
||||
#include "t_lvgl.h"
|
||||
#include "SDL3/SDL.h"
|
||||
|
||||
static void btn_event_cb(lv_event_t *e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t *btn = lv_event_get_target(e);
|
||||
if (code == LV_EVENT_CLICKED) {
|
||||
static uint8_t cnt = 0;
|
||||
cnt++;
|
||||
|
||||
/*Get the first child of the button which is the label and change its text*/
|
||||
lv_obj_t *label = lv_obj_get_child(btn, 0);
|
||||
lv_label_set_text_fmt(label, "Button: %d", cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a button with a label and react on click event.
|
||||
*/
|
||||
void lv_example_get_started_1(void) {
|
||||
lv_obj_t *btn = lv_btn_create(lv_scr_act()); /*Add a button the current screen*/
|
||||
lv_obj_set_pos(btn, 10, 10); /*Set its position*/
|
||||
lv_obj_set_size(btn, 120, 50); /*Set its size*/
|
||||
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL); /*Assign a callback to the button*/
|
||||
|
||||
lv_obj_t *label = lv_label_create(btn); /*Add a label to the button*/
|
||||
lv_label_set_text(label, "Button"); /*Set the labels text*/
|
||||
lv_obj_center(label);
|
||||
}
|
||||
|
||||
int Test_lvgl(void *pVoid) {
|
||||
lv_init();
|
||||
lv_port_disp_init();
|
||||
// lv_port_indev_init();
|
||||
|
||||
// lv_example_get_started_1();
|
||||
// lv_demo_widgets();
|
||||
// printf("\nTEST Widgets\n");
|
||||
|
||||
while (1) {
|
||||
/* Periodically call the lv_task handler.
|
||||
* It could be done in a timer interrupt or an OS task too.*/
|
||||
lv_timer_handler();
|
||||
lv_tick_inc(5);
|
||||
SDL_Delay(5);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#ifndef HW_LIB_T_OLED_H
|
||||
#define HW_LIB_T_OLED_H
|
||||
|
||||
void Test_OLED();
|
||||
int Test_OLED(void *pVoid);
|
||||
|
||||
#endif //HW_LIB_T_OLED_H
|
||||
|
||||
+42
-44
@@ -9,33 +9,33 @@
|
||||
#include "sim_key.h"
|
||||
#include "page.h"
|
||||
|
||||
uint8_t Cmd(uint8_t *data, size_t l) {
|
||||
// Buf_Print("Cmd", data, l, 16);
|
||||
uint8_t Cmd(uint8_t* data, size_t l) {
|
||||
// Buf_Print("Cmd", data, l, 16);
|
||||
}
|
||||
|
||||
uint8_t Data(uint8_t *data, size_t l) {
|
||||
// Buf_Print("Data", data, l, 16);
|
||||
uint8_t Data(uint8_t* data, size_t l) {
|
||||
// Buf_Print("Data", data, l, 16);
|
||||
}
|
||||
|
||||
void Refresh_Call(OLED_T *dev) {
|
||||
// LOGT("OLED", "CALL");
|
||||
// Buf_Print("Buf", dev->buf, dev->width * (dev->height / 8), 128);
|
||||
void Refresh_Call(OLED_T* dev) {
|
||||
// LOGT("OLED", "CALL");
|
||||
// Buf_Print("Buf", dev->buf, dev->width * (dev->height / 8), 128);
|
||||
SIM_OLED_DrawFromBuffer(dev->buf, dev->width, dev->height / 8);
|
||||
}
|
||||
|
||||
uint8_t oledbuf[8][128] = {0};
|
||||
|
||||
void Key_Call_E(Key_t *key) {
|
||||
void Key_Call_E(Key_t* key) {
|
||||
switch (key->event) {
|
||||
case KEY_PRESS_DOWN:
|
||||
// LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "PressTheEvent");
|
||||
break;// 按下事件
|
||||
// LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "PressTheEvent");
|
||||
break; // 按下事件
|
||||
case KEY_PRESS_UP:
|
||||
// LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "BounceIncident");
|
||||
break;// 弹起事件
|
||||
// LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "BounceIncident");
|
||||
break; // 弹起事件
|
||||
case KEY_PRESS_REPEAT:
|
||||
LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "RepeatThePressEvent");
|
||||
break;// 重复按下事件
|
||||
break; // 重复按下事件
|
||||
case KEY_SINGLE_CLICK:
|
||||
LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "ClickEvent");
|
||||
if (key->key_id == SIM_KEY_UP)cur--;
|
||||
@@ -57,25 +57,25 @@ void Key_Call_E(Key_t *key) {
|
||||
if (cur == pagesearch(pageid).curmax)pageid = 0;
|
||||
break;
|
||||
case 4:
|
||||
if(cnt_f==1)cnt_f=0;
|
||||
else cnt_f=1;
|
||||
if (cnt_f == 1)cnt_f = 0;
|
||||
else cnt_f = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;// 单击事件
|
||||
break; // 单击事件
|
||||
case KEY_DOUBLE_CLICK:
|
||||
LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "DoubleClickTheEvent");
|
||||
break;// 双击事件
|
||||
break; // 双击事件
|
||||
case KEY_LONG_PRESS_START:
|
||||
// LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "LongPressToStartTheEvent");
|
||||
break;// 长按开始事件
|
||||
// LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "LongPressToStartTheEvent");
|
||||
break; // 长按开始事件
|
||||
case KEY_LONG_PRESS_HOLD:
|
||||
LOGT("KEY", "ID:%d EVENT:%s", key->key_id, "LongPressToHoldTheEvent");
|
||||
break;// 长按保持事件
|
||||
break; // 长按保持事件
|
||||
}
|
||||
}
|
||||
|
||||
void Get_Key(void *pVoid) {
|
||||
void Get_Key(void* pVoid) {
|
||||
Key_t k1, k2, k3, k4, k5, k6, k7;
|
||||
key_init(&k1, SIM_KEY_UP, 1, SIM_Key_UP);
|
||||
key_init(&k2, SIM_KEY_DOWN, 1, SIM_Key_DOWN);
|
||||
@@ -102,24 +102,22 @@ void Get_Key(void *pVoid) {
|
||||
}
|
||||
|
||||
OLED_T oled = {
|
||||
.height=64,
|
||||
.width=128,
|
||||
.state=IDLE,
|
||||
.buf=oledbuf,
|
||||
.cmd=Cmd,
|
||||
.data=Data,
|
||||
.call=Refresh_Call,
|
||||
.height = 64,
|
||||
.width = 128,
|
||||
.state = IDLE,
|
||||
.buf = oledbuf[0],
|
||||
.cmd = Cmd,
|
||||
.data = Data,
|
||||
.call = Refresh_Call,
|
||||
};
|
||||
|
||||
void Test_OLED() {
|
||||
int Test_OLED(void* pVoid) {
|
||||
SIM_OLED_INIT(128, 64, CYAN, 0x0, 5, 0);
|
||||
|
||||
SIM_OLED_START();
|
||||
|
||||
OLED_Init(&oled);
|
||||
OLED_CLS(&oled);
|
||||
|
||||
OLED_ShowCHString(&oled, 1, 24, "姓名学号:2233");
|
||||
OLED_ShowCHString(&oled, 1, 1, "星海科技机械师");
|
||||
|
||||
OLED_DrawRect(&oled, 0, 0, 127, 63);
|
||||
|
||||
@@ -127,22 +125,22 @@ void Test_OLED() {
|
||||
|
||||
Sleep(3000);
|
||||
|
||||
// extern lv_font_t myFont;
|
||||
// OLED_DisplayString(&oled, &myFont, "班级", 2, 1);
|
||||
// extern lv_font_t myFont;
|
||||
// OLED_DisplayString(&oled, &myFont, "班级", 2, 1);
|
||||
|
||||
// OLED_ShowPic(&oled, 0, 0, 64, 64, BMP1);
|
||||
// OLED_ShowPic(&oled, 0, 0, 64, 64, BMP1);
|
||||
OLED_Refresh(&oled);
|
||||
_beginthread(Get_Key, 0, NULL);
|
||||
pageinit();
|
||||
// pageinit();
|
||||
while (1) {
|
||||
if (pageid > 4)pageid = 0;
|
||||
item_h = pagesearch(pageid).item_h;
|
||||
item_w = pagesearch(pageid).item_w;
|
||||
// pagesearch(pageid).page(&oled);
|
||||
// sprintf(buf, "DATA:%d", s);
|
||||
// OLED_ShowString(&oled, 2, 51, buf, 12);
|
||||
OLED_Refresh(&oled);
|
||||
// if (pageid > 4)pageid = 0;
|
||||
// item_h = pagesearch(pageid).item_h;
|
||||
// item_w = pagesearch(pageid).item_w;
|
||||
//// pagesearch(pageid).page(&oled);
|
||||
//// sprintf(buf, "DATA:%d", s);
|
||||
//// OLED_ShowString(&oled, 2, 51, buf, 12);
|
||||
// OLED_Refresh(&oled);
|
||||
Sleep(200);
|
||||
}
|
||||
SIM_OLED_STOP();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
#define __TEST_CLASS_CLASS_IMPLEMENT__
|
||||
|
||||
#include "test_class.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef ASSERT
|
||||
#define ASSERT(...) assert(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#undef this
|
||||
#define this (*ptThis)
|
||||
|
||||
const i_test_class_t TEST_CLASS = {
|
||||
.Init = &test_class_init,
|
||||
.Depose = &test_class_depose,
|
||||
|
||||
/* other methods */
|
||||
};
|
||||
|
||||
|
||||
/*! \brief the constructor of the class: test_class */
|
||||
test_class_t *test_class_init(test_class_t *ptObj, test_class_cfg_t *ptCFG) {
|
||||
/* initialise "this" (i.e. ptThis) to access class members */
|
||||
class_internal(ptObj, ptThis, test_class_t);
|
||||
|
||||
ASSERT(NULL != ptObj && NULL != ptCFG);
|
||||
|
||||
return ptObj;
|
||||
}
|
||||
|
||||
/*! \brief the destructor of the class: test_class */
|
||||
void test_class_depose(test_class_t *ptObj) {
|
||||
/* initialise "this" (i.e. ptThis) to access class members */
|
||||
class_internal(ptObj, ptThis, test_class_t);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*! \brief a method only visible for current class and derived class */
|
||||
void test_class_protected_method_example1(test_class_t *ptObj) {
|
||||
/* initialise "this" (i.e. ptThis) to access class members */
|
||||
class_internal(ptObj, ptThis, test_class_t);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*! \brief a method only visible for current class and derived class */
|
||||
void test_class_protected_method_example2(test_class_t *ptObj) {
|
||||
/* initialise "this" (i.e. ptThis) to access class members */
|
||||
class_internal(ptObj, ptThis, test_class_t);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef __TEST_CLASS_H__
|
||||
#define __TEST_CLASS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \NOTE: Make sure #include "plooc_class.h" is close to the class definition
|
||||
*/
|
||||
#if defined(__TEST_CLASS_CLASS_IMPLEMENT__)
|
||||
#define __PLOOC_CLASS_IMPLEMENT__
|
||||
#elif defined(__TEST_CLASS_CLASS_INHERIT__)
|
||||
#define __PLOOC_CLASS_INHERIT__
|
||||
#endif
|
||||
|
||||
#include "plooc_class.h"
|
||||
|
||||
|
||||
//! \name class test_class_t
|
||||
//! @{
|
||||
declare_class(test_class_t)
|
||||
def_class(test_class_t,
|
||||
public_member(
|
||||
//!< place your public members here
|
||||
)
|
||||
private_member(
|
||||
//!< place your private members here
|
||||
)
|
||||
protected_member(
|
||||
//!< place your protected members here
|
||||
)
|
||||
)
|
||||
end_def_class(test_class_t) /* do not remove this for forward compatibility */
|
||||
//! @}
|
||||
|
||||
typedef struct test_class_cfg_t {
|
||||
|
||||
//! put your configuration members here
|
||||
|
||||
} test_class_cfg_t;
|
||||
|
||||
//! \name interface i_test_class_t
|
||||
//! @{
|
||||
def_interface(i_test_class_t)
|
||||
test_class_t *(*Init)(test_class_t *ptObj, test_class_cfg_t *ptCFG);
|
||||
|
||||
void (*Depose)(test_class_t *ptObj);
|
||||
/* other methods */
|
||||
|
||||
end_def_interface(i_test_class_t) /*do not remove this for forward compatibility */
|
||||
//! @}
|
||||
|
||||
extern const i_test_class_t TEST_CLASS;
|
||||
|
||||
/*! \brief the constructor of the class: test_class */
|
||||
extern test_class_t *test_class_init(test_class_t *ptObj, test_class_cfg_t *ptCFG);
|
||||
|
||||
/*! \brief the destructor of the class: test_class */
|
||||
extern void test_class_depose(test_class_t *ptObj);
|
||||
|
||||
protected_method(
|
||||
/*! \brief a method only visible for current class and derived class */
|
||||
extern void test_class_protected_method_example1(test_class_t *ptObj);
|
||||
/*! \brief a method only visible for current class and derived class */
|
||||
extern void test_class_protected_method_example2(test_class_t *ptObj);
|
||||
)
|
||||
|
||||
/*! \note it is very important to undef those macros */
|
||||
#undef __TEST_CLASS_CLASS_INHERIT__
|
||||
#undef __TEST_CLASS_CLASS_IMPLEMENT__
|
||||
|
||||
#endif
|
||||
+2
-1
@@ -4,5 +4,6 @@
|
||||
|
||||
#ifndef HW_LIB_T_SPI_H
|
||||
#define HW_LIB_T_SPI_H
|
||||
void Test_spi();
|
||||
|
||||
int Test_spi(void *pVoid);
|
||||
#endif //HW_LIB_T_SPI_H
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ uint8_t Miso_Pin() {
|
||||
return l;
|
||||
}
|
||||
|
||||
void Test_spi() {
|
||||
int Test_spi(void *pVoid) {
|
||||
SW_Dev_Spi ltl = {
|
||||
.MOSI_SET=Mosi_Pin,
|
||||
.SCK_SET=Sck_Pin,
|
||||
@@ -59,4 +59,4 @@ void Test_spi() {
|
||||
SW_SPI_RWL16(ltl, rbuf16, tbuf16, 64);
|
||||
BufPrint("<SPI> TX[16]", tbuf16, TYPE_T(tbuf16), 64, 16);
|
||||
BufPrint("<SPI> RX[16]", rbuf16, TYPE_T(rbuf16), 64, 16);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,6 +5,6 @@
|
||||
#ifndef HW_LIB_T_TASK_H
|
||||
#define HW_LIB_T_TASK_H
|
||||
|
||||
_Noreturn void Test_task();
|
||||
_Noreturn int Test_task(void *pVoid);
|
||||
|
||||
#endif //HW_LIB_T_TASK_H
|
||||
|
||||
+19
-12
@@ -1,6 +1,7 @@
|
||||
#include <sysinfoapi.h>
|
||||
#include "stdio.h"
|
||||
#include "task.h"
|
||||
#include "log.h"
|
||||
|
||||
Task_t *task1;
|
||||
Task_t *task2;
|
||||
@@ -34,23 +35,29 @@ typedef struct CustomUserData {
|
||||
void exampleTimer4Callback(Task_t *task, void *userData) {
|
||||
CustomUserData *customUserData = (CustomUserData *) userData;
|
||||
customUserData->count--;
|
||||
printf("[%012ld] Task:%p callback-> %s.\r\n", GetTick(), task, customUserData->str);
|
||||
printf("[%012llu] Task:%p callback-> %s.\r\n", GetTick(), task, customUserData->str);
|
||||
if (customUserData->count > 0) {
|
||||
TaskStart(task);
|
||||
}
|
||||
}
|
||||
|
||||
void Test_task() {
|
||||
TaskInit(GetTick);
|
||||
TaskCreat(task1, 1000, -1, exampleTimer1Callback, "1000ms CYCLE task");
|
||||
TaskCreat(task2, 5000, -1, exampleTimer2Callback, "5000ms ONCE task");
|
||||
TaskCreat(task3, 3456, 2, exampleTimer3Callback, "3456ms delay start, 4567ms CYCLE task");
|
||||
CustomUserData customUserData = {
|
||||
.count = 3,
|
||||
.str = "2000ms 3 task"
|
||||
};
|
||||
TaskCreat(task4, 2000, 1, exampleTimer4Callback, &customUserData);
|
||||
#undef LOG_RUN_TIMER_FUN
|
||||
#define LOG_RUN_TIMER_FUN GetTick()
|
||||
int Test_task(void *pVoid) {
|
||||
|
||||
LOG_RUN_TIME("Init Timer", {
|
||||
}) {
|
||||
TaskInit(GetTick);
|
||||
TaskCreat(task1, 1000, -1, exampleTimer1Callback, "1000ms CYCLE task");
|
||||
TaskCreat(task2, 5000, -1, exampleTimer2Callback, "5000ms ONCE task");
|
||||
TaskCreat(task3, 3456, 2, exampleTimer3Callback, "3456ms delay start, 4567ms CYCLE task");
|
||||
CustomUserData customUserData = {
|
||||
.count = 3,
|
||||
.str = "2000ms 3 task"
|
||||
};
|
||||
TaskCreat(task4, 2000, 1, exampleTimer4Callback, &customUserData);
|
||||
}
|
||||
while (1) {
|
||||
TaskRun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-5
@@ -1,10 +1,6 @@
|
||||
//
|
||||
// Created by lydxh on 2024/5/10.
|
||||
//
|
||||
|
||||
#ifndef HW_LIB_T_TFT_H
|
||||
#define HW_LIB_T_TFT_H
|
||||
|
||||
void Test_tft();
|
||||
int Test_tft(void *);
|
||||
|
||||
#endif //HW_LIB_T_TFT_H
|
||||
|
||||
+165
-20
@@ -1,29 +1,174 @@
|
||||
#include "stdio.h"
|
||||
#include "lv_port_disp.h"
|
||||
#include "lv_port_indev.h"
|
||||
#include "lvgl.h"
|
||||
#include "lv_demo_widgets.h"
|
||||
#include "tft.h"
|
||||
#include <windows.h>
|
||||
#include "t_tft.h"
|
||||
#include "sim_display.h"
|
||||
#include "tool.h"
|
||||
|
||||
void Test_tft() {
|
||||
lv_init();
|
||||
lv_port_disp_init();
|
||||
lv_port_indev_init();
|
||||
#define LOG_WITH_RUN_TIMER
|
||||
#include "log.h"
|
||||
|
||||
// lv_obj_t * bar1 = lv_bar_create(lv_scr_act());
|
||||
// lv_obj_set_size(bar1, 200, 20);
|
||||
// lv_obj_center(bar1);
|
||||
// lv_bar_set_value(bar1, 70, LV_ANIM_OFF);
|
||||
// lv_demo_widgets();
|
||||
// printf("\nTEST Widgets\n");
|
||||
TFT_T demo_tft;
|
||||
uint16_t xs = 0, ys = 0, xe = 0, ye = 0;
|
||||
bool fill;
|
||||
SIM_Display_t tft_display;
|
||||
//屏幕指令
|
||||
#define WGRAM_CMD 0x5C
|
||||
#define SETXCMD 0x2A
|
||||
#define SETYCMD 0x2B
|
||||
|
||||
while(1) {
|
||||
/* Periodically call the lv_task handler.
|
||||
* It could be done in a timer interrupt or an OS task too.*/
|
||||
lv_timer_handler();
|
||||
lv_tick_inc(5);
|
||||
Sleep(5);
|
||||
//硬件实现区
|
||||
uint8_t tft_writereg(uint8_t reg, uint8_t *pdata, size_t ldata) {
|
||||
uint8_t result;
|
||||
fill = false;
|
||||
Data16_t data16;
|
||||
if (reg == SETXCMD) {
|
||||
if (ldata >= 4) {
|
||||
data16.u8[1] = *pdata;
|
||||
pdata++;
|
||||
data16.u8[0] = *pdata;
|
||||
pdata++;
|
||||
xs = data16.u16;
|
||||
data16.u8[1] = *pdata;
|
||||
pdata++;
|
||||
data16.u8[0] = *pdata;
|
||||
xe = data16.u16;
|
||||
} else if (ldata >= 2) {
|
||||
data16.u8[1] = *pdata;
|
||||
pdata++;
|
||||
data16.u8[0] = *pdata;
|
||||
xs = data16.u16;
|
||||
}
|
||||
// LOGT("SETX","X_S:%d,X_E:%d,len:%d",xs,xe,ldata);
|
||||
} else if (reg == SETYCMD) {
|
||||
if (ldata >= 4) {
|
||||
data16.u8[1] = *pdata;
|
||||
pdata++;
|
||||
data16.u8[0] = *pdata;
|
||||
pdata++;
|
||||
ys = data16.u16;
|
||||
|
||||
|
||||
data16.u8[1] = *pdata;
|
||||
pdata++;
|
||||
data16.u8[0] = *pdata;
|
||||
ye = data16.u16;
|
||||
} else if (ldata >= 2) {
|
||||
data16.u8[1] = *pdata;
|
||||
pdata++;
|
||||
data16.u8[0] = *pdata;
|
||||
ys = data16.u16;
|
||||
}
|
||||
// LOGT("SETY","Y_S:%d,Y_E:%d,len:%d",ys,ye,ldata);
|
||||
} else if (reg == WGRAM_CMD) {
|
||||
fill = true;
|
||||
}
|
||||
if (result > 0) {
|
||||
result = -1;
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//硬件实现
|
||||
uint8_t tft_senddata(uint8_t *data, size_t len) {
|
||||
uint8_t result;
|
||||
uint32_t color[len / 2];
|
||||
TFT_Color_t color_u;
|
||||
if (!fill || len == 0)return -1;
|
||||
if (len == 2) {
|
||||
color_u.u8[1] = *data;
|
||||
color_u.u8[0] = *data++;
|
||||
SIM_Color_DrawPiexl(&tft_display, (SIM_Color_t) RGB565_to_ARGB8888(color_u.u16, true), xs, ys);
|
||||
// LOGT("Piexl","color:%x,x:%d,y:%d,len:%d",color_u.u16,xs,ys,len);
|
||||
// SIM_Color_ImgFromBuffer(color,xs, ys, uint16_t width, 1)
|
||||
} else {
|
||||
for (int i = 0; i < len / 2; i++) {
|
||||
color_u.u8[1] = *data;
|
||||
data++;
|
||||
color_u.u8[0] = *data;
|
||||
data++;
|
||||
color[i] = RGB565_to_ARGB8888(color_u.u16, true);
|
||||
}
|
||||
SIM_Color_ImgFromBuffer(&tft_display, color, xs, ys, len / 2 - 1, 1);
|
||||
// SIM_Color_DrawHLineBuffer(color, xs, ys, len / 2);
|
||||
// LOGT("Img","x:%d,y:%d,len:%d",xs,ys,len);
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
result = -1;
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t GetSysCnt64() {
|
||||
|
||||
}
|
||||
|
||||
int Test_tft(void *arg) {
|
||||
//设备信息预填充
|
||||
demo_tft.width = 480;//实际如有支持不用填(如ST7735/7796)
|
||||
demo_tft.height = 320;//实际如有支持不用填(如ST7735/7796)
|
||||
demo_tft.wgramcmd = WGRAM_CMD;//实际如有支持不用填(如ST7735/7796)
|
||||
demo_tft.setycmd = SETYCMD;//实际如有支持不用填(如ST7735/7796)
|
||||
demo_tft.setxcmd = SETXCMD;//实际如有支持不用填(如ST7735/7796)
|
||||
demo_tft.writeReg = tft_writereg;//必须实现
|
||||
demo_tft.sendData = tft_senddata;//必须实现
|
||||
demo_tft.dir = HORIZONTAL;//必填
|
||||
|
||||
//模拟初始化
|
||||
SIM_Display_Init("TFT", demo_tft.width, demo_tft.height, 0xFFFF, 0x0000, 2, &tft_display);
|
||||
|
||||
|
||||
TFT_Init(&demo_tft);//初始化
|
||||
TFT_Color_t t;
|
||||
t.color = 0XFFFF;
|
||||
TFT_Fill(&demo_tft, 0, 0, demo_tft.width, demo_tft.height, t);
|
||||
|
||||
t.color = 0XFFFF;
|
||||
TFT_SetColor(0xFFFF, 0x0000);
|
||||
|
||||
TFT_Fill(&demo_tft, 0, 0, demo_tft.width, demo_tft.height, t);
|
||||
|
||||
|
||||
TFT_SetColor(0x7D7C, 0x0000);
|
||||
TFT_DrawRect(&demo_tft, 0, 0, 50, 50);
|
||||
|
||||
|
||||
t.color = 0X01CF;
|
||||
TFT_Fill(&demo_tft, 1, 1, 49, 49, t);
|
||||
|
||||
|
||||
TFT_SetColor(0x7D7C, 0x0000);
|
||||
TFT_ShowCHString(&demo_tft, 0, 60, "星海科技机械师", 1);
|
||||
|
||||
|
||||
TFT_DrawCircle(&demo_tft, 25, 25, 15);
|
||||
TFT_DrawRoundedRect(&demo_tft, 200, 0, 100, 30, 8);
|
||||
TFT_DrawArc(&demo_tft, 200, 50, 30, 0, 360);
|
||||
TFT_DrawCross(&demo_tft, 25, 25, 10);
|
||||
TFT_DrawXCross(&demo_tft, 25, 25, 10);
|
||||
|
||||
TFT_ShowString(&demo_tft, 60, 20, "JiXieShi", 16, 1);
|
||||
|
||||
|
||||
TFT_ShowString(&demo_tft, 0, 160,
|
||||
"abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>(){}[]\\/?.,;:'\"!@#$%^&*-=_+~|", 16, 1);
|
||||
for (float p = 0; p < 1; p += 0.001) {
|
||||
TFT_ShowBar(&demo_tft, 0, 100, demo_tft.width, 24, p);
|
||||
TFT_ShowBar(&demo_tft, 0, 125, demo_tft.width, 16, p);
|
||||
TFT_ShowBar(&demo_tft, 0, 142, demo_tft.width, 12, p);
|
||||
TFT_ShowBar(&demo_tft, 0, 155, demo_tft.width, 3, p);
|
||||
}
|
||||
// while (1) {
|
||||
//
|
||||
// Sleep(5);
|
||||
// }
|
||||
|
||||
SIM_Display_STOP(&tft_display);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ set(LIBRARIES
|
||||
HW_LIB_Key key key/inc
|
||||
HW_LIB_Oled oled oled/inc
|
||||
HW_LIB_Tft tft tft/inc
|
||||
HW_LIB_Flash flash flash/inc
|
||||
HW_LIB_Lui lui lui/inc
|
||||
)
|
||||
|
||||
# 循环浏览库列表以创建它们
|
||||
|
||||
+1038
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,359 @@
|
||||
#include "flash.h"
|
||||
|
||||
/**
|
||||
* JEDEC Standard JESD216 Terms and definitions:
|
||||
*
|
||||
* DWORD: Four consecutive 8-bit bytes used as the basic 32-bit building block for headers and parameter tables.
|
||||
*
|
||||
* Sector: The minimum granularity - size and alignment - of an area that can be erased in the data array
|
||||
* of a flash memory device. Different areas within the address range of the data array may have a different
|
||||
* minimum erase granularity (sector size).
|
||||
*/
|
||||
|
||||
#ifdef FLASH_USING_SFDP
|
||||
|
||||
/* support maximum SFDP major revision by driver */
|
||||
#define SUPPORT_MAX_SFDP_MAJOR_REV 1
|
||||
/* the JEDEC basic flash parameter table length is 9 DWORDs (288-bit) on JESD216 (V1.0) initial release standard */
|
||||
#define BASIC_TABLE_LEN 9
|
||||
/* the smallest eraser in SFDP eraser table */
|
||||
#define SMALLEST_ERASER_INDEX 0
|
||||
/**
|
||||
* SFDP parameter header structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t id; /**< Parameter ID LSB */
|
||||
uint8_t minor_rev; /**< Parameter minor revision */
|
||||
uint8_t major_rev; /**< Parameter major revision */
|
||||
uint8_t len; /**< Parameter table length(in double words) */
|
||||
uint32_t ptp; /**< Parameter table 24bit pointer (byte address) */
|
||||
} sfdp_para_header;
|
||||
|
||||
static flash_err read_sfdp_data(const FLASH_t *flash, uint32_t addr, uint8_t *read_buf, size_t size);
|
||||
|
||||
static bool read_sfdp_header(FLASH_t *flash);
|
||||
|
||||
static bool read_basic_header(const FLASH_t *flash, sfdp_para_header *basic_header);
|
||||
|
||||
static bool read_basic_table(FLASH_t *flash, sfdp_para_header *basic_header);
|
||||
|
||||
extern void flash_log_debug(const char *file, const long line, const char *format, ...);
|
||||
|
||||
extern void flash_log_info(const char *format, ...);
|
||||
|
||||
/**
|
||||
* Read SFDP parameter information
|
||||
*
|
||||
* @param flash flash device
|
||||
*
|
||||
* @return true: read OK
|
||||
*/
|
||||
bool flash_read_sfdp(FLASH_t *flash) {
|
||||
FLASH_ASSERT(flash);
|
||||
|
||||
/* JEDEC basic flash parameter header */
|
||||
sfdp_para_header basic_header;
|
||||
if (read_sfdp_header(flash) && read_basic_header(flash, &basic_header)) {
|
||||
return read_basic_table(flash, &basic_header);
|
||||
} else {
|
||||
FLASH_INFO("Warning: Read SFDP parameter header information failed. The %s does not support JEDEC SFDP.",
|
||||
flash->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read SFDP parameter header
|
||||
*
|
||||
* @param flash flash device
|
||||
*
|
||||
* @return true: read OK
|
||||
*/
|
||||
static bool read_sfdp_header(FLASH_t *flash) {
|
||||
flash_sfdp *sfdp = &flash->sfdp;
|
||||
/* The SFDP header is located at address 000000h of the SFDP data structure.
|
||||
* It identifies the SFDP Signature, the number of parameter headers, and the SFDP revision numbers. */
|
||||
/* sfdp parameter header address */
|
||||
uint32_t header_addr = 0;
|
||||
/* each parameter header being 2 DWORDs (64-bit) */
|
||||
uint8_t header[2 * 4] = {0};
|
||||
|
||||
FLASH_ASSERT(flash);
|
||||
|
||||
sfdp->available = false;
|
||||
/* read SFDP header */
|
||||
if (read_sfdp_data(flash, header_addr, header, sizeof(header)) != FLASH_SUCCESS) {
|
||||
FLASH_INFO("Error: Can't read SFDP header.");
|
||||
return false;
|
||||
}
|
||||
/* check SFDP header */
|
||||
if (!(header[0] == 'S' &&
|
||||
header[1] == 'F' &&
|
||||
header[2] == 'D' &&
|
||||
header[3] == 'P')) {
|
||||
FLASH_DEBUG("Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P').");
|
||||
return false;
|
||||
}
|
||||
sfdp->minor_rev = header[4];
|
||||
sfdp->major_rev = header[5];
|
||||
if (sfdp->major_rev > SUPPORT_MAX_SFDP_MAJOR_REV) {
|
||||
FLASH_INFO("Error: This reversion(V%d.%d) of SFDP is not supported.", sfdp->major_rev, sfdp->minor_rev);
|
||||
return false;
|
||||
}
|
||||
FLASH_DEBUG("Check SFDP header is OK. The reversion is V%d.%d, NPN is %d.", sfdp->major_rev, sfdp->minor_rev,
|
||||
header[6]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read JEDEC basic parameter header
|
||||
*
|
||||
* @param flash flash device
|
||||
*
|
||||
* @return true: read OK
|
||||
*/
|
||||
static bool read_basic_header(const FLASH_t *flash, sfdp_para_header *basic_header) {
|
||||
/* The basic parameter header is mandatory, is defined by this standard, and starts at byte offset 08h. */
|
||||
uint32_t header_addr = 8;
|
||||
/* each parameter header being 2 DWORDs (64-bit) */
|
||||
uint8_t header[2 * 4] = {0};
|
||||
|
||||
FLASH_ASSERT(flash);
|
||||
FLASH_ASSERT(basic_header);
|
||||
|
||||
/* read JEDEC basic flash parameter header */
|
||||
if (read_sfdp_data(flash, header_addr, header, sizeof(header)) != FLASH_SUCCESS) {
|
||||
FLASH_INFO("Error: Can't read JEDEC basic flash parameter header.");
|
||||
return false;
|
||||
}
|
||||
basic_header->id = header[0];
|
||||
basic_header->minor_rev = header[1];
|
||||
basic_header->major_rev = header[2];
|
||||
basic_header->len = header[3];
|
||||
basic_header->ptp = (long) header[4] | (long) header[5] << 8 | (long) header[6] << 16;
|
||||
/* check JEDEC basic flash parameter header */
|
||||
if (basic_header->major_rev > SUPPORT_MAX_SFDP_MAJOR_REV) {
|
||||
FLASH_INFO("Error: This reversion(V%d.%d) of JEDEC basic flash parameter header is not supported.",
|
||||
basic_header->major_rev, basic_header->minor_rev);
|
||||
return false;
|
||||
}
|
||||
if (basic_header->len < BASIC_TABLE_LEN) {
|
||||
FLASH_INFO("Error: The JEDEC basic flash parameter table length (now is %d) error.", basic_header->len);
|
||||
return false;
|
||||
}
|
||||
FLASH_DEBUG("Check JEDEC basic flash parameter header is OK. The table id is %d, reversion is V%d.%d,"
|
||||
" length is %d, parameter table pointer is 0x%06lX.", basic_header->id, basic_header->major_rev,
|
||||
basic_header->minor_rev, basic_header->len, basic_header->ptp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read JEDEC basic parameter table
|
||||
*
|
||||
* @param flash flash device
|
||||
*
|
||||
* @return true: read OK
|
||||
*/
|
||||
static bool read_basic_table(FLASH_t *flash, sfdp_para_header *basic_header) {
|
||||
flash_sfdp *sfdp = &flash->sfdp;
|
||||
/* parameter table address */
|
||||
uint32_t table_addr = basic_header->ptp;
|
||||
/* parameter table */
|
||||
uint8_t table[BASIC_TABLE_LEN * 4] = {0}, i, j;
|
||||
|
||||
FLASH_ASSERT(flash);
|
||||
FLASH_ASSERT(basic_header);
|
||||
|
||||
/* read JEDEC basic flash parameter table */
|
||||
if (read_sfdp_data(flash, table_addr, table, sizeof(table)) != FLASH_SUCCESS) {
|
||||
FLASH_INFO("Warning: Can't read JEDEC basic flash parameter table.");
|
||||
return false;
|
||||
}
|
||||
/* print JEDEC basic flash parameter table info */
|
||||
FLASH_DEBUG("JEDEC basic flash parameter table info:");
|
||||
FLASH_DEBUG("MSB-LSB 3 2 1 0");
|
||||
for (i = 0; i < BASIC_TABLE_LEN; i++) {
|
||||
FLASH_DEBUG("[%04d] 0x%02X 0x%02X 0x%02X 0x%02X", i + 1, table[i * 4 + 3], table[i * 4 + 2], table[i * 4 + 1],
|
||||
table[i * 4]);
|
||||
}
|
||||
|
||||
/* get block/sector 4 KB erase supported and command */
|
||||
sfdp->erase_4k_cmd = table[1];
|
||||
switch (table[0] & 0x03) {
|
||||
case 1:
|
||||
sfdp->erase_4k = true;
|
||||
FLASH_DEBUG("4 KB Erase is supported throughout the device. Command is 0x%02X.", sfdp->erase_4k_cmd);
|
||||
break;
|
||||
case 3:
|
||||
sfdp->erase_4k = false;
|
||||
FLASH_DEBUG("Uniform 4 KB erase is unavailable for this device.");
|
||||
break;
|
||||
default:
|
||||
FLASH_INFO("Error: Uniform 4 KB erase supported information error.");
|
||||
return false;
|
||||
}
|
||||
/* get write granularity */
|
||||
//TODO 目前为 1.0 所提供的方式,后期支持 V1.5 及以上的方式读取 page size
|
||||
switch ((table[0] & (0x01 << 2)) >> 2) {
|
||||
case 0:
|
||||
sfdp->write_gran = 1;
|
||||
FLASH_DEBUG("Write granularity is 1 byte.");
|
||||
break;
|
||||
case 1:
|
||||
sfdp->write_gran = 256;
|
||||
FLASH_DEBUG("Write granularity is 64 bytes or larger.");
|
||||
break;
|
||||
}
|
||||
/* volatile status register block protect bits */
|
||||
switch ((table[0] & (0x01 << 3)) >> 3) {
|
||||
case 0:
|
||||
/* Block Protect bits in device's status register are solely non-volatile or may be
|
||||
* programmed either as volatile using the 50h instruction for write enable or non-volatile
|
||||
* using the 06h instruction for write enable.
|
||||
*/
|
||||
sfdp->sr_is_non_vola = true;
|
||||
FLASH_DEBUG("Target flash status register is non-volatile.");
|
||||
break;
|
||||
case 1:
|
||||
/* block protect bits in device's status register are solely volatile. */
|
||||
sfdp->sr_is_non_vola = false;
|
||||
FLASH_DEBUG("Block Protect bits in device's status register are solely volatile.");
|
||||
/* write enable instruction select for writing to volatile status register */
|
||||
switch ((table[0] & (0x01 << 4)) >> 4) {
|
||||
case 0:
|
||||
sfdp->vola_sr_we_cmd = FLASH_VOLATILE_SR_WRITE_ENABLE;
|
||||
FLASH_DEBUG("Flash device requires instruction 50h as the write enable prior "
|
||||
"to performing a volatile write to the status register.");
|
||||
break;
|
||||
case 1:
|
||||
sfdp->vola_sr_we_cmd = FLASH_CMD_WRITE_ENABLE;
|
||||
FLASH_DEBUG("Flash device requires instruction 06h as the write enable prior "
|
||||
"to performing a volatile write to the status register.");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* get address bytes, number of bytes used in addressing flash array read, write and erase. */
|
||||
switch ((table[2] & (0x03 << 1)) >> 1) {
|
||||
case 0:
|
||||
sfdp->addr_3_byte = true;
|
||||
sfdp->addr_4_byte = false;
|
||||
FLASH_DEBUG("3-Byte only addressing.");
|
||||
break;
|
||||
case 1:
|
||||
sfdp->addr_3_byte = true;
|
||||
sfdp->addr_4_byte = true;
|
||||
FLASH_DEBUG("3- or 4-Byte addressing.");
|
||||
break;
|
||||
case 2:
|
||||
sfdp->addr_3_byte = false;
|
||||
sfdp->addr_4_byte = true;
|
||||
FLASH_DEBUG("4-Byte only addressing.");
|
||||
break;
|
||||
default:
|
||||
sfdp->addr_3_byte = false;
|
||||
sfdp->addr_4_byte = false;
|
||||
FLASH_INFO("Error: Read address bytes error!");
|
||||
return false;
|
||||
}
|
||||
/* get flash memory capacity */
|
||||
uint32_t table2_temp = ((long) table[7] << 24) | ((long) table[6] << 16) | ((long) table[5] << 8) | (long) table[4];
|
||||
switch ((table[7] & (0x01 << 7)) >> 7) {
|
||||
case 0:
|
||||
sfdp->capacity = 1 + (table2_temp >> 3);
|
||||
break;
|
||||
case 1:
|
||||
table2_temp &= 0x7FFFFFFF;
|
||||
if (table2_temp > sizeof(sfdp->capacity) * 8 + 3) {
|
||||
sfdp->capacity = 0;
|
||||
FLASH_INFO("Error: The flash capacity is grater than 32 Gb/ 4 GB! Not Supported.");
|
||||
return false;
|
||||
}
|
||||
sfdp->capacity = 1L << (table2_temp - 3);
|
||||
break;
|
||||
}
|
||||
FLASH_DEBUG("Capacity is %ld Bytes.", sfdp->capacity);
|
||||
/* get erase size and erase command */
|
||||
for (i = 0, j = 0; i < FLASH_SFDP_ERASE_TYPE_MAX_NUM; i++) {
|
||||
if (table[28 + 2 * i] != 0x00) {
|
||||
sfdp->eraser[j].size = 1L << table[28 + 2 * i];
|
||||
sfdp->eraser[j].cmd = table[28 + 2 * i + 1];
|
||||
FLASH_DEBUG("Flash device supports %ldKB block erase. Command is 0x%02X.", sfdp->eraser[j].size / 1024,
|
||||
sfdp->eraser[j].cmd);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
/* sort the eraser size from small to large */
|
||||
for (i = 0, j = 0; i < FLASH_SFDP_ERASE_TYPE_MAX_NUM; i++) {
|
||||
if (sfdp->eraser[i].size) {
|
||||
for (j = i + 1; j < FLASH_SFDP_ERASE_TYPE_MAX_NUM; j++) {
|
||||
if (sfdp->eraser[j].size != 0 && sfdp->eraser[i].size > sfdp->eraser[j].size) {
|
||||
/* swap the small eraser */
|
||||
uint32_t temp_size = sfdp->eraser[i].size;
|
||||
uint8_t temp_cmd = sfdp->eraser[i].cmd;
|
||||
sfdp->eraser[i].size = sfdp->eraser[j].size;
|
||||
sfdp->eraser[i].cmd = sfdp->eraser[j].cmd;
|
||||
sfdp->eraser[j].size = temp_size;
|
||||
sfdp->eraser[j].cmd = temp_cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sfdp->available = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static flash_err read_sfdp_data(const FLASH_t *flash, uint32_t addr, uint8_t *read_buf, size_t size) {
|
||||
uint8_t cmd[] = {
|
||||
FLASH_CMD_READ_SFDP_REGISTER,
|
||||
(uint8_t) ((addr >> 16) & 0xFF),
|
||||
(uint8_t) ((addr >> 8) & 0xFF),
|
||||
(uint8_t) ((addr >> 0) & 0xFF),
|
||||
FLASH_DUMMY_DATA,
|
||||
};
|
||||
|
||||
FLASH_ASSERT(flash);
|
||||
FLASH_ASSERT(addr < 1L << 24);
|
||||
FLASH_ASSERT(read_buf);
|
||||
FLASH_ASSERT(flash->spi.wr);
|
||||
|
||||
return flash->spi.wr(&flash->spi, cmd, sizeof(cmd), read_buf, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the most suitable eraser for erase process from SFDP parameter
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param addr start address
|
||||
* @param erase_size will be erased size
|
||||
*
|
||||
* @return the eraser index of SFDP eraser table @see flash_sfdp.eraser[]
|
||||
*/
|
||||
size_t flash_sfdp_get_suitable_eraser(const FLASH_t *flash, uint32_t addr, size_t erase_size) {
|
||||
size_t index = SMALLEST_ERASER_INDEX, i;
|
||||
/* only used when flash supported SFDP */
|
||||
FLASH_ASSERT(flash->sfdp.available);
|
||||
/* the address isn't align by smallest eraser's size, then use the smallest eraser */
|
||||
if (addr % flash->sfdp.eraser[SMALLEST_ERASER_INDEX].size) {
|
||||
return SMALLEST_ERASER_INDEX;
|
||||
}
|
||||
/* Find the suitable eraser.
|
||||
* The largest size eraser is at the end of eraser table.
|
||||
* In order to decrease erase command counts, so the find process is from the end of eraser table. */
|
||||
for (i = FLASH_SFDP_ERASE_TYPE_MAX_NUM - 1;; i--) {
|
||||
if ((flash->sfdp.eraser[i].size != 0) && (erase_size >= flash->sfdp.eraser[i].size)
|
||||
&& (addr % flash->sfdp.eraser[i].size == 0)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if (i == SMALLEST_ERASER_INDEX) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
#endif /* FLASH_USING_SFDP */
|
||||
@@ -0,0 +1,208 @@
|
||||
//
|
||||
// Created by lydxh on 24-11-27.
|
||||
//
|
||||
|
||||
#ifndef HW_LIB_FLASH_H
|
||||
#define HW_LIB_FLASH_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <flash_cfg.h>
|
||||
#include "flash_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* debug print function. Must be implement by user. */
|
||||
#ifdef FLASH_DEBUG_MODE
|
||||
#ifndef FLASH_DEBUG
|
||||
#define FLASH_DEBUG(...) flash_log_debug(__FILE__, __LINE__, __VA_ARGS__)
|
||||
#endif /* FLASH_DEBUG */
|
||||
#else
|
||||
#define FLASH_DEBUG(...)
|
||||
#endif /* FLASH_DEBUG_MODE */
|
||||
|
||||
#ifndef FLASH_INFO
|
||||
#define FLASH_INFO(...) flash_log_info(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/* assert for developer. */
|
||||
#ifdef FLASH_DEBUG_MODE
|
||||
#define FLASH_ASSERT(EXPR) \
|
||||
if (!(EXPR)) \
|
||||
{ \
|
||||
FLASH_DEBUG("(%s) has assert failed at %s.", #EXPR, __FUNCTION__); \
|
||||
while (1); \
|
||||
}
|
||||
#else
|
||||
#define FLASH_ASSERT(EXPR)
|
||||
#endif
|
||||
|
||||
typedef struct FLASH_Dev FLASH_t;
|
||||
|
||||
struct FLASH_Dev {
|
||||
char *name; /**< serial flash name */
|
||||
size_t index; /**< index of flash device information table @see flash_table */
|
||||
flash_chip chip; /**< flash chip information */
|
||||
flash_spi spi; /**< SPI device */
|
||||
bool init_ok; /**< initialize OK flag */
|
||||
bool addr_in_4_byte; /**< flash is in 4-Byte addressing */
|
||||
struct {
|
||||
void (*delay)(void); /**< every retry's delay */
|
||||
size_t times; /**< default times for error retry */
|
||||
} retry;
|
||||
|
||||
void *user_data; /**< some user data */
|
||||
|
||||
#ifdef FLASH_USING_QSPI
|
||||
flash_qspi_read_cmd_format read_cmd_format; /**< fast read cmd format */
|
||||
#endif
|
||||
|
||||
#ifdef FLASH_USING_SFDP
|
||||
flash_sfdp sfdp; /**< serial flash discoverable parameters by JEDEC standard */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FLASH library initialize.
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_init(void);
|
||||
|
||||
/**
|
||||
* FLASH initialize by flash device
|
||||
*
|
||||
* @param flash flash device
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_device_init(FLASH_t *flash);
|
||||
|
||||
/**
|
||||
* get flash device by its index which in the flash information table
|
||||
*
|
||||
* @param index the index which in the flash information table @see flash_table
|
||||
*
|
||||
* @return flash device
|
||||
*/
|
||||
FLASH_t *flash_get_device(size_t index);
|
||||
|
||||
/**
|
||||
* get flash device total number on flash device information table @see flash_table
|
||||
*
|
||||
* @return flash device total number
|
||||
*/
|
||||
size_t flash_get_device_num(void);
|
||||
|
||||
/**
|
||||
* get flash device information table @see flash_table
|
||||
*
|
||||
* @return flash device table pointer
|
||||
*/
|
||||
const FLASH_t *flash_get_device_table(void);
|
||||
|
||||
#ifdef FLASH_USING_QSPI
|
||||
/**
|
||||
* Enbale the fast read mode in QSPI flash mode. Default read mode is normal SPI mode.
|
||||
*
|
||||
* it will find the appropriate fast-read instruction to replace the read instruction(0x03)
|
||||
* fast-read instruction @see FLASH_FLASH_EXT_INFO_TABLE
|
||||
*
|
||||
* @note When Flash is in QSPI mode, the method must be called after flash_device_init().
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param data_line_width the data lines max width which QSPI bus supported, such as 1, 2, 4
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_qspi_fast_read_enable(FLASH_t *flash, uint8_t data_line_width);
|
||||
#endif /* FLASH_USING_QSPI */
|
||||
|
||||
/**
|
||||
* read flash data
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param addr start address
|
||||
* @param size read size
|
||||
* @param data read data pointer
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_read(const FLASH_t *flash, uint32_t addr, size_t size, uint8_t *data);
|
||||
|
||||
/**
|
||||
* erase flash data
|
||||
*
|
||||
* @note It will erase align by erase granularity.
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param addr start address
|
||||
* @param size erase size
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_erase(const FLASH_t *flash, uint32_t addr, size_t size);
|
||||
|
||||
/**
|
||||
* write flash data (no erase operate)
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param addr start address
|
||||
* @param data write data
|
||||
* @param size write size
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_write(const FLASH_t *flash, uint32_t addr, size_t size, const uint8_t *data);
|
||||
|
||||
/**
|
||||
* erase and write flash data
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param addr start address
|
||||
* @param size write size
|
||||
* @param data write data
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_erase_write(const FLASH_t *flash, uint32_t addr, size_t size, const uint8_t *data);
|
||||
|
||||
/**
|
||||
* erase all flash data
|
||||
*
|
||||
* @param flash flash device
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_chip_erase(const FLASH_t *flash);
|
||||
|
||||
/**
|
||||
* read flash register status
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param status register status
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_read_status(const FLASH_t *flash, uint8_t *status);
|
||||
|
||||
/**
|
||||
* write status register
|
||||
*
|
||||
* @param flash flash device
|
||||
* @param is_volatile true: volatile mode, false: non-volatile mode
|
||||
* @param status register status
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
flash_err flash_write_status(const FLASH_t *flash, bool is_volatile, uint8_t status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_FLASH_H
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Created by lydxh on 24-11-27.
|
||||
//
|
||||
|
||||
#ifndef HW_LIB_FLASH_CFG_H
|
||||
#define HW_LIB_FLASH_CFG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FLASH_DEBUG_MODE
|
||||
|
||||
#define FLASH_USING_SFDP
|
||||
|
||||
// #define FLASH_USING_FAST_READ
|
||||
|
||||
#define FLASH_USING_FLASH_INFO_TABLE
|
||||
|
||||
enum {
|
||||
FLASH_XXXX_DEVICE_INDEX = 0,
|
||||
};
|
||||
|
||||
#define FLASH_FLASH_DEVICE_TABLE \
|
||||
{ \
|
||||
[FLASH_XXXX_DEVICE_INDEX] = {.name = "XXXX", .spi={.name = "SPIX"}, }, \
|
||||
}
|
||||
|
||||
#define FLASH_USING_QSPI
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_FLASH_CFG_H
|
||||
@@ -0,0 +1,406 @@
|
||||
//
|
||||
// Created by lydxh on 24-11-27.
|
||||
//
|
||||
|
||||
#ifndef HW_LIB_FLASH_DEF_H
|
||||
#define HW_LIB_FLASH_DEF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <flash_cfg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* flash program(write) data mode
|
||||
*/
|
||||
enum flash_write_mode {
|
||||
FLASH_WM_PAGE_256B = 1 << 0, /**< write 1 to 256 bytes per page */
|
||||
FLASH_WM_BYTE = 1 << 1, /**< byte write */
|
||||
FLASH_WM_AAI = 1 << 2, /**< auto address increment */
|
||||
FLASH_WM_DUAL_BUFFER = 1 << 3, /**< dual-buffer write, like AT45DB series */
|
||||
};
|
||||
|
||||
/* manufacturer information */
|
||||
typedef struct {
|
||||
char *name;
|
||||
uint8_t id;
|
||||
} flash_mf;
|
||||
|
||||
/* flash chip information */
|
||||
typedef struct {
|
||||
char *name; /**< flash chip name */
|
||||
uint8_t mf_id; /**< manufacturer ID */
|
||||
uint8_t type_id; /**< memory type ID */
|
||||
uint8_t capacity_id; /**< capacity ID */
|
||||
uint32_t capacity; /**< flash capacity (bytes) */
|
||||
uint16_t write_mode; /**< write mode @see flash_write_mode */
|
||||
uint32_t erase_gran; /**< erase granularity (bytes) */
|
||||
uint8_t erase_gran_cmd; /**< erase granularity size block command */
|
||||
} flash_chip;
|
||||
|
||||
#ifdef FLASH_USING_QSPI
|
||||
/* QSPI flash chip's extended information compared with SPI flash */
|
||||
typedef struct {
|
||||
uint8_t mf_id; /**< manufacturer ID */
|
||||
uint8_t type_id; /**< memory type ID */
|
||||
uint8_t capacity_id; /**< capacity ID */
|
||||
uint8_t read_mode; /**< supported read mode on this qspi flash chip */
|
||||
} flash_qspi_flash_ext_info;
|
||||
#endif
|
||||
|
||||
/* FLASH support manufacturer JEDEC ID */
|
||||
#define FLASH_MF_ID_CYPRESS 0x01
|
||||
#define FLASH_MF_ID_FUJITSU 0x04
|
||||
#define FLASH_MF_ID_EON 0x1C
|
||||
#define FLASH_MF_ID_ATMEL 0x1F
|
||||
#define FLASH_MF_ID_MICRON 0x20
|
||||
#define FLASH_MF_ID_AMIC 0x37
|
||||
#define FLASH_MF_ID_NOR_MEM 0x52
|
||||
#define FLASH_MF_ID_SANYO 0x62
|
||||
#define FLASH_MF_ID_INTEL 0x89
|
||||
#define FLASH_MF_ID_ESMT 0x8C
|
||||
#define FLASH_MF_ID_FUDAN 0xA1
|
||||
#define FLASH_MF_ID_HYUNDAI 0xAD
|
||||
#define FLASH_MF_ID_SST 0xBF
|
||||
#define FLASH_MF_ID_MACRONIX 0xC2
|
||||
#define FLASH_MF_ID_GIGADEVICE 0xC8
|
||||
#define FLASH_MF_ID_ISSI 0xD5
|
||||
#define FLASH_MF_ID_WINBOND 0xEF
|
||||
#define FLASH_MF_ID_PUYA 0x85
|
||||
|
||||
/* FLASH supported manufacturer information table */
|
||||
#define FLASH_MF_TABLE \
|
||||
{ \
|
||||
{"Cypress", FLASH_MF_ID_CYPRESS}, \
|
||||
{"Fujitsu", FLASH_MF_ID_FUJITSU}, \
|
||||
{"EON", FLASH_MF_ID_EON}, \
|
||||
{"Atmel", FLASH_MF_ID_ATMEL}, \
|
||||
{"Micron", FLASH_MF_ID_MICRON}, \
|
||||
{"AMIC", FLASH_MF_ID_AMIC}, \
|
||||
{"Sanyo", FLASH_MF_ID_SANYO}, \
|
||||
{"Intel", FLASH_MF_ID_INTEL}, \
|
||||
{"ESMT", FLASH_MF_ID_ESMT}, \
|
||||
{"Fudan", FLASH_MF_ID_FUDAN}, \
|
||||
{"Hyundai", FLASH_MF_ID_HYUNDAI}, \
|
||||
{"SST", FLASH_MF_ID_SST}, \
|
||||
{"GigaDevice", FLASH_MF_ID_GIGADEVICE}, \
|
||||
{"ISSI", FLASH_MF_ID_ISSI}, \
|
||||
{"Winbond", FLASH_MF_ID_WINBOND}, \
|
||||
{"Macronix", FLASH_MF_ID_MACRONIX}, \
|
||||
{"NOR-MEM", FLASH_MF_ID_NOR_MEM}, \
|
||||
{"PUYA", FLASH_MF_ID_PUYA}, \
|
||||
}
|
||||
|
||||
#ifdef FLASH_USING_FLASH_INFO_TABLE
|
||||
/* FLASH supported flash chip information table. If the flash not support JEDEC JESD216 standard,
|
||||
* then the FLASH will find the flash chip information by this table. You can add other flash to here then
|
||||
* notice me for update it. The configuration information name and index reference the flash_flash_chip structure.
|
||||
* | name | mf_id | type_id | capacity_id | capacity | write_mode | erase_gran | erase_gran_cmd |
|
||||
*/
|
||||
#define FLASH_FLASH_CHIP_TABLE \
|
||||
{ \
|
||||
{"AT45DB161E", FLASH_MF_ID_ATMEL, 0x26, 0x00, 2L*1024L*1024L, FLASH_WM_BYTE|FLASH_WM_DUAL_BUFFER, 512, 0x81}, \
|
||||
{"W25Q40BV", FLASH_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25X40CL", FLASH_MF_ID_WINBOND, 0x30, 0x13, 512L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25X16AV", FLASH_MF_ID_WINBOND, 0x30, 0x15, 2L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25Q16BV", FLASH_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25Q32BV", FLASH_MF_ID_WINBOND, 0x40, 0x16, 4L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25Q64CV", FLASH_MF_ID_WINBOND, 0x40, 0x17, 8L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25Q64DW", FLASH_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25Q128BV", FLASH_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"W25Q256FV", FLASH_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"SST25VF080B", FLASH_MF_ID_SST, 0x25, 0x8E, 1L*1024L*1024L, FLASH_WM_BYTE|FLASH_WM_AAI, 4096, 0x20}, \
|
||||
{"SST25VF016B", FLASH_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, FLASH_WM_BYTE|FLASH_WM_AAI, 4096, 0x20}, \
|
||||
{"M25P32", FLASH_MF_ID_MICRON, 0x20, 0x16, 4L*1024L*1024L, FLASH_WM_PAGE_256B, 64L*1024L, 0xD8}, \
|
||||
{"M25P80", FLASH_MF_ID_MICRON, 0x20, 0x14, 1L*1024L*1024L, FLASH_WM_PAGE_256B, 64L*1024L, 0xD8}, \
|
||||
{"M25P40", FLASH_MF_ID_MICRON, 0x20, 0x13, 512L*1024L, FLASH_WM_PAGE_256B, 64L*1024L, 0xD8}, \
|
||||
{"EN25Q32B", FLASH_MF_ID_EON, 0x30, 0x16, 4L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"GD25Q64B", FLASH_MF_ID_GIGADEVICE, 0x40, 0x17, 8L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"GD25Q16B", FLASH_MF_ID_GIGADEVICE, 0x40, 0x15, 2L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"GD25Q32C", FLASH_MF_ID_GIGADEVICE, 0x40, 0x16, 4L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"S25FL216K", FLASH_MF_ID_CYPRESS, 0x40, 0x15, 2L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"S25FL032P", FLASH_MF_ID_CYPRESS, 0x02, 0x15, 4L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"A25L080", FLASH_MF_ID_AMIC, 0x30, 0x14, 1L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"F25L004", FLASH_MF_ID_ESMT, 0x20, 0x13, 512L*1024L, FLASH_WM_BYTE|FLASH_WM_AAI, 4096, 0x20}, \
|
||||
{"PCT25VF016B", FLASH_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, FLASH_WM_BYTE|FLASH_WM_AAI, 4096, 0x20}, \
|
||||
{"NM25Q128EVB", FLASH_MF_ID_NOR_MEM, 0x21, 0x18, 16L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"P25D05H", FLASH_MF_ID_PUYA, 0x60, 0x13, 5L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"P25D10H", FLASH_MF_ID_PUYA, 0x60, 0x12, 1L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"P25D20H", FLASH_MF_ID_PUYA, 0x60, 0x11, 2L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"P25D40H", FLASH_MF_ID_PUYA, 0x60, 0x10, 4L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
{"P25Q80H", FLASH_MF_ID_PUYA, 0x30, 0x14, 8L*1024L*1024L, FLASH_WM_PAGE_256B, 4096, 0x20}, \
|
||||
}
|
||||
#endif /* FLASH_USING_FLASH_INFO_TABLE */
|
||||
|
||||
#ifdef FLASH_USING_QSPI
|
||||
/* This table saves flash read-fast instructions in QSPI mode,
|
||||
* FLASH can use this table to select the most appropriate read instruction for flash.
|
||||
* | mf_id | type_id | capacity_id | qspi_read_mode |
|
||||
*/
|
||||
#define FLASH_FLASH_EXT_INFO_TABLE \
|
||||
{ \
|
||||
/* W25Q40BV */ \
|
||||
{FLASH_MF_ID_WINBOND, 0x40, 0x13, NORMAL_SPI_READ|DUAL_OUTPUT}, \
|
||||
/* W25Q80JV */ \
|
||||
{FLASH_MF_ID_WINBOND, 0x40, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT}, \
|
||||
/* W25Q16BV */ \
|
||||
{FLASH_MF_ID_WINBOND, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT}, \
|
||||
/* W25Q32BV */ \
|
||||
{FLASH_MF_ID_WINBOND, 0x40, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT|QUAD_OUTPUT|QUAD_IO}, \
|
||||
/* W25Q64JV */ \
|
||||
{FLASH_MF_ID_WINBOND, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
|
||||
/* W25Q128JV */ \
|
||||
{FLASH_MF_ID_WINBOND, 0x40, 0x18, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
|
||||
/* W25Q256FV */ \
|
||||
{FLASH_MF_ID_WINBOND, 0x40, 0x19, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
|
||||
/* EN25Q32B */ \
|
||||
{FLASH_MF_ID_EON, 0x30, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT|QUAD_IO}, \
|
||||
/* S25FL216K */ \
|
||||
{FLASH_MF_ID_CYPRESS, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT}, \
|
||||
/* A25L080 */ \
|
||||
{FLASH_MF_ID_AMIC, 0x30, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO}, \
|
||||
/* A25LQ64 */ \
|
||||
{FLASH_MF_ID_AMIC, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_IO}, \
|
||||
/* MX25L3206E and KH25L3206E */ \
|
||||
{FLASH_MF_ID_MACRONIX, 0x20, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT}, \
|
||||
/* MX25L51245G */ \
|
||||
{FLASH_MF_ID_MACRONIX, 0x20, 0x1A, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
|
||||
/* GD25Q64B */ \
|
||||
{FLASH_MF_ID_GIGADEVICE, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT}, \
|
||||
/* NM25Q128EVB */ \
|
||||
{FLASH_MF_ID_NOR_MEM, 0x21, 0x18, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
|
||||
}
|
||||
#endif /* FLASH_USING_QSPI */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* retry process
|
||||
*
|
||||
* @param delay delay function for every retry. NULL will not delay for every retry.
|
||||
* @param retry retry counts
|
||||
* @param result FLASH_ERR_TIMEOUT: retry timeout
|
||||
*/
|
||||
#define FLASH_RETRY_PROCESS(delay, retry, result) \
|
||||
void (*__delay_temp)(void) = (void (*)(void))delay; \
|
||||
if (retry == 0) {result = FLASH_ERR_TIMEOUT;break;} \
|
||||
else {if (__delay_temp) {__delay_temp();} retry --;}
|
||||
|
||||
/* software version number */
|
||||
#define FLASH_SW_VERSION "1.1.0"
|
||||
/*
|
||||
* all defined supported command
|
||||
*/
|
||||
#ifndef FLASH_CMD_WRITE_ENABLE
|
||||
#define FLASH_CMD_WRITE_ENABLE 0x06
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_WRITE_DISABLE
|
||||
#define FLASH_CMD_WRITE_DISABLE 0x04
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_READ_STATUS_REGISTER
|
||||
#define FLASH_CMD_READ_STATUS_REGISTER 0x05
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_VOLATILE_SR_WRITE_ENABLE
|
||||
#define FLASH_VOLATILE_SR_WRITE_ENABLE 0x50
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_WRITE_STATUS_REGISTER
|
||||
#define FLASH_CMD_WRITE_STATUS_REGISTER 0x01
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_PAGE_PROGRAM
|
||||
#define FLASH_CMD_PAGE_PROGRAM 0x02
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_AAI_WORD_PROGRAM
|
||||
#define FLASH_CMD_AAI_WORD_PROGRAM 0xAD
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_ERASE_CHIP
|
||||
#define FLASH_CMD_ERASE_CHIP 0xC7
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_READ_DATA
|
||||
#define FLASH_CMD_READ_DATA 0x03
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_FAST_READ_DATA
|
||||
#define FLASH_CMD_FAST_READ_DATA 0x0B
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_DUAL_OUTPUT_READ_DATA
|
||||
#define FLASH_CMD_DUAL_OUTPUT_READ_DATA 0x3B
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_DUAL_IO_READ_DATA
|
||||
#define FLASH_CMD_DUAL_IO_READ_DATA 0xBB
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_QUAD_IO_READ_DATA
|
||||
#define FLASH_CMD_QUAD_IO_READ_DATA 0xEB
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_QUAD_OUTPUT_READ_DATA
|
||||
#define FLASH_CMD_QUAD_OUTPUT_READ_DATA 0x6B
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_MANUFACTURER_DEVICE_ID
|
||||
#define FLASH_CMD_MANUFACTURER_DEVICE_ID 0x90
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_JEDEC_ID
|
||||
#define FLASH_CMD_JEDEC_ID 0x9F
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_READ_UNIQUE_ID
|
||||
#define FLASH_CMD_READ_UNIQUE_ID 0x4B
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_READ_SFDP_REGISTER
|
||||
#define FLASH_CMD_READ_SFDP_REGISTER 0x5A
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_ENABLE_RESET
|
||||
#define FLASH_CMD_ENABLE_RESET 0x66
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_RESET
|
||||
#define FLASH_CMD_RESET 0x99
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_ENTER_4B_ADDRESS_MODE
|
||||
#define FLASH_CMD_ENTER_4B_ADDRESS_MODE 0xB7
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_CMD_EXIT_4B_ADDRESS_MODE
|
||||
#define FLASH_CMD_EXIT_4B_ADDRESS_MODE 0xE9
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_WRITE_MAX_PAGE_SIZE
|
||||
#define FLASH_WRITE_MAX_PAGE_SIZE 256
|
||||
#endif
|
||||
|
||||
/* send dummy data for read data */
|
||||
#ifndef FLASH_DUMMY_DATA
|
||||
#define FLASH_DUMMY_DATA 0xFF
|
||||
#endif
|
||||
|
||||
/* dummy data count for fast read data and etc */
|
||||
#ifndef FLASH_READ_DUMMY_BYTE_CNT
|
||||
#ifdef FLASH_USING_FAST_READ
|
||||
#define FLASH_READ_DUMMY_BYTE_CNT 1
|
||||
#else
|
||||
#define FLASH_READ_DUMMY_BYTE_CNT 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* maximum number of erase type support on JESD216 (V1.0) */
|
||||
#define FLASH_SFDP_ERASE_TYPE_MAX_NUM 4
|
||||
|
||||
/**
|
||||
* status register bits
|
||||
*/
|
||||
enum {
|
||||
FLASH_STATUS_REGISTER_BUSY = (1 << 0), /**< busing */
|
||||
FLASH_STATUS_REGISTER_WEL = (1 << 1), /**< write enable latch */
|
||||
FLASH_STATUS_REGISTER_SRP = (1 << 7), /**< status register protect */
|
||||
};
|
||||
|
||||
/**
|
||||
* error code
|
||||
*/
|
||||
typedef enum {
|
||||
FLASH_SUCCESS = 0, /**< success */
|
||||
FLASH_ERR_NOT_FOUND = 1, /**< not found or not supported */
|
||||
FLASH_ERR_WRITE = 2, /**< write error */
|
||||
FLASH_ERR_READ = 3, /**< read error */
|
||||
FLASH_ERR_TIMEOUT = 4, /**< timeout error */
|
||||
FLASH_ERR_ADDR_OUT_OF_BOUND = 5, /**< address is out of flash bound */
|
||||
} flash_err;
|
||||
|
||||
#ifdef FLASH_USING_QSPI
|
||||
/**
|
||||
* QSPI flash read cmd format
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t instruction;
|
||||
uint8_t instruction_lines;
|
||||
uint8_t address_size;
|
||||
uint8_t address_lines;
|
||||
uint8_t alternate_bytes_lines;
|
||||
uint8_t dummy_cycles;
|
||||
uint8_t data_lines;
|
||||
} flash_qspi_read_cmd_format;
|
||||
#endif /* FLASH_USING_QSPI */
|
||||
|
||||
/* SPI bus write read data function type */
|
||||
typedef flash_err (*spi_write_read_func)(const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
|
||||
size_t read_size);
|
||||
|
||||
#ifdef FLASH_USING_SFDP
|
||||
/**
|
||||
* the SFDP (Serial Flash Discoverable Parameters) parameter info which used on this library
|
||||
*/
|
||||
typedef struct {
|
||||
bool available; /**< available when read SFDP OK */
|
||||
uint8_t major_rev; /**< SFDP Major Revision */
|
||||
uint8_t minor_rev; /**< SFDP Minor Revision */
|
||||
uint16_t write_gran; /**< write granularity (bytes) */
|
||||
uint8_t erase_4k; /**< 4 kilobyte erase is supported throughout the device */
|
||||
uint8_t erase_4k_cmd; /**< 4 Kilobyte erase command */
|
||||
bool sr_is_non_vola; /**< status register is supports non-volatile */
|
||||
uint8_t vola_sr_we_cmd; /**< volatile status register write enable command */
|
||||
bool addr_3_byte; /**< supports 3-Byte addressing */
|
||||
bool addr_4_byte; /**< supports 4-Byte addressing */
|
||||
uint32_t capacity; /**< flash capacity (bytes) */
|
||||
struct {
|
||||
uint32_t size; /**< erase sector size (bytes). 0x00: not available */
|
||||
uint8_t cmd; /**< erase command */
|
||||
} eraser[FLASH_SFDP_ERASE_TYPE_MAX_NUM]; /**< supported eraser types table */
|
||||
//TODO lots of fast read-related stuff (like modes supported and number of wait states/dummy cycles needed in each)
|
||||
} flash_sfdp, *flash_sfdp_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SPI device
|
||||
*/
|
||||
typedef struct __flash_spi {
|
||||
/* SPI device name */
|
||||
char *name;
|
||||
|
||||
/* SPI bus write read data function */
|
||||
flash_err (*wr)(const struct __flash_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
|
||||
size_t read_size);
|
||||
|
||||
#ifdef FLASH_USING_QSPI
|
||||
|
||||
/* QSPI fast read function */
|
||||
flash_err
|
||||
(*qspi_read)(const struct __flash_spi *spi, uint32_t addr, flash_qspi_read_cmd_format *qspi_read_cmd_format,
|
||||
uint8_t *read_buf, size_t read_size);
|
||||
|
||||
#endif
|
||||
|
||||
/* lock SPI bus */
|
||||
void (*lock)(const struct __flash_spi *spi);
|
||||
|
||||
/* unlock SPI bus */
|
||||
void (*unlock)(const struct __flash_spi *spi);
|
||||
|
||||
/* some user data */
|
||||
void *user_data;
|
||||
} flash_spi, *flash_spi_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_FLASH_DEF_H
|
||||
+56
-56
@@ -1,75 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef HW_LIB_OLED_FONT_CHUC_H
|
||||
#define HW_LIB_OLED_FONT_CHUC_H
|
||||
#ifndef HW_LIB_FONT_CHUC_H
|
||||
#define HW_LIB_FONT_CHUC_H
|
||||
|
||||
typedef struct {
|
||||
uint8_t unicode[2];
|
||||
uint8_t data[32];
|
||||
uint8_t data[128];
|
||||
} Chinese_t;
|
||||
|
||||
uint8_t Hzk_size = 16;
|
||||
static uint8_t Hzk_size=32;
|
||||
|
||||
Chinese_t Hzk[] = {
|
||||
static Chinese_t Hzk[] = {
|
||||
{
|
||||
// Original: 星
|
||||
{ 0x66, 0x1F },
|
||||
{
|
||||
// Original: ÐÇ
|
||||
{0x66, 0x1F},
|
||||
{
|
||||
0x00, 0x08, 0x3F, 0xFC, 0x20, 0x08, 0x3F, 0xF8, 0x20, 0x08, 0x3F, 0xF8, 0x01, 0x00, 0x21, 0x08,
|
||||
0x3F, 0xFC, 0x21, 0x00, 0x41, 0x10, 0xBF, 0xF8, 0x01, 0x00, 0x01, 0x04, 0xFF, 0xFE, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0x80, 0x01, 0xC0, 0x03, 0x80, 0x01, 0xC0, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0x80, 0x01, 0xC0, 0x03, 0x80, 0x01, 0xC0, 0x03, 0x80, 0x01, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0x80, 0x01, 0xC0, 0x01, 0x01, 0x81, 0x80, 0x01, 0x81, 0xC0, 0x00,
|
||||
0x01, 0xC1, 0x80, 0x40, 0x01, 0x81, 0x80, 0xE0, 0x03, 0xFF, 0xFF, 0xF0, 0x03, 0x01, 0x80, 0x00, 0x06, 0x01, 0x80, 0x00, 0x0C, 0x01, 0x80, 0x00, 0x08, 0x01, 0x81, 0x80, 0x11, 0xFF, 0xFF, 0xC0, 0x21, 0x01, 0x80, 0x00, 0x40, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18, 0x00, 0x01, 0x80, 0x3C, 0x3F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
{
|
||||
// Original: 海
|
||||
{ 0x6D, 0x77 },
|
||||
{
|
||||
// Original: º£
|
||||
{0x6D, 0x77},
|
||||
{
|
||||
0x02, 0x00, 0x42, 0x08, 0x33, 0xFC, 0x14, 0x00, 0x8B, 0xF8, 0x62, 0x88, 0x22, 0x48, 0x0A, 0x08,
|
||||
0x1F, 0xFE, 0x24, 0x88, 0xE4, 0x48, 0x24, 0x08, 0x27, 0xFC, 0x20, 0x08, 0x20, 0x28, 0x20, 0x10,
|
||||
}
|
||||
},
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x0E, 0x06, 0x00, 0x00, 0x07, 0x0E, 0x00, 0x30, 0x07, 0x0F, 0xFF, 0xF8, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x98, 0x00, 0x80, 0x70, 0xBF, 0xFF, 0xC0, 0x38, 0xAF, 0xFF, 0xC0, 0x19, 0xCC, 0xC1, 0xC0, 0x19, 0x8C, 0x61, 0xC0, 0x09, 0x1C, 0x71, 0xC0, 0x03, 0x1C, 0x31, 0xC0,
|
||||
0x03, 0x1C, 0x01, 0xC8, 0x02, 0xFF, 0xFF, 0xFC, 0x06, 0x18, 0x01, 0x80, 0x06, 0x18, 0xC1, 0x80, 0x06, 0x18, 0x61, 0x80, 0x0C, 0x38, 0x71, 0x80, 0x7C, 0x38, 0x71, 0x80, 0x1C, 0x30, 0x21, 0x88, 0x1C, 0x7F, 0xFF, 0xFC, 0x1C, 0x30, 0x01, 0x80, 0x1C, 0x00, 0x01, 0x80, 0x1C, 0x00, 0x63, 0x80, 0x1C, 0x00, 0x3F, 0x80, 0x1C, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
{
|
||||
// Original: 科
|
||||
{ 0x79, 0xD1 },
|
||||
{
|
||||
// Original: ¿Æ
|
||||
{0x79, 0xD1},
|
||||
{
|
||||
0x04, 0x10, 0x0E, 0x10, 0xF8, 0x90, 0x08, 0x50, 0x08, 0x10, 0xFE, 0x90, 0x08, 0x50, 0x1C, 0x14,
|
||||
0x1A, 0x1E, 0x29, 0xF0, 0x28, 0x10, 0x48, 0x10, 0x88, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10,
|
||||
}
|
||||
},
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x00, 0x3C, 0x00, 0xE0, 0x01, 0xFC, 0x00, 0xC0, 0x1F, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x60, 0xC0, 0x00, 0xC0, 0x30, 0xC0, 0x00, 0xC0, 0x38, 0xC0, 0x00, 0xC0, 0x18, 0xC0, 0x00, 0xC4, 0x18, 0xC0, 0x3F, 0xFE, 0x00, 0xC0, 0x3F, 0xFE, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0xC0, 0xC0, 0x01, 0xE0, 0x70, 0xC0,
|
||||
0x03, 0xF8, 0x30, 0xC0, 0x03, 0xDC, 0x30, 0xC8, 0x07, 0xCE, 0x00, 0xDC, 0x06, 0xC6, 0x00, 0xFE, 0x0C, 0xC0, 0x0F, 0xE0, 0x18, 0xC3, 0xF8, 0xC0, 0x10, 0xC7, 0x00, 0xC0, 0x20, 0xC0, 0x00, 0xC0, 0x40, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
{
|
||||
// Original: 技
|
||||
{ 0x62, 0x80 },
|
||||
{
|
||||
// Original: ¼¼
|
||||
{0x62, 0x80},
|
||||
{
|
||||
0x10, 0x40, 0x10, 0x40, 0x10, 0x48, 0x13, 0xFC, 0xFC, 0x40, 0x10, 0x40, 0x10, 0x40, 0x13, 0xF8,
|
||||
0x1A, 0x08, 0x31, 0x10, 0xD1, 0x10, 0x10, 0xA0, 0x10, 0x40, 0x10, 0xB0, 0x51, 0x0E, 0x26, 0x04,
|
||||
}
|
||||
},
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0xC0, 0x0E, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0x88, 0x0C, 0x18, 0x3F, 0xFF, 0xFF, 0xFC, 0x21, 0x80, 0x0C, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0x80, 0x0C, 0x00, 0x01, 0x8C, 0x0C, 0x20, 0x01, 0xFB, 0xFF, 0xF0,
|
||||
0x03, 0xE0, 0x80, 0x60, 0x1F, 0x80, 0xC0, 0xE0, 0x3F, 0x80, 0x40, 0xC0, 0x39, 0x80, 0x41, 0xC0, 0x01, 0x80, 0x61, 0xC0, 0x01, 0x80, 0x33, 0x80, 0x01, 0x80, 0x33, 0x00, 0x01, 0x80, 0x1F, 0x00, 0x01, 0x80, 0x1E, 0x00, 0x01, 0x80, 0x1E, 0x00, 0x01, 0x80, 0x3F, 0x00, 0x11, 0x80, 0xE3, 0xC0, 0x1F, 0x83, 0xC1, 0xFC, 0x07, 0x8F, 0x00, 0x7C, 0x03, 0x38, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
{
|
||||
// Original: 机
|
||||
{ 0x67, 0x3A },
|
||||
{
|
||||
// Original: »ú
|
||||
{0x67, 0x3A},
|
||||
{
|
||||
0x10, 0x00, 0x10, 0x10, 0x11, 0xF8, 0x11, 0x10, 0xFD, 0x10, 0x11, 0x10, 0x31, 0x10, 0x39, 0x10,
|
||||
0x55, 0x10, 0x51, 0x10, 0x91, 0x10, 0x11, 0x10, 0x11, 0x12, 0x12, 0x12, 0x14, 0x0E, 0x18, 0x00,
|
||||
}
|
||||
},
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x81, 0x01, 0x80, 0x03, 0x81, 0xFF, 0xC0, 0x03, 0x81, 0x81, 0xC0, 0x03, 0x81, 0x81, 0x80, 0x03, 0x91, 0x81, 0x80, 0x01, 0xB9, 0x81, 0x80, 0x3F, 0xFD, 0x81, 0x80, 0x03, 0x81, 0x81, 0x80, 0x03, 0x81, 0x81, 0x80, 0x03, 0x81, 0x81, 0x80, 0x03, 0xE1, 0x81, 0x80, 0x07, 0xF9, 0x81, 0x80,
|
||||
0x07, 0xBD, 0x81, 0x80, 0x07, 0x9D, 0x81, 0x80, 0x0F, 0x8D, 0x81, 0x80, 0x0F, 0x81, 0x81, 0x80, 0x1B, 0x81, 0x81, 0x80, 0x1B, 0x83, 0x81, 0x80, 0x33, 0x83, 0x01, 0x80, 0x23, 0x83, 0x01, 0x8C, 0x63, 0x83, 0x01, 0x8C, 0x03, 0x86, 0x01, 0x8C, 0x03, 0x86, 0x01, 0x8C, 0x03, 0x8C, 0x01, 0x8E, 0x03, 0x98, 0x01, 0xFE, 0x03, 0xB0, 0x00, 0xFC, 0x03, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
{
|
||||
// Original: 械
|
||||
{ 0x68, 0xB0 },
|
||||
{
|
||||
// Original: е
|
||||
{0x68, 0xB0},
|
||||
{
|
||||
0x10, 0x20, 0x10, 0x28, 0x10, 0x24, 0x17, 0xFE, 0xFC, 0x20, 0x12, 0xA0, 0x32, 0xA0, 0x3A, 0xA4,
|
||||
0x57, 0xE4, 0x52, 0xA8, 0x92, 0xA8, 0x12, 0x90, 0x14, 0xB0, 0x18, 0x52, 0x10, 0x8A, 0x13, 0x06,
|
||||
}
|
||||
},
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x07, 0xC0, 0x03, 0x00, 0x06, 0x70, 0x03, 0x00, 0x06, 0x30, 0x03, 0x00, 0x06, 0x30, 0x03, 0x00, 0x06, 0x00, 0x03, 0x20, 0x06, 0x1C, 0x3F, 0xF7, 0xFF, 0xFC, 0x3F, 0xF0, 0x06, 0x00, 0x07, 0x06, 0xE6, 0x00, 0x07, 0x06, 0xE6, 0x20, 0x07, 0xC6, 0xE6, 0x38, 0x07, 0xE6, 0xE6, 0x38, 0x07, 0x76, 0xE6, 0x30,
|
||||
0x0F, 0x26, 0xE6, 0x30, 0x0F, 0x3F, 0xFE, 0x70, 0x1B, 0x3F, 0xFE, 0x60, 0x1B, 0x06, 0xE7, 0x60, 0x13, 0x06, 0xE3, 0xC0, 0x33, 0x06, 0xE3, 0xC0, 0x23, 0x0C, 0xE3, 0x80, 0x43, 0x0C, 0xE3, 0x84, 0x03, 0x0C, 0xE3, 0x84, 0x03, 0x18, 0xE7, 0xC4, 0x03, 0x18, 0xEC, 0xEC, 0x03, 0x30, 0xD8, 0x7C, 0x03, 0x20, 0x30, 0x3C, 0x03, 0x40, 0xE0, 0x1C, 0x03, 0x03, 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
{
|
||||
// Original: 师
|
||||
{ 0x5E, 0x08 },
|
||||
{
|
||||
// Original: ʦ
|
||||
{0x5E, 0x08},
|
||||
{
|
||||
0x08, 0x04, 0x0B, 0xFE, 0x48, 0x20, 0x48, 0x24, 0x49, 0xFE, 0x49, 0x24, 0x49, 0x24, 0x49, 0x24,
|
||||
0x49, 0x24, 0x49, 0x24, 0x49, 0x24, 0x49, 0x24, 0x11, 0x34, 0x11, 0x28, 0x20, 0x20, 0x40, 0x20,
|
||||
}
|
||||
},
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x18, 0x00, 0xEF, 0xFF, 0xFC, 0x00, 0xE6, 0x0C, 0x00, 0x10, 0xE0, 0x0C, 0x00, 0x1C, 0xE0, 0x0C, 0x00, 0x1C, 0xE0, 0x0C, 0x00, 0x1C, 0xE0, 0x0C, 0x10, 0x1C, 0xE7, 0xFF, 0xF8, 0x1C, 0xE7, 0xFF, 0xF8, 0x1C, 0xE6, 0x0C, 0x18, 0x1C, 0xE6, 0x0C, 0x18, 0x1C, 0xC6, 0x0C, 0x18, 0x1C, 0xC6, 0x0C, 0x18,
|
||||
0x1C, 0xC6, 0x0C, 0x18, 0x1C, 0xC6, 0x0C, 0x18, 0x1C, 0xC6, 0x0C, 0x18, 0x1C, 0xC6, 0x0C, 0x18, 0x1C, 0xC6, 0x0C, 0x18, 0x1D, 0xC6, 0x0C, 0x18, 0x1D, 0x86, 0x0C, 0x18, 0x19, 0x86, 0x0D, 0xF8, 0x03, 0x86, 0x0C, 0x70, 0x03, 0x06, 0x0C, 0x20, 0x06, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x1C, 0x00, 0x10, 0x00, 0x1C, 0x00, 0x20, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Chinese_t *find_chinese_data(uint8_t unicode_high, uint8_t unicode_low) {
|
||||
static Chinese_t* find_chinese_data(uint8_t unicode_high, uint8_t unicode_low) {
|
||||
for (int i = 0; i < sizeof(Hzk) / sizeof(Chinese_t); ++i) {
|
||||
if (Hzk[i].unicode[0] == unicode_high && Hzk[i].unicode[1] == unicode_low) {
|
||||
return &Hzk[i];
|
||||
@@ -78,4 +78,4 @@ Chinese_t *find_chinese_data(uint8_t unicode_high, uint8_t unicode_low) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif //HW_LIB_OLED_FONT_CHUC_H
|
||||
#endif //HW_LIB_FONT_CHUC_H
|
||||
+1
-1
@@ -6,7 +6,7 @@ extern "C" {
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#define KEY_TICKS_INTERVAL 5 // 定时器间隔时间,单位为毫秒
|
||||
#define DEBOUNCE_TICKS 0 // 按键去抖动计数阈值,最大为7(0 ~ 7)
|
||||
#define SHORT_TICKS (300 / KEY_TICKS_INTERVAL) // 短按阈值,单位为定时器间隔的倍数
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
#include "hash_table.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
static Hash_Item_t HT_DELETED_ITEM = {NULL, NULL};
|
||||
|
||||
static Hash_Item_t* ht_new_item(const char* k, const char* v) {
|
||||
Hash_Item_t* i = (Hash_Item_t*)malloc(sizeof(Hash_Item_t));
|
||||
i->key = strdup(k);
|
||||
i->value = strdup(v);
|
||||
return i;
|
||||
}
|
||||
|
||||
static int ht_hash(const char* s, const int a, const int m) {
|
||||
long hash = 0;
|
||||
const int len_s = strlen(s);
|
||||
for (int i = 0; i < len_s; i++) {
|
||||
hash += (long)pow(a, len_s - (i+1)) * s[i];
|
||||
hash = hash % m;
|
||||
}
|
||||
return (int)hash;
|
||||
}
|
||||
|
||||
static int ht_get_hash(
|
||||
const char* s, const int num_buckets, const int attempt
|
||||
) {
|
||||
const int hash_a = ht_hash(s, HT_PRIME_1, num_buckets);
|
||||
const int hash_b = ht_hash(s, HT_PRIME_2, num_buckets);
|
||||
return (hash_a + (attempt * (hash_b + 1))) % num_buckets;
|
||||
}
|
||||
static void ht_del_item(Hash_Item_t* i) {
|
||||
free(i->key);
|
||||
free(i->value);
|
||||
free(i);
|
||||
}
|
||||
|
||||
void ht_del_hash_table(Hash_Table_t* ht) {
|
||||
for (int i = 0; i < ht->size; i++) {
|
||||
Hash_Item_t* item = ht->items[i];
|
||||
if (item != NULL) {
|
||||
ht_del_item(item);
|
||||
}
|
||||
}
|
||||
free(ht->items);
|
||||
free(ht);
|
||||
}
|
||||
|
||||
int is_prime(const int x) {
|
||||
if (x < 2) { return -1; }
|
||||
if (x < 4) { return 1; }
|
||||
if ((x % 2) == 0) { return 0; }
|
||||
for (int i = 3; i <= floor(sqrt((double) x)); i += 2) {
|
||||
if ((x % i) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int next_prime(int x) {
|
||||
while (is_prime(x) != 1) {
|
||||
x++;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static Hash_Table_t* ht_new_sized(const int base_size) {
|
||||
Hash_Table_t* ht = (Hash_Table_t*)malloc(sizeof(Hash_Table_t));
|
||||
ht->base_size = base_size;
|
||||
|
||||
ht->size = next_prime(ht->base_size);
|
||||
|
||||
ht->count = 0;
|
||||
ht->items = (Hash_Item_t**) calloc((size_t)ht->size, sizeof(Hash_Item_t*));
|
||||
return ht;
|
||||
}
|
||||
|
||||
Hash_Table_t* ht_new() {
|
||||
return ht_new_sized(HT_INITIAL_BASE_SIZE);
|
||||
}
|
||||
|
||||
static void ht_resize(Hash_Table_t* ht, const int base_size) {
|
||||
if (base_size < HT_INITIAL_BASE_SIZE) {
|
||||
return;
|
||||
}
|
||||
Hash_Table_t* new_ht = ht_new_sized(base_size);
|
||||
for (int i = 0; i < ht->size; i++) {
|
||||
Hash_Item_t* item = ht->items[i];
|
||||
if (item != NULL && item != &HT_DELETED_ITEM) {
|
||||
ht_insert(new_ht, item->key, item->value);
|
||||
}
|
||||
}
|
||||
|
||||
ht->base_size = new_ht->base_size;
|
||||
ht->count = new_ht->count;
|
||||
|
||||
// To delete new_ht, we give it ht's size and items
|
||||
const int tmp_size = ht->size;
|
||||
ht->size = new_ht->size;
|
||||
new_ht->size = tmp_size;
|
||||
|
||||
Hash_Item_t** tmp_items = ht->items;
|
||||
ht->items = new_ht->items;
|
||||
new_ht->items = tmp_items;
|
||||
|
||||
ht_del_hash_table(new_ht);
|
||||
}
|
||||
|
||||
static void ht_resize_up(Hash_Table_t* ht) {
|
||||
const int new_size = ht->base_size * 2;
|
||||
ht_resize(ht, new_size);
|
||||
}
|
||||
|
||||
|
||||
static void ht_resize_down(Hash_Table_t* ht) {
|
||||
const int new_size = ht->base_size / 2;
|
||||
ht_resize(ht, new_size);
|
||||
}
|
||||
|
||||
void ht_insert(Hash_Table_t* ht, const char* key, const char* value) {
|
||||
const int load = ht->count * 100 / ht->size;
|
||||
if (load > 70) {
|
||||
ht_resize_up(ht);
|
||||
}
|
||||
Hash_Item_t* item = ht_new_item(key, value);
|
||||
int index = ht_get_hash(item->key, ht->size, 0);
|
||||
Hash_Item_t* cur_item = ht->items[index];
|
||||
int i = 1;
|
||||
while (cur_item != NULL) {
|
||||
if (cur_item != &HT_DELETED_ITEM) {
|
||||
if (strcmp(cur_item->key, key) == 0) {
|
||||
ht_del_item(cur_item);
|
||||
ht->items[index] = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
index = ht_get_hash(item->key, ht->size, i);
|
||||
cur_item = ht->items[index];
|
||||
i++;
|
||||
}
|
||||
ht->items[index] = item;
|
||||
ht->count++;
|
||||
}
|
||||
|
||||
char* ht_search(Hash_Table_t* ht, const char* key) {
|
||||
int index = ht_get_hash(key, ht->size, 0);
|
||||
Hash_Item_t* item = ht->items[index];
|
||||
int i = 1;
|
||||
while (item != NULL) {
|
||||
if (item != &HT_DELETED_ITEM) {
|
||||
if (strcmp(item->key, key) == 0) {
|
||||
return item->value;
|
||||
}
|
||||
}
|
||||
index = ht_get_hash(key, ht->size, i);
|
||||
item = ht->items[index];
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ht_delete(Hash_Table_t* ht, const char* key) {
|
||||
const int load = ht->count * 100 / ht->size;
|
||||
if (load < 10) {
|
||||
ht_resize_down(ht);
|
||||
}
|
||||
int index = ht_get_hash(key, ht->size, 0);
|
||||
Hash_Item_t* item = ht->items[index];
|
||||
int i = 1;
|
||||
while (item != NULL) {
|
||||
if (item != &HT_DELETED_ITEM) {
|
||||
if (strcmp(item->key, key) == 0) {
|
||||
ht_del_item(item);
|
||||
ht->items[index] = &HT_DELETED_ITEM;
|
||||
}
|
||||
}
|
||||
index = ht_get_hash(key, ht->size, i);
|
||||
item = ht->items[index];
|
||||
i++;
|
||||
}
|
||||
ht->count--;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#ifndef HW_LIB_HASH_TABLE_H
|
||||
#define HW_LIB_HASH_TABLE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HT_PRIME_1 151
|
||||
#define HT_PRIME_2 163
|
||||
#define HT_INITIAL_BASE_SIZE 53
|
||||
|
||||
|
||||
typedef struct Hash_Item
|
||||
{
|
||||
char* key;
|
||||
char* value;
|
||||
} Hash_Item_t;
|
||||
|
||||
typedef struct Hash_Table
|
||||
{
|
||||
int base_size;
|
||||
int size;
|
||||
int count;
|
||||
Hash_Item_t** items;
|
||||
} Hash_Table_t;
|
||||
|
||||
Hash_Table_t* ht_new();
|
||||
void ht_del_hash_table(Hash_Table_t* ht);
|
||||
void ht_insert(Hash_Table_t* ht, const char* key, const char* value);
|
||||
char* ht_search(Hash_Table_t* ht, const char* key);
|
||||
void ht_delete(Hash_Table_t* h, const char* key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_HASH_TABLE_H
|
||||
File diff suppressed because it is too large
Load Diff
+6376
File diff suppressed because it is too large
Load Diff
+5
-3
@@ -4,7 +4,7 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stdbool.h"
|
||||
#include "stdint.h"
|
||||
|
||||
|
||||
@@ -95,15 +95,17 @@ struct OLED_Dev
|
||||
* @return void
|
||||
* @example OLED_Init(&oled_dev);
|
||||
*/
|
||||
void OLED_Init(OLED_T* dev);
|
||||
void OLED_Init(OLED_T *dev);
|
||||
|
||||
/**
|
||||
* @brief OLED初始化
|
||||
* @param dev: [输入] OLED设备指针
|
||||
* @param cmd: [输入] OLED初始化指令表
|
||||
* @param len: [输入] OLED初始化指令表长度
|
||||
* @return void
|
||||
* @example OLED_Init(&oled_dev);
|
||||
*/
|
||||
void OLED_Init_CMD(OLED_T* dev, uint8_t* cmd, uint16_t len);
|
||||
void OLED_Init_CMD(OLED_T *dev, uint8_t *cmd, uint16_t len);
|
||||
/**
|
||||
* @brief 打开OLED显示
|
||||
* @param dev: [输入] OLED设备指针
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@ const uint8_t initCmd[] = {
|
||||
0x40, 0x00, // 设置显示起始行
|
||||
0x8D, 0x14, // 电荷泵设置
|
||||
0x20, 0x00, // 设置内存寻址模式
|
||||
0xA0, // 设置段重映射
|
||||
0xC8, // 设置COM输出扫描方向
|
||||
0xA0, // 设置段重映射 从左到右A1 //左右翻转A0
|
||||
0xC8, // 设置COM输出扫描方向 从上到下C8 //上下颠倒C0
|
||||
0xDA, 0x12, // 设置COM引脚硬件配置
|
||||
0x81, 0xCF, // 设置对比度控制
|
||||
0xD9, 0xF1, // 设置预充电周期
|
||||
|
||||
+635
-656
File diff suppressed because it is too large
Load Diff
+10
-4
@@ -118,7 +118,6 @@ extern "C" {
|
||||
/**
|
||||
* @brief LCD_Type_Define
|
||||
*/
|
||||
#define ST7735_1_8_inch_screen 0x00U
|
||||
#define ST7735_0_9_inch_screen 0x01U
|
||||
#define ST7735_1_8a_inch_screen 0x02U
|
||||
/**
|
||||
@@ -135,9 +134,13 @@ extern "C" {
|
||||
|
||||
|
||||
#define ST7735_DELAY 120
|
||||
#define ST7735_PANEL HannStar_Panel
|
||||
#define ST7735_TYPE ST7735_0_9_inch_screen
|
||||
#define ST7735_PANEL BOE_Panel
|
||||
#define ST7735_TYPE ST7735_1_8a_inch_screen
|
||||
|
||||
//#define ST7735_X_OFFSET 0
|
||||
//#define ST7735_Y_OFFSET 0
|
||||
//#define ST7735_X_OFFSET 0
|
||||
//#define ST7735_Y_OFFSET 0
|
||||
|
||||
#if ST7735_TYPE == ST7735_0_9_inch_screen //0.96 ST7735
|
||||
#if ST7735_PANEL == HannStar_Panel
|
||||
@@ -176,8 +179,11 @@ const uint8_t st7735initcmd[] = {
|
||||
3, ST7735_PWR_CTRL4, 0x8A, 0x2A,
|
||||
3, ST7735_PWR_CTRL5, 0x8A, 0xEE,
|
||||
2, ST7735_VCOMH_VCOML_CTRL1, 0x0E,
|
||||
#if ST7735_PANEL == HannStar_Panel
|
||||
1, ST7735_DISPLAY_INVERSION_ON,//HannStar_Panel
|
||||
// 1,ST7735_DISPLAY_INVERSION_OFF,//BOE_Panel
|
||||
#else
|
||||
1, ST7735_DISPLAY_INVERSION_OFF,//BOE_Panel
|
||||
#endif
|
||||
2, ST7735_COLOR_MODE, ST7735_FORMAT_RBG565,
|
||||
17, ST7735_PV_GAMMA_CTRL, 0x02, 0x1C, 0x07U, 0x12U, 0x37U, 0x32U, 0x29U, 0x2DU, 0x29U, 0x25U, 0x2BU, 0x39U,
|
||||
0x00U, 0x01U, 0x03U, 0x10U,
|
||||
|
||||
+114
-20
@@ -8,24 +8,54 @@ extern "C" {
|
||||
#include "stdint.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
|
||||
/*功能配置区*/
|
||||
//#define REFRESH_CALL_ENABLE 1 //使用DMA或者整体刷新函数
|
||||
#define HZK_FONT //使用HZK 12/16 字体 tools下可自由生成
|
||||
#define UTF8_TO_UNICODE //启用UTF8转换显示
|
||||
//#define LVGL_FONT //启用LVGL字体
|
||||
|
||||
/*启用设备配置区*/
|
||||
#define TFT_ST7735 0x5CU
|
||||
#define TFT_ST7796 0xACU
|
||||
#define TFT_ST7796 0x1E74U
|
||||
|
||||
typedef struct TFT_Dev TFT_T;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 写寄存器数据函数指针类型
|
||||
* @param reg: [输入] 寄存器地址
|
||||
* @param pdata: [输入] 数据缓冲区指针
|
||||
* @param ldata: [输入] 数据长度
|
||||
* @return uint8_t 返回状态
|
||||
* @example write_status = TFT_WRITE_REG(reg_addr, data_buffer, data_length);
|
||||
**/
|
||||
typedef uint8_t (*TFT_WRITE_REG_t)(uint8_t reg, uint8_t *pdata, size_t ldata);
|
||||
|
||||
/**
|
||||
* @brief 读寄存器数据函数指针类型
|
||||
* @param reg: [输入] 寄存器地址
|
||||
* @param pdata: [输出] 数据缓冲区指针
|
||||
* @param ldata: [输入] 数据长度
|
||||
* @return uint8_t 返回状态
|
||||
* @example read_status = TFT_READ_REG(reg_addr, data_buffer, data_length);
|
||||
**/
|
||||
typedef uint8_t (*TFT_READ_REG_t)(uint8_t reg, uint8_t *pdata, size_t ldata);
|
||||
|
||||
/**
|
||||
* @brief 发送数据函数指针类型
|
||||
* @param data: [输入] 数据缓冲区指针
|
||||
* @param len: [输入] 数据长度
|
||||
* @return uint8_t 返回状态
|
||||
* @example send_status = TFT_SEND_DATA(data_buffer, data_length);
|
||||
**/
|
||||
typedef uint8_t (*TFT_SEND_DATA_t)(uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief 接收数据函数指针类型
|
||||
* @param data: [输出] 数据缓冲区指针
|
||||
* @param len: [输入] 数据长度
|
||||
* @return uint8_t 返回状态
|
||||
* @example recv_status = TFT_RECV_DATA(data_buffer, data_length);
|
||||
**/
|
||||
typedef uint8_t (*TFT_RECV_DATA_t)(uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
@@ -55,7 +85,7 @@ typedef void (*TFT_REFRESH_t)(TFT_T *dev);
|
||||
* @brief TFT状态枚举
|
||||
*/
|
||||
typedef enum {
|
||||
TFT_ERROR,
|
||||
TFT_ERROR,/**< 错误状态 */
|
||||
TFT_IDLE, /**< 空闲状态 */
|
||||
TFT_WRITE, /**< 写入状态 */
|
||||
TFT_REFRESH, /**< 刷新状态 */
|
||||
@@ -78,24 +108,25 @@ typedef union TFT_Color {
|
||||
* @brief TFT设备结构体
|
||||
*/
|
||||
struct TFT_Dev {
|
||||
uint32_t id;
|
||||
uint8_t setxcmd;
|
||||
uint8_t setycmd;
|
||||
uint8_t wgramcmd;
|
||||
TFT_DIR_T dir: 4; /**< 显示方向,占4位 */
|
||||
TFT_STATE_T state: 4; /**< TFT状态,占4位 */
|
||||
uint16_t width; /**< 显示宽度 */
|
||||
uint16_t height; /**< 显示高度 */
|
||||
TFT_WRITE_REG_t writeReg; /**< 写寄存器函数指针 */
|
||||
TFT_READ_REG_t readReg; /**< 读寄存器函数指针 */
|
||||
TFT_SEND_DATA_t sendData; /**< 发送数据函数指针 */
|
||||
TFT_RECV_DATA_t recvData; /**< 接收数据函数指针 */
|
||||
TFT_BLACKLIGHT_t blacklight; /**< TFT背光控制函数指针 */
|
||||
TFT_DELAY_t delay; /**< TFT延迟函数指针类型 */
|
||||
uint32_t id; /**< TFT设备ID */
|
||||
uint8_t setxcmd; /**< 设置X坐标命令 */
|
||||
uint8_t setycmd; /**< 设置Y坐标命令 */
|
||||
uint8_t wgramcmd; /**< 写GRAM命令 */
|
||||
TFT_DIR_T dir: 4; /**< 显示方向,占4位 */
|
||||
TFT_STATE_T state: 4; /**< TFT状态,占4位 */
|
||||
uint16_t width; /**< 显示宽度 */
|
||||
uint16_t height; /**< 显示高度 */
|
||||
TFT_WRITE_REG_t writeReg; /**< 写寄存器函数指针 */
|
||||
TFT_READ_REG_t readReg; /**< 读寄存器函数指针 */
|
||||
TFT_SEND_DATA_t sendData; /**< 发送数据函数指针 */
|
||||
TFT_RECV_DATA_t recvData; /**< 接收数据函数指针 */
|
||||
TFT_BLACKLIGHT_t blacklight; /**< TFT背光控制函数指针 */
|
||||
TFT_DELAY_t delay; /**< TFT延迟函数指针类型 */
|
||||
#if REFRESH_CALL_ENABLE
|
||||
TFT_REFRESH_t call; /**< TFT刷新函数指针,仅在REFRESH_CALL_ENABLE宏定义启用时有效 */
|
||||
TFT_REFRESH_t call; /**< TFT刷新函数指针,仅在REFRESH_CALL_ENABLE宏定义启用时有效 */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 初始化TFT显示屏
|
||||
* @param dev: [输入] TFT设备结构体指针
|
||||
@@ -252,6 +283,8 @@ void TFT_DrawRect(TFT_T *dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2
|
||||
**/
|
||||
void TFT_DrawCircle(TFT_T *dev, uint16_t x, uint16_t y, uint16_t r);
|
||||
|
||||
void TFT_DrawArc(TFT_T *dev, uint16_t x0, uint16_t y0, uint16_t radius, int start_angle, int end_angle);
|
||||
|
||||
/**
|
||||
* @brief 在TFT显示屏上显示单个字符
|
||||
* @param dev: [输入] TFT设备结构体指针
|
||||
@@ -317,6 +350,53 @@ void TFT_ShowNum(TFT_T *dev, uint16_t x, uint16_t y, uint32_t num, uint16_t len,
|
||||
**/
|
||||
void TFT_ShowPic(TFT_T *dev, uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, TFT_Color_t *bmp);
|
||||
|
||||
/**
|
||||
* @brief 在屏幕上绘制一个十字交叉线
|
||||
* @param dev: [输入] TFT设备指针
|
||||
* @param x: [输入] 十字交叉线中心点x坐标
|
||||
* @param y: [输入] 十字交叉线中心点y坐标
|
||||
* @param r: [输入] 十字交叉线长度的一半(即从中心点到横竖线的长度)
|
||||
* @return void
|
||||
* @example TFT_DrawCross(&tft_dev, 100, 80, 5);
|
||||
**/
|
||||
void TFT_DrawCross(TFT_T *dev, uint16_t x, uint16_t y, uint8_t r);
|
||||
|
||||
/**
|
||||
* @brief 在屏幕上绘制一个X字交叉线
|
||||
* @param dev: [输入] TFT设备指针
|
||||
* @param x: [输入] 十字交叉线中心点x坐标
|
||||
* @param y: [输入] 十字交叉线中心点y坐标
|
||||
* @param r: [输入] 十字交叉线长度的一半(即从中心点到横竖线的长度)
|
||||
* @return void
|
||||
* @example TFT_DrawCross(&tft_dev, 100, 80, 5);
|
||||
**/
|
||||
void TFT_DrawXCross(TFT_T *dev, uint16_t x, uint16_t y, uint8_t r);
|
||||
|
||||
/**
|
||||
* @brief 在屏幕上显示进度条
|
||||
* @param dev: [输入] TFT设备指针
|
||||
* @param x: [输入] 进度条左上角x坐标
|
||||
* @param y: [输入] 进度条左上角y坐标
|
||||
* @param width: [输入] 进度条宽度
|
||||
* @param height: [输入] 进度条高度
|
||||
* @param progress: [输入] 进度值,范围[0.0, 1.0]
|
||||
* @return void
|
||||
* @example TFT_ShowBar(&tft_device, 10, 20, 100, 10, 0.75);
|
||||
**/
|
||||
void TFT_ShowBar(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height, float progress);
|
||||
|
||||
/**
|
||||
* @brief 绘制带圆角的矩形
|
||||
* @param dev: [输入] TFT设备指针
|
||||
* @param x: [输入] 矩形左上角x坐标
|
||||
* @param y: [输入] 矩形左上角y坐标
|
||||
* @param width: [输入] 矩形宽度
|
||||
* @param height: [输入] 矩形高度
|
||||
* @param radius: [输入] 圆角半径
|
||||
* @return void
|
||||
**/
|
||||
void TFT_DrawRoundedRect(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t radius);
|
||||
|
||||
#ifdef LVGL_FONT
|
||||
|
||||
#include "lvgl_font.h"
|
||||
@@ -333,8 +413,22 @@ void TFT_ShowPic(TFT_T *dev, uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, T
|
||||
* @example TFT_DisplayString(&oled_device, &font_arial_16, "Hello World", 10, 20,bool mode);
|
||||
**/
|
||||
void TFT_DisplayString(TFT_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define ARGB_TO_RGB565(...) \
|
||||
_ARGB_TO_RGB565_NARG(__VA_ARGS__, _ARGB_TO_RGB565_4, _ARGB_TO_RGB565_1)(__VA_ARGS__)
|
||||
|
||||
#define _ARGB_TO_RGB565_NARG(...) _ARGB_TO_RGB565_NARG_(__VA_ARGS__, _ARGB_TO_RGB565_RSEQ_N())
|
||||
#define _ARGB_TO_RGB565_NARG_(...) _ARGB_TO_RGB565_ARG_N(__VA_ARGS__)
|
||||
|
||||
#define _ARGB_TO_RGB565_ARG_N(_1, _2, _3, _4, N, ...) N
|
||||
#define _ARGB_TO_RGB565_RSEQ_N() 4, 3, 2, 1, 0
|
||||
|
||||
#define _ARGB_TO_RGB565_1(argb) (((((argb) >> 8) & 0xF800) | (((argb) >> 5) & 0x07E0) | ((argb) >> 3) & 0x001F)
|
||||
|
||||
#define _ARGB_TO_RGB565_4(a, r, g, b) (((((a) & 0xFF) >> 3) << 11) | ((((r) & 0xFF) >> 2) << 5) | (((g) & 0xFF) >> 3))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+194
-28
@@ -1,3 +1,4 @@
|
||||
#include <valarray>
|
||||
#include "tft.h"
|
||||
#include "ascii_font.h"
|
||||
|
||||
@@ -14,7 +15,7 @@
|
||||
#include "ST7796.h"
|
||||
#endif
|
||||
|
||||
|
||||
const uint8_t initcmd[] = {0};
|
||||
TFT_Color_t POINT_COLOR;
|
||||
TFT_Color_t BACK_COLOR;
|
||||
uint8_t *cmdIndex;
|
||||
@@ -24,6 +25,7 @@ void TFT_Init(TFT_T *dev) {
|
||||
return;
|
||||
}
|
||||
uint8_t count, temp;
|
||||
cmdIndex = (uint8_t *) initcmd;
|
||||
#ifdef TFT_ST7735
|
||||
if (dev->id==ST7735_ID) {
|
||||
cmdIndex= (uint8_t *) st7735initcmd;
|
||||
@@ -200,11 +202,11 @@ void TFT_FillColor(TFT_T *dev,TFT_Color_t color){
|
||||
dev->sendData(color.u8, 2);
|
||||
}
|
||||
|
||||
|
||||
#define swap_(a, b) (a=(a)+(b),b=(a)-(b),a=(a)-(b))
|
||||
|
||||
void TFT_DrawLine(TFT_T *dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
|
||||
uint16_t i, k, k1, k2;
|
||||
if ((x1 < 0) || (x2 > dev->width) || (y1 < 0) || (y2 > dev->height) || (x1 > x2) || (y1 > y2))return;
|
||||
uint16_t i;
|
||||
if ((x1 < 0) || (x2 > dev->width) || (y1 < 0) || (y2 > dev->height))return;
|
||||
if (x1 == x2) //画竖线
|
||||
{
|
||||
for (i = 0; i < (y2 - y1); i++) {
|
||||
@@ -216,12 +218,50 @@ void TFT_DrawLine(TFT_T *dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2
|
||||
TFT_SetPixel(dev, x1 + i, y1,POINT_COLOR);
|
||||
}
|
||||
} else //画斜线
|
||||
{
|
||||
k1 = y2 - y1;
|
||||
k2 = x2 - x1;
|
||||
k = k1 * 10 / k2;
|
||||
for (i = 0; i < (x2 - x1); i++) {
|
||||
TFT_SetPixel(dev, x1 + i, y1 + i * k / 10,POINT_COLOR);
|
||||
{//Bresenham算法
|
||||
int p, twoDy, twoDyMinusDx, s1, s2;
|
||||
int dx = abs(x2 - x1), dy = abs(y2 - y1);
|
||||
if (dy > dx) //斜率大于1
|
||||
{
|
||||
p = 2 * dx - dy;
|
||||
twoDy = 2 * dx;
|
||||
twoDyMinusDx = 2 * (dx - dy);
|
||||
if (y1 > y2)//斜率为负时 反转斜率
|
||||
{
|
||||
swap_(x1, x2);
|
||||
swap_(y1, y2);
|
||||
}
|
||||
s1 = x2 > x1 ? 1 : -1;
|
||||
TFT_SetPixel(dev, x1, y1, POINT_COLOR);
|
||||
while (y1 < y2) {
|
||||
y1++;
|
||||
if (p < 0) { p += twoDy; }
|
||||
else {
|
||||
x1 += s1;
|
||||
p += twoDyMinusDx;
|
||||
}
|
||||
TFT_SetPixel(dev, x1, y1, POINT_COLOR);
|
||||
}
|
||||
} else {
|
||||
p = 2 * dy - dx;
|
||||
twoDy = 2 * dy;
|
||||
twoDyMinusDx = 2 * (dy - dx);
|
||||
if (x1 > x2)//斜率为负时 反转斜率
|
||||
{
|
||||
swap_(x1, x2);
|
||||
swap_(y1, y2);
|
||||
}
|
||||
s2 = y2 > y1 ? 1 : -1;
|
||||
TFT_SetPixel(dev, x1, y1, POINT_COLOR);
|
||||
while (x1 < x2) {
|
||||
x1++;
|
||||
if (p < 0) { p += twoDy; }
|
||||
else {
|
||||
y1 += s2;
|
||||
p += twoDyMinusDx;
|
||||
}
|
||||
TFT_SetPixel(dev, x1, y1, POINT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,29 +273,98 @@ void TFT_DrawRect(TFT_T *dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2
|
||||
TFT_DrawLine(dev, x1, y2, x2, y2); // Bottom side
|
||||
}
|
||||
|
||||
void TFT_DrawCircle(TFT_T *dev, uint16_t x, uint16_t y, uint16_t r) {
|
||||
int a, b, num;
|
||||
a = 0;
|
||||
b = r;
|
||||
while (2 * b * b >= r * r) {
|
||||
TFT_SetPixel(dev, x + a, y - b,POINT_COLOR);
|
||||
TFT_SetPixel(dev, x - a, y - b,POINT_COLOR);
|
||||
TFT_SetPixel(dev, x - a, y + b,POINT_COLOR);
|
||||
TFT_SetPixel(dev, x + a, y + b,POINT_COLOR);
|
||||
TFT_SetPixel(dev, x + b, y + a,POINT_COLOR);
|
||||
TFT_SetPixel(dev, x + b, y - a,POINT_COLOR);
|
||||
TFT_SetPixel(dev, x - b, y - a,POINT_COLOR);
|
||||
TFT_SetPixel(dev, x - b, y + a,POINT_COLOR);
|
||||
void TFT_DrawCircle(TFT_T *dev, uint16_t x0, uint16_t y0, uint16_t radius) {
|
||||
int x = radius;
|
||||
int y = 0;
|
||||
int decision = 1 - x;
|
||||
|
||||
a++;
|
||||
num = (a * a + b * b) - r * r;//计算画的点离圆心的距离
|
||||
if (num > 0) {
|
||||
b--;
|
||||
a--;
|
||||
while (y <= x) {
|
||||
TFT_SetPixel(dev, x0 + x, y0 + y, POINT_COLOR);
|
||||
TFT_SetPixel(dev, x0 + y, y0 + x, POINT_COLOR);
|
||||
TFT_SetPixel(dev, x0 - y, y0 + x, POINT_COLOR);
|
||||
TFT_SetPixel(dev, x0 - x, y0 + y, POINT_COLOR);
|
||||
TFT_SetPixel(dev, x0 - x, y0 - y, POINT_COLOR);
|
||||
TFT_SetPixel(dev, x0 - y, y0 - x, POINT_COLOR);
|
||||
TFT_SetPixel(dev, x0 + y, y0 - x, POINT_COLOR);
|
||||
TFT_SetPixel(dev, x0 + x, y0 - y, POINT_COLOR);
|
||||
|
||||
y++;
|
||||
|
||||
if (decision <= 0) {
|
||||
decision += 2 * y + 1;
|
||||
} else {
|
||||
x--;
|
||||
decision += 2 * (y - x) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PI 3.14159265359
|
||||
|
||||
#define PI 3.14159265359
|
||||
|
||||
//void TFT_DrawArc(TFT_T *dev, uint16_t x0, uint16_t y0, uint16_t radius, int start_angle, int end_angle) {
|
||||
// int x = radius;
|
||||
// int y = 0;
|
||||
// int decision = 1 - x;
|
||||
// int change = 4 * (1 - x);
|
||||
//
|
||||
// int angle = start_angle;
|
||||
//
|
||||
// while (y <= x) {
|
||||
// if (angle >= start_angle && angle <= end_angle) {
|
||||
// TFT_SetPixel(dev, x0 + x, y0 + y, POINT_COLOR);
|
||||
// TFT_SetPixel(dev, x0 + y, y0 + x, POINT_COLOR);
|
||||
// TFT_SetPixel(dev, x0 - y, y0 + x, POINT_COLOR);
|
||||
// TFT_SetPixel(dev, x0 - x, y0 + y, POINT_COLOR);
|
||||
// TFT_SetPixel(dev, x0 - x, y0 - y, POINT_COLOR);
|
||||
// TFT_SetPixel(dev, x0 - y, y0 - x, POINT_COLOR);
|
||||
// TFT_SetPixel(dev, x0 + y, y0 - x, POINT_COLOR);
|
||||
// TFT_SetPixel(dev, x0 + x, y0 - y, POINT_COLOR);
|
||||
// }
|
||||
//
|
||||
// if (decision <= 0) {
|
||||
// decision += 2 * y + 1;
|
||||
// change += 2;
|
||||
// } else {
|
||||
// x--;
|
||||
// decision += 2 * (y - x) + 1;
|
||||
// change += 4 * ((y - x) + 1);
|
||||
// }
|
||||
//
|
||||
// y++;
|
||||
// angle = (int)(0.5 + (atan((double)y / x) * 180.0 / PI));
|
||||
// }
|
||||
//}
|
||||
|
||||
#define PI 3.14159265359
|
||||
|
||||
void TFT_DrawArc(TFT_T *dev, uint16_t x, uint16_t y, uint16_t radius, int start_angle, int end_angle) {
|
||||
// 修复输入角度范围
|
||||
if (start_angle < 0) {
|
||||
start_angle = 0;
|
||||
} else if (start_angle > 360) {
|
||||
start_angle = 360;
|
||||
}
|
||||
if (end_angle < 0) {
|
||||
end_angle = 0;
|
||||
} else if (end_angle > 360) {
|
||||
end_angle = 360;
|
||||
}
|
||||
double angle;
|
||||
unsigned int cirx, ciry, lastX, lastY;
|
||||
cirx = x;
|
||||
ciry = y;
|
||||
|
||||
angle = start_angle;
|
||||
while (angle <= end_angle) {
|
||||
lastX = cirx + radius * sin(angle * PI / 180);
|
||||
lastY = ciry - radius * cos(angle * PI / 180);
|
||||
TFT_SetPixel(dev, lastX, lastY, POINT_COLOR);
|
||||
angle = angle + 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
void TFT_ShowChar(TFT_T *dev, uint16_t x, uint16_t y, uint8_t chr, uint16_t size,bool mode) {
|
||||
uint16_t i, m, temp, size2, chr1;
|
||||
uint16_t ys = y;
|
||||
@@ -439,3 +548,60 @@ void TFT_ShowPic(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t he
|
||||
bmp+=width;
|
||||
}
|
||||
}
|
||||
|
||||
void TFT_DrawCross(TFT_T *dev, uint16_t x, uint16_t y, uint8_t r) {
|
||||
TFT_DrawLine(dev, x - r, y, x + r, y);
|
||||
TFT_DrawLine(dev, x, y - r, x, y + r);
|
||||
}
|
||||
|
||||
void TFT_DrawXCross(TFT_T *dev, uint16_t x, uint16_t y, uint8_t r) {
|
||||
TFT_DrawLine(dev, x - r, y - r, x + r, y + r);
|
||||
TFT_DrawLine(dev, x - r, y + r, x + r, y - r);
|
||||
}
|
||||
|
||||
void TFT_DrawRoundedRect(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t radius) {
|
||||
// 画四条直线
|
||||
TFT_DrawLine(dev, x + radius, y, x + width - radius, y); // 上方横线
|
||||
TFT_DrawLine(dev, x + radius, y + height, x + width - radius, y + height); // 下方横线
|
||||
|
||||
TFT_DrawLine(dev, x, y + radius, x, y + height - radius); // 左侧竖线
|
||||
TFT_DrawLine(dev, x + width, y + radius, x + width, y + height - radius); // 右侧竖线
|
||||
|
||||
// 画四个圆角
|
||||
TFT_DrawArc(dev, x + radius, y + radius, radius, 270, 360); // 左上角
|
||||
TFT_DrawArc(dev, x + width - radius, y + radius, radius, 0, 90); // 右上角
|
||||
TFT_DrawArc(dev, x + width - radius, y + height - radius, radius, 90, 180); // 右下角
|
||||
TFT_DrawArc(dev, x + radius, y + height - radius, radius, 180, 270); // 左下角
|
||||
}
|
||||
|
||||
uint16_t invertRGB565(uint16_t color) {
|
||||
// 分离颜色分量
|
||||
uint8_t r = (color >> 11) & 0x1F; // 取出红色分量
|
||||
uint8_t g = (color >> 5) & 0x3F; // 取出绿色分量
|
||||
uint8_t b = color & 0x1F; // 取出蓝色分量
|
||||
|
||||
// 取反颜色分量
|
||||
r = 31 - r;
|
||||
g = 63 - g;
|
||||
b = 31 - b;
|
||||
|
||||
// 重新组合颜色分量
|
||||
return (r << 11) | (g << 5) | b;
|
||||
}
|
||||
|
||||
void TFT_ShowBar(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height, float progress) {
|
||||
if (x + width > dev->width || y + height > dev->height || progress > 1)return;
|
||||
uint16_t xp = (width - x) * progress;
|
||||
TFT_Fill(dev, x, y, xp, height, POINT_COLOR);
|
||||
if (progress < 1)TFT_Fill(dev, xp, y, width, height, BACK_COLOR);
|
||||
if (height >= 12 && height < 32) {
|
||||
uint8_t tmp[7];
|
||||
uint16_t sp = (width - x) / 2 - 3 * ((height >= 24) ? 24 : (height >= 16) ? 16 : 12) / 2;
|
||||
TFT_Color_t temp = POINT_COLOR;
|
||||
POINT_COLOR.u16 = invertRGB565(POINT_COLOR.u16);
|
||||
sprintf((char *) tmp, "%05.2f%%", progress * 100);
|
||||
if (xp < sp)TFT_ShowString(dev, sp, y, tmp, (height >= 24) ? 24 : (height >= 16) ? 16 : 12, 0);
|
||||
else TFT_ShowString(dev, sp, y, tmp, (height >= 24) ? 24 : (height >= 16) ? 16 : 12, 1);
|
||||
POINT_COLOR = temp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "stdbool.h"
|
||||
typedef char OptId;
|
||||
|
||||
typedef struct Option {
|
||||
|
||||
+144
-18
@@ -42,11 +42,11 @@
|
||||
////////////////////////
|
||||
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOG_RUN_TIMER_FUN GetSysCnt32()
|
||||
#define LOG_RUN_TIMER_FUN GetTickCount64()
|
||||
#define LOG_RUN_TIMER_FMT "-T(%lums)"
|
||||
#else
|
||||
#define LOG_RUN_TIMER_FUN 0
|
||||
#define LOG_RUN_TIMER_FMT "-T(%lu)"
|
||||
#define LOG_RUN_TIMER_FUN GetTickCount64()
|
||||
#define LOG_RUN_TIMER_FMT "(%llums)"
|
||||
#endif
|
||||
|
||||
#ifdef LOG_LINE_END_CRLF
|
||||
@@ -65,6 +65,9 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LOG_OUT_FUNC printf
|
||||
|
||||
|
||||
#define LOG_BASE_FILENAME \
|
||||
(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : \
|
||||
strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||
@@ -101,9 +104,9 @@
|
||||
// 带时钟输出
|
||||
#if defined(LOG_TIMER)
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOGT(tag, fmt, ...) do{ printf(LOG_COLOR_BLUE "[" tag "]" LOG_RUN_TIMER_FMT ": " fmt LOG_END,LOG_RUN_TIMER_FUN, ##__VA_ARGS__); } while(0)
|
||||
#define LOGT(tag, fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_BLUE "[" tag "]" LOG_RUN_TIMER_FMT ": " fmt LOG_END,LOG_RUN_TIMER_FUN, ##__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LOGT(tag, fmt, ...) do{ printf(LOG_COLOR_BLUE "[" tag "]: " fmt LOG_END, ##__VA_ARGS__); } while(0)
|
||||
#define LOGT(tag, fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_BLUE "[" tag "]: " fmt LOG_END, ##__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
#else
|
||||
#define LOGT(fmt, ...) ((void)0)
|
||||
@@ -112,9 +115,9 @@
|
||||
// 等级输出
|
||||
#if LOG_OUTPUT_LVL >= LOG_LVL_FATAL
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOGF(fmt, ...) do{ printf(LOG_COLOR_CYAN "[F]" LOG_RUN_TIMER_FMT ": %s: %s: %d: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); LOG_EXIT_PROGRAM(); } while(0)
|
||||
#define LOGF(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_CYAN "[F]" LOG_RUN_TIMER_FMT ": %s: %s: %d: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); LOG_EXIT_PROGRAM(); } while(0)
|
||||
#else
|
||||
#define LOGF(fmt, ...) do{ printf(LOG_COLOR_CYAN "[F]: %s: %s: %d: " fmt LOG_END, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); LOG_EXIT_PROGRAM(); } while(0)
|
||||
#define LOGF(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_CYAN "[F]: %s: %s: %d: " fmt LOG_END, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); LOG_EXIT_PROGRAM(); } while(0)
|
||||
#endif
|
||||
#else
|
||||
#define LOGF(fmt, ...) ((void)0)
|
||||
@@ -122,9 +125,9 @@
|
||||
|
||||
#if LOG_OUTPUT_LVL >= LOG_LVL_ERROR
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOGE(fmt, ...) do{ printf(LOG_COLOR_RED "[E]" LOG_RUN_TIMER_FMT ": %s: %s: %d: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#define LOGE(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_RED "[E]" LOG_RUN_TIMER_FMT ": %s: %s: %d: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LOGE(fmt, ...) do{ printf(LOG_COLOR_RED "[E]: %s: %s: %d: " fmt LOG_END, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#define LOGE(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_RED "[E]: %s: %s: %d: " fmt LOG_END, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
#else
|
||||
#define LOGE(fmt, ...) ((void)0)
|
||||
@@ -132,9 +135,9 @@
|
||||
|
||||
#if LOG_OUTPUT_LVL >= LOG_LVL_WARN
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOGW(fmt, ...) do{ printf(LOG_COLOR_CARMINE "[W]" LOG_RUN_TIMER_FMT ": %s: %s: %d: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#define LOGW(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_CARMINE "[W]" LOG_RUN_TIMER_FMT ": %s: %s: %d: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LOGW(fmt, ...) do{ printf(LOG_COLOR_CARMINE "[W]: %s: %s: %d: " fmt LOG_END, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#define LOGW(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_CARMINE "[W]: %s: %s: %d: " fmt LOG_END, LOG_BASE_FILENAME, __func__, __LINE__, ##__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
#else
|
||||
#define LOGW(fmt, ...) ((void)0)
|
||||
@@ -142,9 +145,9 @@
|
||||
|
||||
#if LOG_OUTPUT_LVL >= LOG_LVL_INFO
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOGI(fmt, ...) do{ printf(LOG_COLOR_YELLOW "[I]" LOG_RUN_TIMER_FMT ": %s: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#define LOGI(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_YELLOW "[I]" LOG_RUN_TIMER_FMT ": %s: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LOGI(fmt, ...) do{ printf(LOG_COLOR_YELLOW "[I]: %s: " fmt LOG_END, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#define LOGI(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_YELLOW "[I]: %s: " fmt LOG_END, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
#else
|
||||
#define LOGI(fmt, ...) ((void)0)
|
||||
@@ -152,9 +155,9 @@
|
||||
|
||||
#if LOG_OUTPUT_LVL >= LOG_LVL_DEBUG
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOGD(fmt, ...) do{ printf(LOG_COLOR_DEFAULT "[D]" LOG_RUN_TIMER_FMT ": %s: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#define LOGD(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_DEFAULT "[D]" LOG_RUN_TIMER_FMT ": %s: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LOGD(fmt, ...) do{ printf(LOG_COLOR_DEFAULT "[D]: %s: " fmt LOG_END, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#define LOGD(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_DEFAULT "[D]: %s: " fmt LOG_END, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
#else
|
||||
#define LOGD(fmt, ...) ((void)0)
|
||||
@@ -162,11 +165,134 @@
|
||||
|
||||
#if LOG_OUTPUT_LVL >= LOG_LVL_VERBOSE
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOGV(fmt, ...) do{ printf(LOG_COLOR_DEFAULT "[V]" LOG_RUN_TIMER_FMT ": %s: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#define LOGV(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_DEFAULT "[V]" LOG_RUN_TIMER_FMT ": %s: " fmt LOG_END,LOG_RUN_TIMER_FUN, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LOGV(fmt, ...) do{ printf(LOG_COLOR_DEFAULT "[V]: %s: " fmt LOG_END, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#define LOGV(fmt, ...) do{ LOG_OUT_FUNC(LOG_COLOR_DEFAULT "[V]: %s: " fmt LOG_END, LOG_BASE_FILENAME, ##__VA_ARGS__); } while(0)
|
||||
#endif
|
||||
#else
|
||||
#define LOGV(fmt, ...) ((void)0)
|
||||
#endif
|
||||
#endif //HW_LIB_LOG_H
|
||||
|
||||
|
||||
#ifndef LOG_RUN_TIME
|
||||
#ifndef __LOG_VA_NUM_ARGS_IMPL
|
||||
# define __LOG_VA_NUM_ARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, \
|
||||
_12, _13, _14, _15, _16, __N, ...) __N
|
||||
#endif
|
||||
|
||||
#ifndef __LOG_VA_NUM_ARGS
|
||||
#define __LOG_VA_NUM_ARGS(...) \
|
||||
__LOG_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9, \
|
||||
8,7,6,5,4,3,2,1,0)
|
||||
#endif
|
||||
|
||||
#ifndef __ticks_sync_barrier__
|
||||
|
||||
/* default implementation */
|
||||
#if defined(__clang__) || __IS_COMPILER_GCC__
|
||||
# define __ticks_sync_barrier__(...) __sync_synchronize()
|
||||
#else
|
||||
# define __ticks_sync_barrier__(...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#undef __CONNECT2
|
||||
#undef __CONNECT3
|
||||
|
||||
#undef CONNECT2
|
||||
#undef CONNECT3
|
||||
|
||||
#undef CONNECT
|
||||
|
||||
#undef __MACRO_EXPANDING
|
||||
#define __MACRO_EXPANDING(...) __VA_ARGS__
|
||||
|
||||
#define __CONNECT2(__A, __B) __A##__B
|
||||
#define __CONNECT3(__A, __B, __C) __A##__B##__C
|
||||
|
||||
#define ALT_CONNECT2(__A, __B) __CONNECT2(__A, __B)
|
||||
#define CONNECT2(__A, __B) __CONNECT2(__A, __B)
|
||||
#define CONNECT3(__A, __B, __C) __CONNECT3(__A, __B, __C)
|
||||
|
||||
#define CONNECT(...) \
|
||||
ALT_CONNECT2(CONNECT, __LOG_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#undef __using1
|
||||
#undef __using2
|
||||
#undef __using3
|
||||
#undef __using4
|
||||
#undef using
|
||||
|
||||
#define __using1(__declare) \
|
||||
for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL; \
|
||||
)
|
||||
|
||||
#define __using2(__declare, __on_leave_expr) \
|
||||
for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL; \
|
||||
(__on_leave_expr) \
|
||||
)
|
||||
|
||||
#define __using3(__declare, __on_enter_expr, __on_leave_expr) \
|
||||
for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL ? \
|
||||
((__on_enter_expr),1) : 0; \
|
||||
(__on_leave_expr) \
|
||||
)
|
||||
|
||||
#define __using4(__dcl1, __dcl2, __on_enter_expr, __on_leave_expr) \
|
||||
for (__dcl1, __dcl2, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL ? \
|
||||
((__on_enter_expr),1) : 0; \
|
||||
(__on_leave_expr) \
|
||||
)
|
||||
|
||||
#define using(...) \
|
||||
CONNECT2(__using, __LOG_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#ifdef LOG_WITH_RUN_TIMER
|
||||
#define LOG_RUN_TIME(__STR, ...) \
|
||||
using(uint64_t _ = LOG_RUN_TIMER_FUN, __time_count__ = _, \
|
||||
{__ticks_sync_barrier__();}, \
|
||||
{ \
|
||||
__ticks_sync_barrier__(); \
|
||||
_ = LOG_RUN_TIMER_FUN - _; \
|
||||
__time_count__ = _; \
|
||||
if (__LOG_VA_NUM_ARGS(__VA_ARGS__) == 0) { \
|
||||
LOG_OUT_FUNC("\r\n"); \
|
||||
LOG_OUT_FUNC("-[Run Timer]"); \
|
||||
LOG_OUT_FUNC( \
|
||||
"------------------------------------\r\n"); \
|
||||
LOG_OUT_FUNC( \
|
||||
__STR " total run timer: " LOG_RUN_TIMER_FMT LOG_END, \
|
||||
_); \
|
||||
} else { \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
})
|
||||
#else
|
||||
|
||||
#define LOG_RUN_TIME(__STR, ...) \
|
||||
using(uint64_t _ = LOG_RUN_TIMER_FUN, __time_count__ = _, \
|
||||
{__ticks_sync_barrier__();}, \
|
||||
{ \
|
||||
__ticks_sync_barrier__(); \
|
||||
_ = LOG_RUN_TIMER_FUN - _; \
|
||||
__time_count__ = _; \
|
||||
if (__LOG_VA_NUM_ARGS(__VA_ARGS__) == 0) { \
|
||||
LOG_OUT_FUNC("\r\n"); \
|
||||
LOG_OUT_FUNC("-[Run Timer]"); \
|
||||
LOG_OUT_FUNC( \
|
||||
"------------------------------------\r\n"); \
|
||||
LOG_OUT_FUNC( \
|
||||
__STR " total run timer: " LOG_RUN_TIMER_FMT LOG_END, \
|
||||
_); \
|
||||
} else { \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
})
|
||||
#endif
|
||||
#endif
|
||||
#endif //HW_LIB_LOG_H
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
#ifndef HW_LIB_PLOOC_H
|
||||
#define HW_LIB_PLOOC_H
|
||||
|
||||
/*============================ INCLUDES ======================================*/
|
||||
#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus)
|
||||
//! you have to define this by yourselves
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*! \NOTE the uint_fast8_t used in this header file is defined in stdint.h
|
||||
if you don't have stdint.h supported in your toolchain, you should
|
||||
define uint_fast8_t all by yourself with following rule:
|
||||
a. if the target processor is 8 bits, define it as uint8_t
|
||||
b. if the target processor is 16 bits, define it as uint16_t
|
||||
c. if the target processor is 32 bits, define it as uint32_t
|
||||
d. if the target processor is 64 bits, define it as either uint32_t or
|
||||
uint64_t
|
||||
*/
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
# pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
# pragma clang diagnostic ignored "-Wtypedef-redefinition"
|
||||
# pragma clang diagnostic ignored "-Wmissing-declarations"
|
||||
# pragma clang diagnostic ignored "-Wempty-body"
|
||||
# pragma clang diagnostic ignored "-Wmicrosoft-anon-tag"
|
||||
#elif ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION < 6000000))
|
||||
/*! arm compiler 5 */
|
||||
# pragma push
|
||||
# pragma diag_suppress 1,64,174,177,188,68,513,144,2525
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
/*! IAR */
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
# pragma GCC diagnostic ignored "-Wempty-body"
|
||||
# pragma GCC diagnostic ignored "-Wpragmas"
|
||||
# pragma GCC diagnostic ignored "-Wformat="
|
||||
# pragma GCC diagnostic ignored "-Wmissing-braces"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*============================ MACROS ========================================*/
|
||||
#ifndef __cplusplus
|
||||
# ifndef plooc_private
|
||||
# define plooc_private static
|
||||
# endif
|
||||
|
||||
# ifndef plooc_public
|
||||
# define plooc_public
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef plooc_malloc_align
|
||||
# define plooc_malloc_align(__size, __align) malloc(__size)
|
||||
#endif
|
||||
|
||||
#ifndef plooc_free
|
||||
# define plooc_free free
|
||||
#endif
|
||||
|
||||
|
||||
/*============================ MACROFIED FUNCTIONS ===========================*/
|
||||
|
||||
|
||||
/*! \note add which macro to support multiple inheriting and implementations
|
||||
*!
|
||||
*! declare_interface( i_lv0_abc_t )
|
||||
*! declare_interface( i_lv0_efg_t )
|
||||
*! def_interface( i_lv0_abc_t )
|
||||
*! ...
|
||||
*! end_def_interface( i_lv0_abc_t )
|
||||
*!
|
||||
*! def_interface( i_lv0_efg_t )
|
||||
*! ...
|
||||
*! end_def_interface( i_lv0_efg_t )
|
||||
*!
|
||||
*! declare_interface( i_lv1_t )
|
||||
*! def_interface( i_lv1_t, which( inherit( i_lv0_abc_t )
|
||||
*! inherit( i_lv0_efg_t ) ) )
|
||||
*! ...
|
||||
*! end_def_interface( i_lv1_t )
|
||||
*/
|
||||
|
||||
#define __declare_interface(__name) typedef struct __name __name;
|
||||
#define __declare_structure(__name) typedef struct __name __name;
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus)
|
||||
|
||||
//! \name interface definition
|
||||
//! @{
|
||||
#define __def_interface(__name) \
|
||||
/*typedef struct __name __name;*/ \
|
||||
struct __name {
|
||||
|
||||
#define __end_def_interface(__name) \
|
||||
};
|
||||
//! @}
|
||||
|
||||
//! \name structure definition
|
||||
//! @{
|
||||
#define __def_structure(__name) \
|
||||
/*typedef struct __name __name; */ \
|
||||
struct __name {
|
||||
|
||||
#define __end_def_structure(__name) \
|
||||
};
|
||||
//! @}
|
||||
|
||||
#else
|
||||
//! \name interface definition
|
||||
//! @{
|
||||
#define __def_interface(__name, ...) \
|
||||
typedef struct __name __name; \
|
||||
__VA_ARGS__ \
|
||||
struct __name {
|
||||
|
||||
#define __end_def_interface(__name) \
|
||||
};
|
||||
//! @}
|
||||
|
||||
//! \name structure definition
|
||||
//! @{
|
||||
#define __def_structure(__name, ...) \
|
||||
typedef struct __name __name; \
|
||||
__VA_ARGS__ \
|
||||
struct __name {
|
||||
|
||||
#define __end_def_structure(__name) \
|
||||
};
|
||||
//! @}
|
||||
#endif
|
||||
|
||||
//! \brief macro for inheritance
|
||||
|
||||
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
|
||||
#define __IMPLEMENT_EX(__TYPE, __NAME) \
|
||||
__TYPE __NAME;
|
||||
#else
|
||||
#define __IMPLEMENT_EX(__TYPE, __NAME) \
|
||||
union { \
|
||||
__TYPE __NAME; \
|
||||
__TYPE; \
|
||||
};
|
||||
#endif
|
||||
|
||||
#define __INHERIT_EX(__TYPE, __NAME) __TYPE __NAME;
|
||||
#define INHERIT_EX(__TYPE, __NAME) __INHERIT_EX(__TYPE, __NAME)
|
||||
|
||||
#define __INHERIT(__TYPE) INHERIT_EX(__TYPE, use_as__##__TYPE)
|
||||
#define INHERIT(__TYPE) __INHERIT(__TYPE)
|
||||
|
||||
|
||||
|
||||
/*! \note You can only use IMPLEMENT when defining INTERFACE. For Implement
|
||||
* interface when defining class, you should use DEF_CLASS_IMPLEMENT
|
||||
* instead.
|
||||
*/
|
||||
#define __IMPLEMENT(__INTERFACE) __IMPLEMENT_EX( __INTERFACE, \
|
||||
use_as__##__INTERFACE)
|
||||
#define IMPLEMENT(__INTERFACE) __IMPLEMENT(__INTERFACE)
|
||||
|
||||
/*! \note if you have used INHERIT or IMPLEMENT to define a class / INTERFACE,
|
||||
you can use OBJ_CONVERT_AS to extract the reference to the inherited
|
||||
object.
|
||||
\*/
|
||||
#define __OBJ_CONVERT_AS(__OBJ, __INTERFACE) (__OBJ.use_as__##__INTERFACE)
|
||||
#define OBJ_CONVERT_AS(__OBJ, __INTERFACE) __OBJ_CONVERT_AS( (__OBJ), \
|
||||
__INTERFACE)
|
||||
|
||||
#define __REF_OBJ_AS(__OBJ, __TYPE) (&(__OBJ.use_as__##__TYPE))
|
||||
#define REF_OBJ_AS(__OBJ, __TYPE) __REF_OBJ_AS((__OBJ), __TYPE)
|
||||
|
||||
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus)
|
||||
/*! \brief You can use __PLOOC_EVAL() to dynamically select the right API which
|
||||
*! has the right number of parameters (no more than 8).
|
||||
*/
|
||||
//! @{
|
||||
#define __PLOOC_VA_NUM_ARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
|
||||
_13, _14, _15, _16, __N, ...) __N
|
||||
#define __PLOOC_VA_NUM_ARGS(...) \
|
||||
__PLOOC_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9, \
|
||||
8,7,6,5,4,3,2,1,0)
|
||||
|
||||
#define __16_PLOOC_EVAL(__FUNC, __NO_ARGS) __FUNC##__NO_ARGS
|
||||
#define __15_PLOOC_EVAL(__FUNC, __NO_ARGS) __16_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __14_PLOOC_EVAL(__FUNC, __NO_ARGS) __15_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __13_PLOOC_EVAL(__FUNC, __NO_ARGS) __14_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
|
||||
#define __12_PLOOC_EVAL(__FUNC, __NO_ARGS) __13_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __11_PLOOC_EVAL(__FUNC, __NO_ARGS) __12_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __10_PLOOC_EVAL(__FUNC, __NO_ARGS) __11_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __9_PLOOC_EVAL(__FUNC, __NO_ARGS) __10_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __8_PLOOC_EVAL(__FUNC, __NO_ARGS) __9_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
|
||||
#define __7_PLOOC_EVAL(__FUNC, __NO_ARGS) __8_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __6_PLOOC_EVAL(__FUNC, __NO_ARGS) __7_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __5_PLOOC_EVAL(__FUNC, __NO_ARGS) __6_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __4_PLOOC_EVAL(__FUNC, __NO_ARGS) __5_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __3_PLOOC_EVAL(__FUNC, __NO_ARGS) __4_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __2_PLOOC_EVAL(__FUNC, __NO_ARGS) __3_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __1_PLOOC_EVAL(__FUNC, __NO_ARGS) __2_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
#define __0_PLOOC_EVAL(__FUNC, __NO_ARGS) __1_PLOOC_EVAL(__FUNC, __NO_ARGS)
|
||||
|
||||
#define __PLOOC_EVAL(__FUNC, ...) __0_PLOOC_EVAL( \
|
||||
__FUNC, \
|
||||
__PLOOC_VA_NUM_ARGS(__VA_ARGS__))
|
||||
//! @}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* new standard (lower case) *
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
|
||||
# define def_interface(__name) __def_interface(__name)
|
||||
# define define_interface(__name) __def_interface(__name)
|
||||
# define def_structure(__name) __def_structure(__name)
|
||||
# define define_structure(__name) __def_structure(__name)
|
||||
# define def_params(__code) __code
|
||||
# define define_params(__code) __code
|
||||
# define end_def_params()
|
||||
# define end_define_params()
|
||||
# define def_members(__code) __code
|
||||
# define define_members(__code) __code
|
||||
# define end_def_members()
|
||||
# define end_define_members()
|
||||
#else
|
||||
# define def_interface(__name, ...) __def_interface(__name, __VA_ARGS__)
|
||||
# define define_interface(__name, ...) __def_interface(__name, __VA_ARGS__)
|
||||
# define def_structure(__name, ...) __def_structure(__name, __VA_ARGS__)
|
||||
# define define_structure(__name, ...) __def_structure(__name, __VA_ARGS__)
|
||||
# define def_params(...) __VA_ARGS__
|
||||
# define define_params(...) __VA_ARGS__
|
||||
# define end_def_params(...)
|
||||
# define end_define_params(...)
|
||||
# define def_members(...) __VA_ARGS__
|
||||
# define define_members(...) __VA_ARGS__
|
||||
# define end_def_members(...)
|
||||
# define end_define_members(...)
|
||||
#endif
|
||||
|
||||
#define implement(__type) IMPLEMENT(__type)
|
||||
#define implement_ex(__type, __name) __IMPLEMENT_EX(__type, __name)
|
||||
#define inherit_ex(__type, __name) INHERIT_EX(__type, __name)
|
||||
#define inherit(__type) INHERIT(__type)
|
||||
#define ref_interface(__INTERFACE) const __INTERFACE *ptMethod;
|
||||
#define convert_obj_as(__obj, __type) OBJ_CONVERT_AS(__obj, __type)
|
||||
#define obj_convert_as(__obj, __type) OBJ_CONVERT_AS(__obj, __type) /* obsolete */
|
||||
#define ref_obj_as(__obj, __type) REF_OBJ_AS(__obj, __type)
|
||||
|
||||
#define end_def_interface(__name) __end_def_interface(__name)
|
||||
#define end_define_interface(__name) __end_def_interface(__name)
|
||||
#define dcl_interface(__name) __declare_interface(__name)
|
||||
#define declare_interface(__name) __declare_interface(__name)
|
||||
#define end_def_structure(__name) __end_def_structure(__name)
|
||||
#define end_define_structure(__name) __end_def_structure(__name)
|
||||
#define dcl_structure(__name) __declare_structure(__name)
|
||||
#define declare_structure(__name) __declare_structure(__name)
|
||||
|
||||
#define this_interface(__INTERFACE) convert_obj_as(this, __INTERFACE)
|
||||
#define base_obj(__type) convert_obj_as(this, __type)
|
||||
|
||||
|
||||
|
||||
/*============================ TYPES =========================================*/
|
||||
|
||||
//! \name interface: u32_property_t
|
||||
//! @{
|
||||
dcl_interface(u32_property_t)
|
||||
def_interface(u32_property_t)
|
||||
bool (*Set)(uint32_t wValue);
|
||||
|
||||
uint32_t (*Get)(void);
|
||||
end_def_interface(u32_property_t)
|
||||
//! @}
|
||||
|
||||
//! \name interface: u16_property_t
|
||||
//! @{
|
||||
dcl_interface(u16_property_t)
|
||||
def_interface(u16_property_t)
|
||||
bool (*Set)(uint_fast16_t wValue);
|
||||
|
||||
uint_fast16_t (*Get)(void);
|
||||
end_def_interface(u16_property_t)
|
||||
//! @}
|
||||
|
||||
//! \name interface: u8_property_t
|
||||
//! @{
|
||||
dcl_interface(u8_property_t)
|
||||
def_interface(u8_property_t)
|
||||
bool (*Set)(uint_fast8_t wValue);
|
||||
|
||||
uint_fast8_t (*Get)(void);
|
||||
end_def_interface(u8_property_t)
|
||||
//! @}
|
||||
|
||||
|
||||
//! \name interface: i32_property_t
|
||||
//! @{
|
||||
dcl_interface(i32_property_t)
|
||||
def_interface(i32_property_t)
|
||||
bool (*Set)(int32_t wValue);
|
||||
|
||||
int32_t (*Get)(void);
|
||||
end_def_interface(i32_property_t)
|
||||
//! @}
|
||||
|
||||
//! \name interface: i16_property_t
|
||||
//! @{
|
||||
dcl_interface(i16_property_t)
|
||||
def_interface(i16_property_t)
|
||||
bool (*Set)(int_fast16_t wValue);
|
||||
|
||||
int_fast16_t (*Get)(void);
|
||||
end_def_interface(i16_property_t)
|
||||
//! @}
|
||||
|
||||
//! \name interface: u8_property_t
|
||||
//! @{
|
||||
dcl_interface(i8_property_t)
|
||||
def_interface(i8_property_t)
|
||||
bool (*Set)(int_fast8_t wValue);
|
||||
|
||||
int_fast8_t (*Get)(void);
|
||||
end_def_interface(i8_property_t)
|
||||
//! @}
|
||||
|
||||
//! \name interface: bool_property_t
|
||||
//! @{
|
||||
dcl_interface(bool_property_t)
|
||||
def_interface(bool_property_t)
|
||||
bool (*Set)(bool bValue);
|
||||
|
||||
bool (*Get)(void);
|
||||
end_def_interface(bool_property_t)
|
||||
//! @}
|
||||
|
||||
//! \name interface: bool_property_t
|
||||
//! @{
|
||||
dcl_interface(en_property_t)
|
||||
def_interface(en_property_t)
|
||||
bool (*Enable)(void);
|
||||
|
||||
bool (*Disable)(void);
|
||||
end_def_interface(en_property_t)
|
||||
//! @}
|
||||
|
||||
/*============================ GLOBAL VARIABLES ==============================*/
|
||||
/*============================ LOCAL VARIABLES ===============================*/
|
||||
/*============================ PROTOTYPES ====================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//#if defined(__clang__)
|
||||
//# pragma clang diagnostic pop
|
||||
//#endif
|
||||
|
||||
#endif //HW_LIB_PLOOC_H
|
||||
@@ -0,0 +1,386 @@
|
||||
#ifndef HW_LIB_PLOOC_CLASS_H
|
||||
#define HW_LIB_PLOOC_CLASS_H
|
||||
|
||||
#if defined(__cplusplus) || defined(__OOC_CPP__)
|
||||
# undef __PLOOC_CLASS_USE_STRICT_TEMPLATE__
|
||||
# undef PLOOC_CFG_REMOVE_MEMORY_LAYOUT_BOUNDARY___USE_WITH_CAUTION___
|
||||
# define PLOOC_CFG_REMOVE_MEMORY_LAYOUT_BOUNDARY___USE_WITH_CAUTION___
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__OOC_RELEASE__) || defined(__OOC_CPP__)
|
||||
# undef __OOC_DEBUG__
|
||||
# define __OOC_DEBUG__ 1
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(__PLOOC_CLASS_USE_STRICT_TEMPLATE__) \
|
||||
&& !defined(__PLOOC_CLASS_USE_SIMPLE_TEMPLATE__) \
|
||||
&& !defined(__PLOOC_CLASS_USE_BLACK_BOX_TEMPLATE__)
|
||||
# define __PLOOC_CLASS_USE_SIMPLE_TEMPLATE__ 1
|
||||
#endif
|
||||
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus)
|
||||
|
||||
#ifndef __OOC_DEBUG__
|
||||
# define __OOC_DEBUG__
|
||||
# warning For C89/90, __OOC_DEBUG__ is enforced.
|
||||
#endif
|
||||
|
||||
#if defined(__PLOOC_CLASS_USE_STRICT_TEMPLATE__)
|
||||
# undef __PLOOC_CLASS_USE_STRICT_TEMPLATE__
|
||||
# define __PLOOC_CLASS_USE_SIMPLE_TEMPLATE__
|
||||
#endif
|
||||
|
||||
#if defined(__PLOOC_CLASS_USE_BLACK_BOX_TEMPLATE__)
|
||||
# undef __PLOOC_CLASS_USE_BLACK_BOX_TEMPLATE__
|
||||
# define __PLOOC_CLASS_USE_SIMPLE_TEMPLATE__
|
||||
#endif
|
||||
|
||||
# if !defined(__OOC_DEBUG__) || !defined(__PLOOC_CLASS_USE_SIMPLE_TEMPLATE__)
|
||||
# error \
|
||||
You must use __OOC_DEBUG__ (or __OOC_RELEASE__) together with the\
|
||||
__PLOOC_CLASS_USE_SIMPLE_TEMPLATE__ in ANSI-C89/90.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __PLOOC_CLASS_H__
|
||||
#define __PLOOC_CLASS_H__
|
||||
|
||||
/******************************************************************************
|
||||
* HOW TO USE *
|
||||
******************************************************************************/
|
||||
//! TODO: Add How to use
|
||||
|
||||
|
||||
|
||||
/*============================ INCLUDES ======================================*/
|
||||
//#include <stdint.h>
|
||||
/*! \NOTE the uint_fast8_t used in this header file is defined in stdint.h
|
||||
if you don't have stdint.h supported in your toolchain, you should
|
||||
define uint_fast8_t all by yourself with following rule:
|
||||
a. if the target processor is 8 bits, define it as uint8_t
|
||||
b. if the target processor is 16 bits, define it as uint16_t
|
||||
c. if the target processor is 32 bits, define it as uint32_t
|
||||
d. if the target processor is 64 bits, define it as either uint32_t or
|
||||
uint64_t
|
||||
*/
|
||||
|
||||
#include "plooc.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*============================ MACROS ========================================*/
|
||||
/*!\ node if you want your code more "elegent", say you want to use "this" with
|
||||
* "." rather than a pointer with "->", you can add following macros to
|
||||
* your code, assuming the variable name of the object pointer is "ptThis".
|
||||
* If your object pointer has a different name, please feel free to change
|
||||
* the macro by yourself
|
||||
|
||||
#undef this
|
||||
#define this (*ptThis)
|
||||
|
||||
*/
|
||||
|
||||
/*============================ MACROFIED FUNCTIONS ===========================*/
|
||||
|
||||
//! @{
|
||||
#ifndef __PLOOC_CONNECT2
|
||||
# define __PLOOC_CONNECT2( __A, __B) __A##__B
|
||||
#endif
|
||||
#ifndef __PLOOC_CONNECT3
|
||||
# define __PLOOC_CONNECT3( __A, __B, __C) __A##__B##__C
|
||||
#endif
|
||||
#ifndef __PLOOC_CONNECT4
|
||||
# define __PLOOC_CONNECT4( __A, __B, __C, __D) __A##__B##__C##__D
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
#ifndef __PLOOC_ALIGN
|
||||
# define __PLOOC_ALIGN(__N) __attribute__((aligned(__N)))
|
||||
#endif
|
||||
#ifndef PLOOC_ALIGN
|
||||
# define PLOOC_ALIGN(__N) __PLOOC_ALIGN(__N)
|
||||
#endif
|
||||
/*
|
||||
#ifndef PLOOC_DEFAULT_OBJ_ALIGN
|
||||
# define PLOOC_DEFAULT_OBJ_ALIGN sizeof(uint_fast8_t)
|
||||
#endif
|
||||
*/
|
||||
#ifndef PLOOC_PACKED
|
||||
# define PLOOC_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
//! @{
|
||||
#ifndef PLOOC_CONNECT2
|
||||
# define PLOOC_CONNECT2( __A, __B) __PLOOC_CONNECT2( __A, __B)
|
||||
#endif
|
||||
#ifndef PLOOC_CONNECT3
|
||||
# define PLOOC_CONNECT3( __A, __B, __C) __PLOOC_CONNECT3( __A, __B, __C)
|
||||
#endif
|
||||
#ifndef PLOOC_CONNECT4
|
||||
# define PLOOC_CONNECT4( __A, __B, __C, __D) __PLOOC_CONNECT4( __A, __B, __C, __D)
|
||||
#endif
|
||||
//! @}
|
||||
|
||||
#ifndef PLOOC_UNUSED_PARAM
|
||||
# define PLOOC_UNUSED_PARAM(__N) do {(__N) = (__N);}while(0)
|
||||
#endif
|
||||
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus)
|
||||
|
||||
# ifndef PLOOC_ALIGNOF
|
||||
# define PLOOC_ALIGNOF(__TYPE) __alignof__(__TYPE)
|
||||
# endif
|
||||
|
||||
# define PLOOC_ALIGNOF_STRUCT(__TYPE) PLOOC_ALIGNOF(struct {__TYPE})
|
||||
# define PLOOC_SIZEOF_STRUCT(__TYPE) sizeof(struct {__TYPE})
|
||||
|
||||
#else
|
||||
|
||||
# ifndef PLOOC_ALIGNOF
|
||||
# define PLOOC_ALIGNOF(...) __alignof__(__VA_ARGS__)
|
||||
# endif
|
||||
|
||||
# define PLOOC_ALIGNOF_STRUCT(...) PLOOC_ALIGNOF(struct {__VA_ARGS__})
|
||||
# define PLOOC_SIZEOF_STRUCT(...) sizeof(struct {__VA_ARGS__})
|
||||
|
||||
/*! \note When both __OOC_DEBUG__ and
|
||||
*! PLOOC_CFG_REMOVE_MEMORY_LAYOUT_BOUNDARY___USE_WITH_CAUTION___ are
|
||||
*! defined, memory layout boundary, i.e. struct wrapper inside PLOOC
|
||||
*! VISIBLE will be removed. This enables some platform to use the gaps
|
||||
*! between members with different memory aligments to add members with
|
||||
*! correct size and aligment for saving space.
|
||||
*!
|
||||
*! You can do this when you have all the source code and compile all
|
||||
*! the source code with the same presence of "__OOC_DEBUG__".
|
||||
*! If some of the code is compiled with different presence of
|
||||
*! "__OOC_DEBUG__", i.e. using Lib + source, removing the memory
|
||||
*! layout boundaries will cause different view of the structure and hence
|
||||
*! cause undefined behaviours.
|
||||
*/
|
||||
# if defined(PLOOC_CFG_REMOVE_MEMORY_LAYOUT_BOUNDARY___USE_WITH_CAUTION___)
|
||||
# define PLOOC_VISIBLE(...) __VA_ARGS__
|
||||
# else
|
||||
# define PLOOC_VISIBLE(...) \
|
||||
struct { \
|
||||
__VA_ARGS__ \
|
||||
}PLOOC_ALIGN(PLOOC_ALIGNOF_STRUCT(__VA_ARGS__));
|
||||
# endif
|
||||
|
||||
# if !defined (__PLOOC_CLASS_USE_NO_STRUCT_MASK__)
|
||||
|
||||
# define PLOOC_INVISIBLE(...) \
|
||||
uint8_t PLOOC_CONNECT3(chMask_,__LINE__,__COUNTER__) \
|
||||
[PLOOC_SIZEOF_STRUCT(__VA_ARGS__)] \
|
||||
PLOOC_ALIGN(PLOOC_ALIGNOF_STRUCT(__VA_ARGS__));
|
||||
|
||||
# else
|
||||
# define PLOOC_INVISIBLE(...) \
|
||||
struct { \
|
||||
__VA_ARGS__ \
|
||||
} PLOOC_CONNECT3(zzz_, __LINE__,__COUNTER__) \
|
||||
PLOOC_ALIGN(PLOOC_ALIGNOF_STRUCT(__VA_ARGS__));
|
||||
# endif /* __PLOOC_CLASS_USE_NO_STRUCT_MASK__ */
|
||||
|
||||
# define __PLOOC_PRO_struct struct
|
||||
# define __PLOOC_PRI_struct struct
|
||||
# define __PLOOC_EXT_struct struct
|
||||
# define __PLOOC_PRO_union union
|
||||
# define __PLOOC_PRI_union union
|
||||
# define __PLOOC_EXT_union union
|
||||
# define __PLOOC_EXT_uint8_t uint8_t
|
||||
# define __PLOOC_PRI_uint8_t uint8_t
|
||||
# define __PLOOC_PRO_uint8_t uint8_t
|
||||
# define __PLOOC_EXT_
|
||||
# define __PLOOC_PRI_
|
||||
# define __PLOOC_PRO_
|
||||
|
||||
|
||||
|
||||
# ifdef __OOC_DEBUG__
|
||||
|
||||
//! \brief wrapper for shell type
|
||||
# define __PLOOC_EXT__public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_EXT__private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_EXT__protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_EXT__which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
//! \brief wrapper for internal private type
|
||||
# define __PLOOC_PRI__public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRI__private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRI__protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRI__which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
//! \brief wrapper for internal protected type
|
||||
# define __PLOOC_PRO__public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRO__private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRO__protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRO__which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# else
|
||||
|
||||
//! \brief wrapper for shell type
|
||||
# define __PLOOC_EXT__public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_EXT__private_member(...) PLOOC_INVISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_EXT__protected_member(...) PLOOC_INVISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_EXT__which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
//! \brief wrapper for internal private type
|
||||
# define __PLOOC_PRI__public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRI__private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRI__protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRI__which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
//! \brief wrapper for internal protected type
|
||||
# define __PLOOC_PRO__public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRO__private_member(...) PLOOC_INVISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRO__protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define __PLOOC_PRO__which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
|
||||
&& !defined(__cplusplus)
|
||||
# undef which
|
||||
# define which(__declare) ,_which(__declare)
|
||||
#else
|
||||
# undef which
|
||||
# define which(...) ,_which(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#undef private_member
|
||||
#define private_member ,_private_member
|
||||
|
||||
#undef protected_member
|
||||
#define protected_member ,_protected_member
|
||||
|
||||
#undef public_member
|
||||
#define public_member ,_public_member
|
||||
|
||||
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
|
||||
|| defined(__cplusplus)
|
||||
|
||||
/*! \brief helper macros for heap managed objects. They use malloc() and free()
|
||||
*! internally.
|
||||
*!
|
||||
*! \note Make sure your constractor is named as <class_name>_init and it takes
|
||||
*! an configuration structure with a type named as <class_name>_cfg_t.
|
||||
*!
|
||||
*! \note Make sure your destructor is named as <class_name>_depose.
|
||||
*/
|
||||
# undef __new_class
|
||||
# define __new_class(__name, ...) \
|
||||
__name##_init( \
|
||||
(__name##_t *)plooc_malloc_align( sizeof(__name##_t), \
|
||||
PLOOC_ALIGNOF(__name##_t)), \
|
||||
(__name##_cfg_t []) {{__VA_ARGS__}} \
|
||||
)
|
||||
|
||||
# undef __free_class
|
||||
# define __free_class(__name, __obj) \
|
||||
do { \
|
||||
__name##_depose((__name##_t *)(__obj)); \
|
||||
plooc_free(__obj); \
|
||||
} while(0)
|
||||
|
||||
|
||||
# undef private_method
|
||||
# undef protected_method
|
||||
# undef public_method
|
||||
|
||||
# if defined(__PLOOC_CLASS_IMPLEMENT) || defined(__PLOOC_CLASS_IMPLEMENT__)
|
||||
|
||||
# define private_method(...) __VA_ARGS__
|
||||
# define protected_method(...) __VA_ARGS__
|
||||
# define public_method(...) __VA_ARGS__
|
||||
|
||||
# elif defined(__PLOOC_CLASS_INHERIT) || defined(__PLOOC_CLASS_INHERIT__)
|
||||
|
||||
# define private_method(...)
|
||||
# define protected_method(...) __VA_ARGS__
|
||||
# define public_method(...) __VA_ARGS__
|
||||
|
||||
# else
|
||||
|
||||
# define private_method(...)
|
||||
# define protected_method(...)
|
||||
# define public_method(...) __VA_ARGS__
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
/*============================ TYPES =========================================*/
|
||||
/*============================ GLOBAL VARIABLES ==============================*/
|
||||
/*============================ PROTOTYPES ====================================*/
|
||||
/*============================ INCLUDES ======================================*/
|
||||
|
||||
|
||||
|
||||
#if defined(__PLOOC_CLASS_USE_STRICT_TEMPLATE__)
|
||||
# include "plooc_class_strict.h"
|
||||
#elif defined(__PLOOC_CLASS_USE_SIMPLE_TEMPLATE__)
|
||||
# if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus)
|
||||
# include "plooc_class_simple_c90.h"
|
||||
# else
|
||||
# include "plooc_class_simple.h"
|
||||
# endif
|
||||
#elif defined(__PLOOC_CLASS_USE_BLACK_BOX_TEMPLATE__)
|
||||
# ifndef __PLOOC_I_KNOW_BLACK_BOX_IS_INCOMPATIBLE_WITH_OTHER_TEMPLATES__
|
||||
# warning The black box template is incompatible with other templates. When\
|
||||
header files which contains different templates mixing together, the one contains\
|
||||
black box template will cause conflicts in other header files. To avoid such\
|
||||
conflicts, you can either use black box alone in a project or in the source code of\
|
||||
the target module avoid including header files which directly or indirectly \
|
||||
including the header file of the very same module. To suppress this warning, please\
|
||||
find the macro __PLOOC_I_KNOW_BLACK_BOX_IS_INCOMPATIBLE_WITH_OTHER_TEMPLATES__ in your\
|
||||
project to acknowledge that you understand the facts and consequences.
|
||||
# endif
|
||||
# include "plooc_class_black_box.h"
|
||||
#else
|
||||
# include "plooc_class_simple.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#undef __PLOOC_CLASS_USE_STRICT_TEMPLATE__
|
||||
#undef __PLOOC_CLASS_USE_SIMPLE_TEMPLATE__
|
||||
#undef __PLOOC_CLASS_USE_BLACK_BOX_TEMPLATE__
|
||||
#undef __PLOOC_CLASS_IMPLEMENT
|
||||
#undef __PLOOC_CLASS_IMPLEMENT__
|
||||
#undef __PLOOC_CLASS_INHERIT__
|
||||
#undef __PLOOC_CLASS_INHERIT
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# undef class
|
||||
# undef this
|
||||
# undef private
|
||||
# undef public
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_PLOOC_CLASS_H
|
||||
@@ -0,0 +1,231 @@
|
||||
#ifndef HW_LIB_PLOOC_CLASS_BLACK_BOX_H
|
||||
#define HW_LIB_PLOOC_CLASS_BLACK_BOX_H
|
||||
/*============================ INCLUDES ======================================*/
|
||||
//#include <stdint.h>
|
||||
//#include <stdbool.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*============================ MACROS ========================================*/
|
||||
#undef declare_class
|
||||
#undef dcl_class
|
||||
#undef def_class
|
||||
#undef define_class
|
||||
#undef __def_class
|
||||
#undef end_def_class
|
||||
#undef end_define_class
|
||||
#undef __end_def_class
|
||||
#undef extern_class
|
||||
#undef __extern_class
|
||||
#undef end_extern_class
|
||||
#undef __end_extern_class
|
||||
#undef class
|
||||
#undef __class
|
||||
/*============================ MACROFIED FUNCTIONS ===========================*/
|
||||
|
||||
#if defined(__PLOOC_CLASS_IMPLEMENT__) || defined(__PLOOC_CLASS_IMPLEMENT)
|
||||
|
||||
# ifdef __OOC_DEBUG__
|
||||
# define __def_class(__name, __public ,...) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__public \
|
||||
PLOOC_VISIBLE(__VA_ARGS__) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__public \
|
||||
PLOOC_VISIBLE(__VA_ARGS__) \
|
||||
};
|
||||
# else
|
||||
# define __def_class(__name, __public, ...) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__public \
|
||||
PLOOC_VISIBLE(__VA_ARGS__) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__public \
|
||||
PLOOC_INVISIBLE(__VA_ARGS__) \
|
||||
};
|
||||
|
||||
# endif
|
||||
|
||||
# define __end_def_class(__name, ...)
|
||||
|
||||
# undef private_member
|
||||
# define private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
# undef public_member
|
||||
# define public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
# undef __class
|
||||
# define __class(__name) __##__name
|
||||
|
||||
# define class(__name) __class(__name)
|
||||
|
||||
#define __extern_class(__name,...)
|
||||
#define __end_extern_class(__name, ...)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef __OOC_DEBUG__
|
||||
|
||||
# define __def_class(__name, __public, ...) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__public \
|
||||
PLOOC_VISIBLE(__VA_ARGS__) \
|
||||
};
|
||||
|
||||
#define __extern_class(__name, __public, ...) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__public \
|
||||
PLOOC_INVISIBLE(__VA_ARGS__) \
|
||||
};
|
||||
|
||||
|
||||
#define __end_extern_class(__name, ...)
|
||||
|
||||
# undef private_member
|
||||
# define private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
# undef public_member
|
||||
# define public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
# define __def_class(__name, __public, ...) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__public \
|
||||
PLOOC_VISIBLE(__VA_ARGS__) \
|
||||
};
|
||||
|
||||
#define __extern_class(__name,__public, ...) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__public \
|
||||
PLOOC_VISIBLE(__VA_ARGS__) \
|
||||
};
|
||||
|
||||
|
||||
#define __end_extern_class(__name, ...)
|
||||
|
||||
# undef private_member
|
||||
# define private_member(...) PLOOC_INVISIBLE(__VA_ARGS__)
|
||||
|
||||
# undef public_member
|
||||
# define public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
# define __end_def_class(__name, ...)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
# undef __class
|
||||
# define __class(__name) __##__name
|
||||
|
||||
# undef class
|
||||
# define class(__name) __class(__name)
|
||||
|
||||
|
||||
#define declare_class(__name) typedef struct __name __name;
|
||||
#define dcl_class(__name) declare_class(__name)
|
||||
|
||||
#define end_def_class(__name, ...) __end_def_class(__name, __VA_ARGS__)
|
||||
#define end_define_class(__name, ...) end_def_class(__name, ...)
|
||||
|
||||
#define def_class(__name, __public, ...) \
|
||||
__def_class(__name, __public, __VA_ARGS__)
|
||||
#define define_class(__name, __public, ...) \
|
||||
def_class(__name,__public, __VA_ARGS__)
|
||||
|
||||
#define class(__name) __class(__name)
|
||||
|
||||
#define extern_class(__name, __public, ...) \
|
||||
__extern_class(__name, __public,__VA_ARGS__)
|
||||
#define end_extern_class(__name, ...) __end_extern_class(__name, __VA_ARGS__)
|
||||
|
||||
#ifndef __PLOOC_CLASS_BLACK_BOX_H__
|
||||
#define __PLOOC_CLASS_BLACK_BOX_H__
|
||||
|
||||
/*! \brief macro for initializing class in compiler-time
|
||||
*! \param __type class name
|
||||
*! \param __obj target object
|
||||
*! \param ... initialization list
|
||||
*/
|
||||
#define __INIT_CLASS_OBJ(__type, __obj, ...) \
|
||||
union { \
|
||||
class(__type) __##__obj; \
|
||||
__type; \
|
||||
} __obj = { \
|
||||
.__##__obj = __VA_ARGS__ \
|
||||
}
|
||||
#define init_class_obj(__type, __obj, ...) \
|
||||
__INIT_CLASS_OBJ(__type, __obj, __VA_ARGS__)
|
||||
|
||||
#define __EXTERN_CLASS_OBJ(__type, __obj) \
|
||||
extern union { \
|
||||
class(__type) __##__obj; \
|
||||
__type; \
|
||||
}__obj;
|
||||
#define extern_class_obj(__type, __obj) \
|
||||
__EXTERN_CLASS_OBJ( __type, __obj )
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* new standard (lower case) *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
# undef __class_internal
|
||||
# define __class_internal(__src, __des, __type, ...) \
|
||||
class(__type) *(__des) = (class(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(__des); \
|
||||
__with_class(__type, (__src), __VA_ARGS__)
|
||||
|
||||
# undef class_internal
|
||||
# define class_internal(__src, __des, __type, ...) \
|
||||
__class_internal(__src, __des, __type, __VA_ARGS__)
|
||||
|
||||
# undef __with_class
|
||||
# define __with_class(__type, __src, ...) \
|
||||
{ \
|
||||
class(__type)*_ =(class(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(_); \
|
||||
__VA_ARGS__; \
|
||||
} \
|
||||
for (class(__type)*_ =(class(__type) *)(__src); NULL != _; _ = NULL)
|
||||
|
||||
# undef with_class
|
||||
# define with_class(__type, __src, ...) \
|
||||
__with_class(__type, __src, __VA_ARGS__)
|
||||
|
||||
#undef which
|
||||
#define which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
/*============================ TYPES =========================================*/
|
||||
|
||||
/*============================ GLOBAL VARIABLES ==============================*/
|
||||
/*============================ LOCAL VARIABLES ===============================*/
|
||||
/*============================ PROTOTYPES ====================================*/
|
||||
|
||||
#undef __PLOOC_CLASS_IMPLEMENT__
|
||||
#undef __PLOOC_CLASS_INHERIT__
|
||||
#undef __PLOOC_CLASS_IMPLEMENT
|
||||
#undef __PLOOC_CLASS_INHERIT
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_PLOOC_CLASS_BLACK_BOX_H
|
||||
@@ -0,0 +1,200 @@
|
||||
#ifndef HW_LIB_PLOOC_CLASS_SIMPLE_H
|
||||
#define HW_LIB_PLOOC_CLASS_SIMPLE_H
|
||||
|
||||
//#include "plooc_class.h"
|
||||
|
||||
/*============================ INCLUDES ======================================*/
|
||||
//#include <stdint.h>
|
||||
|
||||
/*! \NOTE the uint_fast8_t used in this header file is defined in stdint.h
|
||||
if you don't have stdint.h supported in your toolchain, you should
|
||||
define uint_fast8_t all by yourself with following rule:
|
||||
a. if the target processor is 8 bits, define it as uint8_t
|
||||
b. if the target processor is 16 bits, define it as uint16_t
|
||||
c. if the target processor is 32 bits, define it as uint32_t
|
||||
d. if the target processor is 64 bits, define it as either uint32_t or
|
||||
uint64_t
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*============================ MACROS ========================================*/
|
||||
#undef private_member
|
||||
#undef protected_member
|
||||
#undef public_member
|
||||
|
||||
|
||||
/*============================ MACROFIED FUNCTIONS ===========================*/
|
||||
|
||||
#ifndef __PLOOC_CLASS_SIMPLE_H__
|
||||
#define __PLOOC_CLASS_SIMPLE_H__
|
||||
|
||||
# define __def_simple_class(__name) struct __name
|
||||
# define def_simple_class(__name) __def_simple_class(__name)
|
||||
# define define_simple_class(__name) def_simple_class(__name)
|
||||
# define declare_simple_class(__name) typedef struct __name __name;
|
||||
# define dcl_simple_class(__name) declare_simple_class(__name)
|
||||
|
||||
#endif /* __PLOOC_CLASS_SIMPLE_H__ */
|
||||
|
||||
#if defined(__OOC_DEBUG__)
|
||||
|
||||
# define private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
#elif defined(__PLOOC_CLASS_IMPLEMENT__) || defined(__PLOOC_CLASS_IMPLEMENT)
|
||||
|
||||
# define private_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
#elif defined(__PLOOC_CLASS_INHERIT__) || defined(__PLOOC_CLASS_INHERIT)
|
||||
|
||||
# define private_member(...) PLOOC_INVISIBLE(__VA_ARGS__)
|
||||
# define protected_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
# define public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
#else /* __PLOOC_CLASS_EXTERN */
|
||||
|
||||
# define private_member(...) PLOOC_INVISIBLE(__VA_ARGS__)
|
||||
# define protected_member(...) PLOOC_INVISIBLE(__VA_ARGS__)
|
||||
# define public_member(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
// code below is just try to be compatible with plooc_class_strict
|
||||
#undef declare_class
|
||||
#undef dcl_class
|
||||
#undef def_class
|
||||
#undef define_class
|
||||
#undef __def_class
|
||||
#undef end_def_class
|
||||
#undef end_define_class
|
||||
#undef __end_def_class
|
||||
#undef extern_class
|
||||
#undef __extern_class
|
||||
#undef end_extern_class
|
||||
#undef __end_extern_class
|
||||
|
||||
|
||||
#define __end_def_class(...)
|
||||
|
||||
#define __def_class(__name, ...) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__VA_ARGS__ \
|
||||
};
|
||||
|
||||
|
||||
#if defined(__PLOOC_CLASS_IMPLEMENT__) || defined(__PLOOC_CLASS_IMPLEMENT)
|
||||
|
||||
# undef __class
|
||||
# define __class(__name) __name
|
||||
|
||||
# undef class
|
||||
# define class(__name) __class(__name)
|
||||
|
||||
# undef __with_class
|
||||
# define __with_class(__type, __src, ...) \
|
||||
{ \
|
||||
class(__type)*_ =(class(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(_); \
|
||||
__VA_ARGS__; \
|
||||
} \
|
||||
for (class(__type)*_ =(class(__type) *)(__src); NULL != _; _ = NULL)
|
||||
|
||||
# undef with_class
|
||||
# define with_class(__type, __src, ...) \
|
||||
__with_class(__type, __src, __VA_ARGS__)
|
||||
|
||||
# undef __class_internal
|
||||
# define __class_internal(__src, __des, __type, ...) \
|
||||
class(__type) *(__des) = (class(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(__des); \
|
||||
__with_class(__type, (__src), __VA_ARGS__)
|
||||
|
||||
# undef class_internal
|
||||
# define class_internal(__src, __des, __type, ...) \
|
||||
__class_internal(__src, __des, __type, __VA_ARGS__)
|
||||
|
||||
#define __extern_class(...)
|
||||
|
||||
#define __end_extern_class(...)
|
||||
|
||||
#elif defined(__PLOOC_CLASS_INHERIT__) || defined(__PLOOC_CLASS_INHERIT)
|
||||
|
||||
# undef __class_protected
|
||||
# define __class_protected(__name) __name
|
||||
|
||||
# undef class_protected
|
||||
# define class_protected(__name) __class_protected(__name)
|
||||
|
||||
|
||||
|
||||
# undef __with_protected
|
||||
# define __with_protected(__type, __src, ...) \
|
||||
{ \
|
||||
class_protected(__type)*_ =(class_protected(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(_); \
|
||||
__VA_ARGS__; \
|
||||
}
|
||||
|
||||
# undef with_protected
|
||||
# define with_protected(__type, __src, ...) \
|
||||
__with_protected(__type, __src, __VA_ARGS__)
|
||||
|
||||
|
||||
# undef __protected_internal
|
||||
# define __protected_internal(__src, __des, __type, ...) \
|
||||
class_protected(__type) *(__des)=(class_protected(__type) *)(__src);\
|
||||
PLOOC_UNUSED_PARAM(__des); \
|
||||
__with_protected(__type, __src, __VA_ARGS__)
|
||||
|
||||
# undef protected_internal
|
||||
# define protected_internal(__src, __des, __type, ...) \
|
||||
__protected_internal(__src, __des, __type, __VA_ARGS__)
|
||||
|
||||
#define __extern_class(...)
|
||||
|
||||
#define __end_extern_class(...)
|
||||
|
||||
#else /* __PLOOC_CLASS_EXTERN */
|
||||
|
||||
#define __extern_class(...) __def_class(__VA_ARGS__)
|
||||
|
||||
#define __end_extern_class(...)
|
||||
|
||||
#endif
|
||||
|
||||
#undef which
|
||||
#define which(...) PLOOC_VISIBLE(__VA_ARGS__)
|
||||
|
||||
#define def_class(__name, ...) __def_class(__name, __VA_ARGS__)
|
||||
#define define_class(__name, ...) def_class(__name, __VA_ARGS__)
|
||||
|
||||
#define end_def_class(...) __end_def_class(__VA_ARGS__)
|
||||
#define end_define_class(...) end_def_class(__VA_ARGS__)
|
||||
|
||||
#define dcl_class(__name) typedef struct __name __name;
|
||||
#define declare_class(__name) typedef struct __name __name;
|
||||
|
||||
#define extern_class(__name, ...) __extern_class(__name, __VA_ARGS__)
|
||||
|
||||
#define end_extern_class(__name, ...) __end_extern_class(__name, __VA_ARGS__)
|
||||
|
||||
#undef __PLOOC_CLASS_IMPLEMENT__
|
||||
#undef __PLOOC_CLASS_INHERIT__
|
||||
#undef __PLOOC_CLASS_IMPLEMENT
|
||||
#undef __PLOOC_CLASS_INHERIT
|
||||
/*============================ TYPES =========================================*/
|
||||
/*============================ GLOBAL VARIABLES ==============================*/
|
||||
/*============================ LOCAL VARIABLES ===============================*/
|
||||
/*============================ PROTOTYPES ====================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_PLOOC_CLASS_SIMPLE_H
|
||||
@@ -0,0 +1,444 @@
|
||||
#ifndef HW_LIB_PLOOC_CLASS_STRICT_H
|
||||
#define HW_LIB_PLOOC_CLASS_STRICT_H
|
||||
|
||||
|
||||
//#include "plooc_class.h"
|
||||
|
||||
/*============================ INCLUDES ======================================*/
|
||||
//#include <stdint.h>
|
||||
|
||||
/*! \NOTE the uint_fast8_t used in this header file is defined in stdint.h
|
||||
if you don't have stdint.h supported in your toolchain, you should
|
||||
define uint_fast8_t all by yourself with following rule:
|
||||
a. if the target processor is 8 bits, define it as uint8_t
|
||||
b. if the target processor is 16 bits, define it as uint16_t
|
||||
c. if the target processor is 32 bits, define it as uint32_t
|
||||
d. if the target processor is 64 bits, define it as either uint32_t or
|
||||
uint64_t
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*============================ MACROS ========================================*/
|
||||
#undef dcl_class
|
||||
#undef declare_class
|
||||
#undef def_class
|
||||
#undef define_class
|
||||
#undef __def_class2
|
||||
#undef __def_class3
|
||||
#undef __def_class4
|
||||
#undef __def_class5
|
||||
#undef __def_class6
|
||||
#undef __def_class7
|
||||
#undef __def_class8
|
||||
#undef __def_class
|
||||
#undef end_def_class
|
||||
#undef end_define_class
|
||||
#undef __end_def_class
|
||||
#undef extern_class
|
||||
#undef __extern_class
|
||||
#undef end_extern_class
|
||||
#undef __end_extern_class
|
||||
|
||||
/*============================ MACROFIED FUNCTIONS ===========================*/
|
||||
|
||||
|
||||
#if defined(__PLOOC_CLASS_IMPLEMENT__) || defined(__PLOOC_CLASS_IMPLEMENT)
|
||||
|
||||
# define __def_class2(__name, _1) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_1) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
};
|
||||
|
||||
# define __def_class3(__name, _1, _2) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_2) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
};
|
||||
|
||||
# define __def_class4(__name, _1, _2, _3) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_3) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
};
|
||||
|
||||
# define __def_class5(__name, _1, _2, _3, _4) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_4) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
};
|
||||
|
||||
# define __def_class6(__name, _1, _2, _3, _4, _5) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_5) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
};
|
||||
|
||||
# define __def_class7(__name, _1, _2, _3, _4, _5, _6) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_6) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_6) \
|
||||
};
|
||||
|
||||
# define __def_class8(__name, _1, _2, _3, _4, _5, _6, _7) \
|
||||
typedef struct __name __name; \
|
||||
typedef struct __##__name __##__name; \
|
||||
struct __##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_6) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRI_,_7) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_6) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_7) \
|
||||
};
|
||||
|
||||
# define __end_def_class(...)
|
||||
|
||||
# define __extern_class(...)
|
||||
# define __end_extern_class(...)
|
||||
|
||||
|
||||
# undef __class
|
||||
# define __class(__name) __##__name
|
||||
|
||||
# undef class
|
||||
# define class(__name) __class(__name)
|
||||
|
||||
|
||||
# undef __with_class
|
||||
# define __with_class(__type, __src, ...) \
|
||||
{ \
|
||||
class(__type)*_ =(class(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(_); \
|
||||
__VA_ARGS__; \
|
||||
} \
|
||||
for (class(__type)*_ =(class(__type) *)(__src);NULL != _; _ = NULL)
|
||||
|
||||
# undef with_class
|
||||
# define with_class(__type, __src, ...) \
|
||||
__with_class(__type, __src, __VA_ARGS__)
|
||||
|
||||
# undef __class_internal
|
||||
# define __class_internal(__src, __des, __type, ...) \
|
||||
class(__type) *(__des) = (class(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(__des); \
|
||||
__with_class(__type, (__src), __VA_ARGS__)
|
||||
|
||||
|
||||
# undef class_internal
|
||||
# define class_internal(__src, __des, __type,...) \
|
||||
__class_internal(__src, __des, __type, __VA_ARGS__)
|
||||
|
||||
|
||||
#elif defined(__PLOOC_CLASS_INHERIT__) || defined(__PLOOC_CLASS_INHERIT)
|
||||
|
||||
# define __def_class2(__name, _1) \
|
||||
typedef struct __name __name; \
|
||||
struct __protected_##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_1) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
};
|
||||
|
||||
# define __def_class3(__name, _1, _2) \
|
||||
typedef struct __name __name; \
|
||||
struct __protected_##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_2) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
};
|
||||
|
||||
# define __def_class4(__name, _1, _2, _3) \
|
||||
typedef struct __name __name; \
|
||||
struct __protected_##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_3) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
};
|
||||
|
||||
# define __def_class5(__name, _1, _2, _3, _4) \
|
||||
typedef struct __name __name; \
|
||||
struct __protected_##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_4) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
};
|
||||
|
||||
# define __def_class6(__name, _1, _2, _3, _4, _5) \
|
||||
typedef struct __name __name; \
|
||||
struct __protected_##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_5) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
};
|
||||
|
||||
# define __def_class7(__name, _1, _2, _3, _4, _5, _6) \
|
||||
typedef struct __name __name; \
|
||||
struct __protected_##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_6) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_6) \
|
||||
};
|
||||
|
||||
# define __def_class8(__name, _1, _2, _3, _4, _5, _6, _7) \
|
||||
typedef struct __name __name; \
|
||||
struct __protected_##__name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_6) \
|
||||
__PLOOC_CONNECT2(__PLOOC_PRO_,_7) \
|
||||
}; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_6) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_7) \
|
||||
};
|
||||
|
||||
|
||||
|
||||
# define __end_def_class(...)
|
||||
|
||||
# define __extern_class(...)
|
||||
|
||||
# define __end_extern_class(...)
|
||||
|
||||
# undef __class_protected
|
||||
# define __class_protected(__name) struct __protected_##__name
|
||||
|
||||
# undef class_protected
|
||||
# define class_protected(__name) __class_protected(__name)
|
||||
|
||||
|
||||
# undef __with_protected
|
||||
# define __with_protected(__type, __src, ...) \
|
||||
{ \
|
||||
class_protected(__type)*_ =(class_protected(__type) *)(__src); \
|
||||
PLOOC_UNUSED_PARAM(_); \
|
||||
__VA_ARGS__; \
|
||||
} \
|
||||
for ( class_protected(__type)*_ =(class_protected(__type) *)(__src); \
|
||||
NULL != _; \
|
||||
_ = NULL)
|
||||
|
||||
# undef with_protected
|
||||
# define with_protected(__type, __src, ...) \
|
||||
__with_protected(__type, __src, __VA_ARGS__)
|
||||
|
||||
# undef __protected_internal
|
||||
# define __protected_internal(__src, __des, __type, ...) \
|
||||
class_protected(__type) *(__des)=(class_protected(__type) *)(__src);\
|
||||
PLOOC_UNUSED_PARAM(__des); \
|
||||
__with_protected(__type, __src, __VA_ARGS__)
|
||||
|
||||
# undef protected_internal
|
||||
# define protected_internal(__src, __des, __type, ...) \
|
||||
__protected_internal(__src, __des, __type, __VA_ARGS__)
|
||||
|
||||
|
||||
#else /* __PLOOC_CLASS_EXTERN */
|
||||
|
||||
# define __def_class2(__name, _1) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
};
|
||||
|
||||
# define __def_class3(__name, _1, _2) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
};
|
||||
|
||||
# define __def_class4(__name, _1, _2, _3) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
};
|
||||
|
||||
# define __def_class5(__name, _1, _2, _3, _4) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
};
|
||||
|
||||
# define __def_class6(__name, _1, _2, _3, _4, _5) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
};
|
||||
|
||||
# define __def_class7(__name, _1, _2, _3, _4, _5, _6) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_6) \
|
||||
};
|
||||
|
||||
# define __def_class8(__name, _1, _2, _3, _4, _5, _6, _7) \
|
||||
typedef struct __name __name; \
|
||||
struct __name { \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_1) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_2) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_3) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_4) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_5) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_6) \
|
||||
__PLOOC_CONNECT2(__PLOOC_EXT_,_7) \
|
||||
};
|
||||
|
||||
# define __end_def_class(...)
|
||||
|
||||
#define __extern_class(...) __PLOOC_EVAL(__def_class, __VA_ARGS__) \
|
||||
(__VA_ARGS__)
|
||||
|
||||
#define __end_extern_class(...)
|
||||
|
||||
#endif
|
||||
|
||||
#define def_class(...) __PLOOC_EVAL(__def_class, __VA_ARGS__) \
|
||||
(__VA_ARGS__)
|
||||
#define define_class(...) def_class(__VA_ARGS__)
|
||||
|
||||
#define end_def_class(...) __end_def_class(__VA_ARGS__)
|
||||
#define end_define_class(...) end_def_class(__VA_ARGS__)
|
||||
|
||||
#define declare_class(__name) typedef struct __name __name;
|
||||
#define dcl_class(__name) declare_class(__name)
|
||||
|
||||
#define extern_class(...) __extern_class(__VA_ARGS__)
|
||||
#define end_extern_class(...) __end_extern_class(__VA_ARGS__)
|
||||
|
||||
|
||||
#undef __PLOOC_CLASS_IMPLEMENT__
|
||||
#undef __PLOOC_CLASS_INHERIT__
|
||||
#undef __PLOOC_CLASS_IMPLEMENT
|
||||
#undef __PLOOC_CLASS_INHERIT
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_PLOOC_CLASS_STRICT_H
|
||||
@@ -0,0 +1,806 @@
|
||||
//
|
||||
// Created by lydxh on 24-11-27.
|
||||
//
|
||||
|
||||
#ifndef HW_LIB_TICKS_H
|
||||
#define HW_LIB_TICKS_H
|
||||
/*============================ INCLUDES ======================================*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*============================ MACROS ========================================*/
|
||||
|
||||
|
||||
/*!
|
||||
* \addtogroup gHelper 4 Helper
|
||||
* @{
|
||||
*/
|
||||
|
||||
// for IAR
|
||||
#undef __IS_COMPILER_IAR__
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
# define __IS_COMPILER_IAR__ 1
|
||||
#endif
|
||||
|
||||
// for arm compiler 5
|
||||
#undef __IS_COMPILER_ARM_COMPILER_5__
|
||||
#if ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION < 6000000))
|
||||
# define __IS_COMPILER_ARM_COMPILER_5__ 1
|
||||
#endif
|
||||
|
||||
|
||||
//for arm compiler 6
|
||||
|
||||
#undef __IS_COMPILER_ARM_COMPILER_6__
|
||||
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
# define __IS_COMPILER_ARM_COMPILER_6__ 1
|
||||
#endif
|
||||
#undef __IS_COMPILER_ARM_COMPILER__
|
||||
#if defined(__IS_COMPILER_ARM_COMPILER_5__) && __IS_COMPILER_ARM_COMPILER_5__ \
|
||||
|| defined(__IS_COMPILER_ARM_COMPILER_6__) && __IS_COMPILER_ARM_COMPILER_6__
|
||||
# define __IS_COMPILER_ARM_COMPILER__ 1
|
||||
#endif
|
||||
|
||||
// for clang
|
||||
#undef __IS_COMPILER_LLVM__
|
||||
#if defined(__clang__) && !__IS_COMPILER_ARM_COMPILER_6__
|
||||
# define __IS_COMPILER_LLVM__ 1
|
||||
#else
|
||||
|
||||
// for gcc
|
||||
# undef __IS_COMPILER_GCC__
|
||||
# if defined(__GNUC__) && !(defined(__IS_COMPILER_ARM_COMPILER__) \
|
||||
|| defined(__IS_COMPILER_LLVM__) \
|
||||
|| defined(__IS_COMPILER_IAR__))
|
||||
# define __IS_COMPILER_GCC__ 1
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __PERF_COUNT_PLATFORM_SPECIFIC_HEADER__
|
||||
# include __PERF_COUNT_PLATFORM_SPECIFIC_HEADER__
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
# pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
# pragma clang diagnostic ignored "-Wdeclaration-after-statement"
|
||||
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
# pragma clang diagnostic ignored "-Wgnu-statement-expression"
|
||||
# pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||
# pragma clang diagnostic ignored "-Wshadow"
|
||||
# pragma clang diagnostic ignored "-Wshorten-64-to-32"
|
||||
# pragma clang diagnostic ignored "-Wcompound-token-split-by-macro"
|
||||
# pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
|
||||
# pragma diag_suppress 550
|
||||
#elif defined(__IS_COMPILER_GCC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wpedantic"
|
||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
# pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
# pragma GCC diagnostic ignored "-Wformat="
|
||||
#endif
|
||||
|
||||
#ifndef __PLOOC_VA_NUM_ARGS_IMPL
|
||||
# define __PLOOC_VA_NUM_ARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, \
|
||||
_12, _13, _14, _15, _16, __N, ...) __N
|
||||
#endif
|
||||
|
||||
#ifndef __PLOOC_VA_NUM_ARGS
|
||||
#define __PLOOC_VA_NUM_ARGS(...) \
|
||||
__PLOOC_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9, \
|
||||
8,7,6,5,4,3,2,1,0)
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED_PARAM
|
||||
# define UNUSED_PARAM(__VAR) (void)(__VAR)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(__a, __b) ((__a) <= (__b) ? (__a) : (__b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(__a, __b) ((__a) >= (__b) ? (__a) : (__b))
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief an attribute for static variables that no initialisation is required
|
||||
* in the C startup process.
|
||||
*/
|
||||
#ifndef PERF_NOINIT
|
||||
# if defined(__IS_COMPILER_ARM_COMPILER_5__)
|
||||
# define PERF_NOINIT __attribute__(( section( ".bss.noinit"),zero_init))
|
||||
# elif defined(__IS_COMPILER_ARM_COMPILER_6__)
|
||||
# define PERF_NOINIT __attribute__(( section( ".bss.noinit")))
|
||||
# elif defined(__IS_COMPILER_IAR__)
|
||||
# define PERF_NOINIT __no_init
|
||||
# elif (defined(__IS_COMPILER_GCC__) || defined(__IS_COMPILER_LLVM__)) && !defined(__APPLE__)
|
||||
# define PERF_NOINIT __attribute__(( section( ".bss.noinit")))
|
||||
# else
|
||||
# define PERF_NOINIT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#undef __CONNECT2
|
||||
#undef __CONNECT3
|
||||
#undef __CONNECT4
|
||||
#undef __CONNECT5
|
||||
#undef __CONNECT6
|
||||
#undef __CONNECT7
|
||||
#undef __CONNECT8
|
||||
#undef __CONNECT9
|
||||
|
||||
#undef CONNECT2
|
||||
#undef CONNECT3
|
||||
#undef CONNECT4
|
||||
#undef CONNECT5
|
||||
#undef CONNECT6
|
||||
#undef CONNECT7
|
||||
#undef CONNECT8
|
||||
#undef CONNECT9
|
||||
|
||||
#undef CONNECT
|
||||
|
||||
#undef __MACRO_EXPANDING
|
||||
#define __MACRO_EXPANDING(...) __VA_ARGS__
|
||||
|
||||
#define __CONNECT2(__A, __B) __A##__B
|
||||
#define __CONNECT3(__A, __B, __C) __A##__B##__C
|
||||
#define __CONNECT4(__A, __B, __C, __D) __A##__B##__C##__D
|
||||
#define __CONNECT5(__A, __B, __C, __D, __E) __A##__B##__C##__D##__E
|
||||
#define __CONNECT6(__A, __B, __C, __D, __E, __F) __A##__B##__C##__D##__E##__F
|
||||
#define __CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
|
||||
__A##__B##__C##__D##__E##__F##__G
|
||||
#define __CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
|
||||
__A##__B##__C##__D##__E##__F##__G##__H
|
||||
#define __CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
|
||||
__A##__B##__C##__D##__E##__F##__G##__H##__I
|
||||
|
||||
#define ALT_CONNECT2(__A, __B) __CONNECT2(__A, __B)
|
||||
#define CONNECT2(__A, __B) __CONNECT2(__A, __B)
|
||||
#define CONNECT3(__A, __B, __C) __CONNECT3(__A, __B, __C)
|
||||
#define CONNECT4(__A, __B, __C, __D) __CONNECT4(__A, __B, __C, __D)
|
||||
#define CONNECT5(__A, __B, __C, __D, __E) __CONNECT5(__A, __B, __C, __D, __E)
|
||||
#define CONNECT6(__A, __B, __C, __D, __E, __F) \
|
||||
__CONNECT6(__A, __B, __C, __D, __E, __F)
|
||||
#define CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
|
||||
__CONNECT7(__A, __B, __C, __D, __E, __F, __G)
|
||||
#define CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
|
||||
__CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H)
|
||||
#define CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
|
||||
__CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I)
|
||||
|
||||
#define CONNECT(...) \
|
||||
ALT_CONNECT2(CONNECT, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#undef __using1
|
||||
#undef __using2
|
||||
#undef __using3
|
||||
#undef __using4
|
||||
#undef using
|
||||
|
||||
#define __using1(__declare) \
|
||||
for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL; \
|
||||
)
|
||||
|
||||
#define __using2(__declare, __on_leave_expr) \
|
||||
for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL; \
|
||||
(__on_leave_expr) \
|
||||
)
|
||||
|
||||
#define __using3(__declare, __on_enter_expr, __on_leave_expr) \
|
||||
for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL ? \
|
||||
((__on_enter_expr),1) : 0; \
|
||||
(__on_leave_expr) \
|
||||
)
|
||||
|
||||
#define __using4(__dcl1, __dcl2, __on_enter_expr, __on_leave_expr) \
|
||||
for (__dcl1, __dcl2, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
|
||||
CONNECT3(__using_, __LINE__,_ptr)++ == NULL ? \
|
||||
((__on_enter_expr),1) : 0; \
|
||||
(__on_leave_expr) \
|
||||
)
|
||||
|
||||
#define using(...) \
|
||||
CONNECT2(__using, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
|
||||
#undef __with2
|
||||
#undef __with3
|
||||
#undef with
|
||||
|
||||
#define __with1(__addr) \
|
||||
using(__typeof__(*__addr) *_=(__addr))
|
||||
|
||||
#define __with2(__type, __addr) \
|
||||
using(__type *_=(__addr))
|
||||
#define __with3(__type, __addr, __item) \
|
||||
using(__type *_=(__addr), *__item = _, _=_,_=_ )
|
||||
|
||||
#define with(...) \
|
||||
CONNECT2(__with, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#undef _
|
||||
|
||||
#ifndef dimof
|
||||
# define dimof(__array) (sizeof(__array)/sizeof(__array[0]))
|
||||
#endif
|
||||
|
||||
|
||||
#define SAFE_NAME(__NAME) CONNECT3(__,__NAME,__LINE__)
|
||||
|
||||
#undef foreach2
|
||||
#undef foreach3
|
||||
#undef foreach
|
||||
|
||||
#define foreach1(__array) \
|
||||
using(__typeof__(__array[0]) *_ = __array) \
|
||||
for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
|
||||
SAFE_NAME(count) > 0; \
|
||||
_++, SAFE_NAME(count)-- \
|
||||
)
|
||||
|
||||
#define foreach2(__type, __array) \
|
||||
using(__type *_ = __array) \
|
||||
for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
|
||||
SAFE_NAME(count) > 0; \
|
||||
_++, SAFE_NAME(count)-- \
|
||||
)
|
||||
|
||||
#define foreach3(__type, __array, __item) \
|
||||
using(__type *_ = __array, *__item = _, _ = _, _ = _ ) \
|
||||
for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
|
||||
SAFE_NAME(count) > 0; \
|
||||
_++, __item = _, SAFE_NAME(count)-- \
|
||||
)
|
||||
|
||||
#define foreach(...) \
|
||||
CONNECT2(foreach, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#ifndef safe_atom_code
|
||||
# define safe_atom_code() \
|
||||
using( ticks_global_interrupt_status_t SAFE_NAME(temp) = \
|
||||
ticks_port_disable_global_interrupt(), \
|
||||
ticks_port_resume_global_interrupt(SAFE_NAME(temp)))
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __WEAK
|
||||
# define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#ifndef __STATIC_INLINE
|
||||
# define __STATIC_INLINE static inline
|
||||
#endif
|
||||
|
||||
#ifndef __IRQ_SAFE
|
||||
# define __IRQ_SAFE \
|
||||
using( ticks_global_interrupt_status_t SAFE_NAME(temp) = \
|
||||
ticks_port_disable_global_interrupt(), \
|
||||
ticks_port_resume_global_interrupt(SAFE_NAME(temp)))
|
||||
#endif
|
||||
|
||||
#ifndef __perf_counter_printf__
|
||||
# define __perf_counter_printf__ printf
|
||||
#endif
|
||||
|
||||
/* deprecated macro for backward compatibility */
|
||||
#define user_code_insert_to_systick_handler \
|
||||
ticks_port_insert_to_system_timer_insert_ovf_handler
|
||||
|
||||
#if __PLOOC_VA_NUM_ARGS() != 0
|
||||
#warning Please enable GNU extensions, it is required by __cycleof__() and \
|
||||
__super_loop_monitor__()
|
||||
#endif
|
||||
|
||||
#if defined(__PERF_COUNTER_CFG_USE_SYSTICK_WRAPPER__) \
|
||||
&& (!defined(__TICKS_USE_PORTING__) \
|
||||
|| (defined(__TICKS_USE_PORTING__) && (0 == __TICKS_USE_PORTING__)))
|
||||
|
||||
# if defined(__IS_COMPILER_ARM_COMPILER_5__) && __IS_COMPILER_ARM_COMPILER_5__
|
||||
# pragma import(__ensure_systick_wrapper)
|
||||
# elif (defined(__GNUC__) || defined(__clang__)) \
|
||||
&& (!defined(__IS_COMPILER_IAR__) || !__IS_COMPILER_IAR__)
|
||||
__asm(".global __ensure_systick_wrapper\n\t");
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __ticks_sync_barrier__
|
||||
|
||||
/* default implementation */
|
||||
#if defined(__clang__) || __IS_COMPILER_GCC__
|
||||
# define __ticks_sync_barrier__(...) __sync_synchronize()
|
||||
#else
|
||||
# define __ticks_sync_barrier__(...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*! @} */
|
||||
|
||||
/*============================ MACROFIED FUNCTIONS ===========================*/
|
||||
|
||||
/*!
|
||||
* \addtogroup gBasic 1 Basic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief measure the cycle count of a given code segment
|
||||
* \param[in] __STR a description string for the measurement
|
||||
* \param[in] ... an optional code segement, in which we can read the measured
|
||||
* result from __cycle_count__.
|
||||
* \details Here is an example:
|
||||
E.g.
|
||||
\code
|
||||
__cycleof__("printf") {
|
||||
printf("hello world\r\n");
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
#define __cycleof__(__STR, ...) \
|
||||
using(int64_t _ = get_system_ticks(), __cycle_count__ = _, \
|
||||
{__ticks_sync_barrier__();}, \
|
||||
{ \
|
||||
__ticks_sync_barrier__(); \
|
||||
_ = get_system_ticks() - _ - g_nOffset; \
|
||||
__cycle_count__ = _; \
|
||||
if (__PLOOC_VA_NUM_ARGS(__VA_ARGS__) == 0) { \
|
||||
__perf_counter_printf__("\r\n"); \
|
||||
__perf_counter_printf__("-[Cycle Report]"); \
|
||||
__perf_counter_printf__( \
|
||||
"------------------------------------\r\n"); \
|
||||
__perf_counter_printf__( \
|
||||
__STR " total cycle count: %ld [%08lx]\r\n", \
|
||||
(long)_, (long)_); \
|
||||
} else { \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
})
|
||||
|
||||
/*!
|
||||
* \brief measure the cpu usage for a given code segment and print out the
|
||||
* result in percentage.
|
||||
* \param[in] __CNT generate result on every given iterations
|
||||
* \param[in] ... an optional code segement, in which we can read the measured
|
||||
* result from __usage__ which is a float value.
|
||||
* \details Here is an example, 50% cpu time:
|
||||
E.g.
|
||||
\code
|
||||
while (1) {
|
||||
__cpu_usage__(100) {
|
||||
delay_us(5000);
|
||||
}
|
||||
delay_us(5000);
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
#define __cpu_usage__(__CNT, ...) \
|
||||
static int64_t SAFE_NAME(s_lTimestamp) = 0, SAFE_NAME(s_lTotal) = 0; \
|
||||
static uint32_t SAFE_NAME(s_wLoopCounter) = (__CNT); \
|
||||
using(float __usage__ = 0, ({ \
|
||||
if (0 == SAFE_NAME(s_wLoopCounter)) { \
|
||||
__usage__ = (float)((double)SAFE_NAME(s_lTotal) \
|
||||
/ (double)( get_system_ticks() \
|
||||
- SAFE_NAME(s_lTimestamp))); \
|
||||
__usage__ *= 100.0f; \
|
||||
SAFE_NAME(s_lTimestamp) = 0; \
|
||||
SAFE_NAME(s_lTotal) = 0; \
|
||||
if (__PLOOC_VA_NUM_ARGS(__VA_ARGS__) == 0) { \
|
||||
__perf_counter_printf__("CPU Usage %3.2f%%\r\n", (double)__usage__);\
|
||||
} else { \
|
||||
__VA_ARGS__ \
|
||||
} \
|
||||
} \
|
||||
if (0 == SAFE_NAME(s_lTimestamp)) { \
|
||||
SAFE_NAME(s_lTimestamp) = get_system_ticks(); \
|
||||
SAFE_NAME(s_wLoopCounter) = (__CNT); \
|
||||
} \
|
||||
start_task_cycle_counter();}), \
|
||||
({SAFE_NAME(s_lTotal) += stop_task_cycle_counter(); \
|
||||
SAFE_NAME(s_wLoopCounter)--;}))
|
||||
|
||||
#define __cpu_time__ __cpu_usage__
|
||||
|
||||
/*!
|
||||
* \addtogroup gBasicTimerService 1.2 Timer Service
|
||||
* \ingroup gBasic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief should not use
|
||||
*/
|
||||
#define ticks_is_time_out_ms0() true
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in ms and check the status
|
||||
*
|
||||
* \param[in] __ms a time period in millisecond
|
||||
* \param[in] __timestamp_ptr an optional timestamp holder
|
||||
* \param[in] __auto_reload whether starting next period after a timeout event
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_ms3(__ms, __timestamp_ptr, __auto_reload) \
|
||||
({ static int64_t SAFE_NAME(s_lTimestamp); (void)SAFE_NAME(s_lTimestamp); \
|
||||
__ticks_is_time_out(ticks_convert_ms_to_ticks(__ms), \
|
||||
(__timestamp_ptr), (__auto_reload));})
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in ms and check the status
|
||||
*
|
||||
* \param[in] __ms a time period in millisecond
|
||||
* \param[in] __timestamp_ptr an optional timestamp holder
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_ms2(__ms, __timestamp_ptr) \
|
||||
ticks_is_time_out_ms3((__ms), (__timestamp_ptr), true)
|
||||
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in ms and check the status
|
||||
*
|
||||
* \param[in] __ms a time period in millisecond
|
||||
* \param[in] __timestamp_ptr an optional timestamp holder
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_ms1(__ms) \
|
||||
ticks_is_time_out_ms3((__ms), &SAFE_NAME(s_lTimestamp), true)
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in ms and check the status
|
||||
*
|
||||
* \param[in] __ms a time period in millisecond
|
||||
* \param[in] ... an optional timestamp holder
|
||||
* \param[in] ... an optional indicator for whether starting next period after a timeout event
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_ms(...) \
|
||||
CONNECT2(ticks_is_time_out_ms, __PLOOC_VA_NUM_ARGS(__VA_ARGS__)) \
|
||||
(__VA_ARGS__)
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in us and check the status
|
||||
*
|
||||
* \param[in] __us a time period in microsecond
|
||||
* \param[in] __timestamp_ptr an optional timestamp holder
|
||||
* \param[in] __auto_reload whether starting next period after a timeout event
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_us3(__us, __timestamp_ptr, __auto_reload) \
|
||||
({ static int64_t SAFE_NAME(s_lTimestamp); (void)SAFE_NAME(s_lTimestamp); \
|
||||
__ticks_is_time_out(ticks_convert_us_to_ticks(__us), \
|
||||
(__timestamp_ptr), (__auto_reload));})
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in us and check the status
|
||||
*
|
||||
* \param[in] __us a time period in microsecond
|
||||
* \param[in] __timestamp_ptr an optional timestamp holder
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_us2(__us, __timestamp_ptr) \
|
||||
ticks_is_time_out_us3((__us), (__timestamp_ptr), true)
|
||||
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in us and check the status
|
||||
*
|
||||
* \param[in] __us a time period in microsecond
|
||||
* \param[in] __timestamp_ptr an optional timestamp holder
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_us1(__us) \
|
||||
ticks_is_time_out_us3((__us), &SAFE_NAME(s_lTimestamp), true)
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period in us and check the status
|
||||
*
|
||||
* \param[in] __us a time period in microsecond
|
||||
* \param[in] ... an optional timestamp holder
|
||||
* \param[in] ... an optional indicator for whether starting next period after a timeout event
|
||||
*
|
||||
* \return bool whether it is timeout
|
||||
*/
|
||||
#define ticks_is_time_out_us(...) \
|
||||
CONNECT2(ticks_is_time_out_us, __PLOOC_VA_NUM_ARGS(__VA_ARGS__)) \
|
||||
(__VA_ARGS__)
|
||||
|
||||
/*============================ TYPES =========================================*/
|
||||
typedef struct {
|
||||
int64_t lStart;
|
||||
int64_t lUsedTotal;
|
||||
int32_t nUsedRecent;
|
||||
uint16_t hwActiveCount;
|
||||
uint16_t : 15;
|
||||
uint16_t bEnabled: 1;
|
||||
} task_cycle_info_t;
|
||||
|
||||
typedef struct task_cycle_info_agent_t task_cycle_info_agent_t;
|
||||
|
||||
struct task_cycle_info_agent_t {
|
||||
task_cycle_info_t *ptInfo;
|
||||
task_cycle_info_agent_t *ptNext;
|
||||
task_cycle_info_agent_t *ptPrev;
|
||||
};
|
||||
|
||||
extern volatile int64_t g_lLastTimeStamp;
|
||||
extern volatile int32_t g_nOffset;
|
||||
|
||||
|
||||
__attribute__((noinline))
|
||||
extern int64_t get_system_ticks(void);
|
||||
|
||||
|
||||
#ifdef __TICKS_USE_LONG_CLOCK__
|
||||
/*! \note the prototype of this clock() is different from the one defined in
|
||||
*! time.h. As clock_t is usually defined as unsigned int, it is
|
||||
*! not big enough in Cortex-M system to hold a time-stamp. clock()
|
||||
*! defined here returns the timestamp since the begining of main()
|
||||
*! and its unit is clock cycle (rather than 1ms). Hence, for a system
|
||||
*! running under several hundreds MHz or even 1GHz, e.g. RT10xx from
|
||||
*! NXP, it is very easy to see a counter overflow as clock_t is
|
||||
*! defined as uint32_t in timer.h.
|
||||
*! Since we are not allowed to change the defintion of clock_t in
|
||||
*! official header file, i.e. time.h, I use a compatible prototype
|
||||
*! after I checked the AAPCS spec. So, the return of the clock() is
|
||||
*! int64_t, which will use the R0 to store the lower 32bits and R1
|
||||
*! to store the higher 32bits. When you are using the prototype from
|
||||
*! timer.h, caller will only take the lower 32bits stored in R0 and
|
||||
*! the higher 32bits stored in R1 will be ignored.
|
||||
*!
|
||||
*! If you want to use the non-overflow version of this clock(), please
|
||||
*! 1) define the MACRO: __PERF_CNT_USE_LONG_CLOCK__ in your project
|
||||
*! and 2) do not include system header file <time.h>
|
||||
*!
|
||||
*/
|
||||
#if !defined(__IS_COMPILER_IAR__)
|
||||
__attribute__((nothrow))
|
||||
#endif
|
||||
__attribute__((noinline))
|
||||
extern int64_t clock(void);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief try to set a start pointer for the performance counter
|
||||
*/
|
||||
static inline
|
||||
void start_cycle_counter(void) {
|
||||
g_lLastTimeStamp = get_system_ticks();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief calculate the elapsed cycle count since the last start point
|
||||
* \note you can have multiple stop_cycle_counter following one start point
|
||||
* \return int32_t the elapsed cycle count
|
||||
*/
|
||||
static inline
|
||||
int64_t stop_cycle_counter(void) {
|
||||
int64_t lTemp = (get_system_ticks() - g_lLastTimeStamp);
|
||||
|
||||
return lTemp - g_nOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*!
|
||||
* \addtogroup gBasicTimerService 1.2 Timer Service
|
||||
* \ingroup gBasic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief get the system timer frequency
|
||||
* \return uint32_t the system timer frequency in Hz
|
||||
*/
|
||||
extern uint32_t ticks_get_systimer_frequency(void);
|
||||
|
||||
/*!
|
||||
* \brief get the elapsed milliseconds since perf_counter is initialised
|
||||
* \return int64_t the elapsed milliseconds
|
||||
*/
|
||||
extern int64_t get_system_ms(void);
|
||||
|
||||
/*!
|
||||
* \brief get the elapsed microsecond since perf_counter is initialised
|
||||
* \return int64_t the elapsed microsecond
|
||||
*/
|
||||
extern int64_t get_system_us(void);
|
||||
|
||||
/*!
|
||||
* \brief delay specified time in microsecond
|
||||
* \param[in] wUs time in microsecond
|
||||
*/
|
||||
extern void delay_us(uint32_t wUs);
|
||||
|
||||
/*!
|
||||
* \brief delay specified time in millisecond
|
||||
* \param[in] wMs time in millisecond
|
||||
*/
|
||||
extern void delay_ms(uint32_t nMs);
|
||||
|
||||
/*!
|
||||
* \brief convert ticks of a reference timer to millisecond
|
||||
*
|
||||
* \param[in] lTick the tick count
|
||||
* \return int64_t the millisecond
|
||||
*/
|
||||
extern
|
||||
int64_t ticks_convert_ticks_to_ms(int64_t lTick);
|
||||
|
||||
/*!
|
||||
* \brief convert millisecond into ticks of the reference timer
|
||||
*
|
||||
* \param[in] wMS the target time in millisecond
|
||||
* \return int64_t the ticks
|
||||
*/
|
||||
extern
|
||||
int64_t ticks_convert_ms_to_ticks(uint32_t wMS);
|
||||
|
||||
/*!
|
||||
* \brief convert ticks of a reference timer to microsecond
|
||||
*
|
||||
* \param[in] lTick the tick count
|
||||
* \return int64_t the microsecond
|
||||
*/
|
||||
extern
|
||||
int64_t ticks_convert_ticks_to_us(int64_t lTick);
|
||||
|
||||
/*!
|
||||
* \brief convert microsecond into ticks of the reference timer
|
||||
*
|
||||
* \param[in] wUS the target time in microsecond
|
||||
* \return int64_t the ticks
|
||||
*/
|
||||
extern
|
||||
int64_t ticks_convert_us_to_ticks(uint32_t wUS);
|
||||
|
||||
/*!
|
||||
* \brief set an alarm with given period and check the status
|
||||
*
|
||||
* \param[in] lPeriod a time period in ticks
|
||||
* \param[in] plTimestamp a pointer points to an int64_t integer, if NULL is
|
||||
* passed, an static local variable inside the function will be used
|
||||
* \param[in] bAutoReload whether starting next period after a timeout event.
|
||||
* \return bool whether it is timeout or not
|
||||
*/
|
||||
extern
|
||||
bool __ticks_is_time_out(int64_t lPeriod, int64_t *plTimestamp, bool bAutoReload);
|
||||
|
||||
/*!
|
||||
* \addtogroup gBasic 1 Basic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
* Please ignore the following APIs unless you have encountered some known *
|
||||
* special conditions *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*! \brief initialise cycle counter service
|
||||
* \note - don't forget to tell the function whether the systick is already
|
||||
* used by user applications.
|
||||
* Don't worry, this cycle counter service won't affect your existing
|
||||
* systick service.
|
||||
*
|
||||
* \note - Usually the perf_counter can initialise itself with the help of
|
||||
* __attribute__((constructor(255))), this works fine in Arm Compiler
|
||||
* 5 (armcc), Arm Compiler 6 (armclang), arm gcc and llvm. It doesn't
|
||||
* work for IAR. So, when you are using IAR, please call this function
|
||||
* manually to initialise the perf_counter service.
|
||||
*
|
||||
* \note - Perf_counter library assumes that:
|
||||
* 1. Your project has already using SysTick
|
||||
* 2. It assumes that you have already implemented the SysTick_Handler
|
||||
* 3. It assumes that you have enabled the exception handling for
|
||||
* SysTick.
|
||||
* If these are not the case, please:
|
||||
* 1. Add an empty SysTick_Handler to your project if you don't have
|
||||
* one
|
||||
* 2. Make sure you have the SysTick Exception handling enabled
|
||||
* 3. And call function init_cycle_counter(false) if you doesn't
|
||||
* use SysTick in your project at all.
|
||||
*
|
||||
* \param[in] bIsSysTickOccupied A boolean value which indicates whether SysTick
|
||||
* is already used by user application.
|
||||
*
|
||||
* \return false Failed to initialize the timer counter, as the timer is not
|
||||
* available or IO error.
|
||||
* \return true initialization is successful.
|
||||
*/
|
||||
extern bool init_cycle_counter(bool bIsSysTickOccupied);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief a system timer overflow handler
|
||||
*
|
||||
* \note - if you are using a compiler other than armcc or armclang, e.g. iar,
|
||||
* arm gcc etc, the systick_wrapper_ual.o doesn't work with the linker
|
||||
* of your target toolchain as it use the $Super$$ which is only supported
|
||||
* by armlink. For this condition, you have to manually put this function
|
||||
* into your existing SysTick_Handler to make the perf_counter library
|
||||
* work.
|
||||
*
|
||||
* \note - if you are using Arm Compiler 5 (armcc) or Arm Compiler 6 (armclang)
|
||||
* you do NOT have to insert this function into your SysTick_Handler,
|
||||
* the systick_wrapper_ual.s will do the work for you.
|
||||
*/
|
||||
extern void ticks_port_insert_to_system_timer_insert_ovf_handler(void);
|
||||
|
||||
/*!
|
||||
* \brief update perf_counter as SystemCoreClock has been updated.
|
||||
*/
|
||||
extern void update_perf_counter(void);
|
||||
|
||||
/*!
|
||||
* \brief prepare for reconfiguration of SysTick timer.
|
||||
*
|
||||
* \note some systems (e.g. FreeRTOS) might reconfigure the systick timer to
|
||||
* fulfil the requirement of their feature. To support this, just
|
||||
* before the reconfiguration, please call this function in order
|
||||
* to make the perf_counter works correctly later.
|
||||
*
|
||||
* \note after the reconfiguration, please call update_perf_counter() to apply
|
||||
* the changes to perf_counter.
|
||||
*
|
||||
* \note this function will stop the SysTick, clear the pending bit and set
|
||||
* the Load register and Current Value register to zero.
|
||||
*/
|
||||
extern void before_cycle_counter_reconfiguration(void);
|
||||
|
||||
|
||||
#ifndef __ticks_sync_barrier__
|
||||
# define __ticks_sync_barrier__(...) do {__DSB();__ISB();} while(0)
|
||||
#endif
|
||||
|
||||
typedef uint32_t ticks_global_interrupt_status_t;
|
||||
|
||||
__STATIC_INLINE
|
||||
ticks_global_interrupt_status_t ticks_port_disable_global_interrupt(void);
|
||||
//{
|
||||
// ticks_global_interrupt_status_t tStatus = __get_PRIMASK();
|
||||
// __disable_irq();
|
||||
//
|
||||
// return tStatus;
|
||||
//}
|
||||
|
||||
__STATIC_INLINE
|
||||
void ticks_port_resume_global_interrupt(ticks_global_interrupt_status_t tStatus);
|
||||
//{
|
||||
// __set_PRIMASK(tStatus);
|
||||
//}
|
||||
|
||||
|
||||
//#if defined(__clang__)
|
||||
//# pragma clang diagnostic pop
|
||||
//#elif defined(__IS_COMPILER_GCC__)
|
||||
//# pragma GCC diagnostic pop
|
||||
//#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //HW_LIB_TICKS_H
|
||||
+36
-11
@@ -48,9 +48,9 @@ typedef enum { // 定义枚举类型Type_t,包含不同数据类型
|
||||
default: ((void)0))
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) // 计算数组的元素个数
|
||||
//#define in , // 定义逗号为in
|
||||
|
||||
#define _foreach(e, a) for(size_t e = 0; e < ARRAY_SIZE(a); e++) // 实现foreach宏,遍历数组a,e为当前元素下标
|
||||
#define foreach(exp) _foreach(exp) // 定义foreach宏,用于遍历数组
|
||||
|
||||
|
||||
#define _VA_ARGS_N(_9, _8, _7, _6, _5, _4, _3, _2, _1, _0, N, ...) N
|
||||
#define VA_ARGS_N(...) _VA_ARGS_N(0 __VA_OPT__(,) __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
@@ -60,6 +60,7 @@ typedef enum { // 定义枚举类型Type_t,包含不同数据类型
|
||||
#define _range_n_cat(a, b) a ## b
|
||||
#define _range_n(n) _range_n_cat(_range_, n)
|
||||
#define _range(...) _range_n(VA_ARGS_N(__VA_ARGS__)) // 根据传入参数个数选择对应的范围循环宏
|
||||
|
||||
/**
|
||||
* @Name 范围循环
|
||||
* @brief 根据传入参数个数生成不同范围的遍历
|
||||
@@ -125,7 +126,7 @@ float Str2Float(char *str);
|
||||
* @param fmt: [输入] 格式化字段
|
||||
* @param frame: [输入] 断帧大小
|
||||
* @return void
|
||||
* @example BufPrint("TX", buf, 8, 64, 16); //将长64的8位buf以16个数据断帧打印
|
||||
* @example PRINT_ARRAY(buf, " 0x%02x", 16); //将长64的8位buf以16个数据断帧打印
|
||||
**/
|
||||
#define PRINT_ARRAY(arr, fmt, frame) do { \
|
||||
printf("\n"#arr ":\n"); \
|
||||
@@ -134,14 +135,6 @@ float Str2Float(char *str);
|
||||
printf(fmt " ", arr[i]); }\
|
||||
printf("\n"); } while (0)
|
||||
|
||||
/**
|
||||
* @brief 测试函数执行时间
|
||||
* @param name: [输入] 测试名称
|
||||
* @param pFunction: [输入] 指向待测试函数的指针
|
||||
* @return void
|
||||
* @example Test("FunctionName", functionName);
|
||||
**/
|
||||
void Test_RunTime(char *name, void (*pFunction)());
|
||||
|
||||
#define END "\n"
|
||||
#define TYPE_F(v) _Generic((v), \
|
||||
@@ -151,9 +144,41 @@ int :"[int]-> "#v"=%d" END, \
|
||||
float :"[float]-> "#v"=%.2f" END , \
|
||||
double :"[double]-> "#v"=%.2f" END, \
|
||||
default: "[err]-> "#v"=%p" END)
|
||||
|
||||
#define POUT(s) printf(TYPE_F(s) ,s)
|
||||
|
||||
#ifndef GET_BIT
|
||||
#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit)
|
||||
#endif
|
||||
#ifndef SWAP
|
||||
#ifdef __cplusplus
|
||||
#define SWAP(x, y) do { \
|
||||
decltype(x) temp = x; \
|
||||
x = y; \
|
||||
y = temp; \
|
||||
} while(0)
|
||||
#else
|
||||
#define SWAP(x, y) do { \
|
||||
typeof(x) temp = x; \
|
||||
x = y; \
|
||||
y = temp; \
|
||||
} while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(__a, __b) ((__a) <= (__b) ? (__a) : (__b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(__a, __b) ((__a) >= (__b) ? (__a) : (__b))
|
||||
#endif
|
||||
|
||||
#ifndef __WEAK
|
||||
# define __WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1,631 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __IMPLEMENT_PERF_COUNTER
|
||||
|
||||
#include "ticks.h"
|
||||
|
||||
#if defined(__IS_COMPILER_GCC__)
|
||||
# pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
# pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
# pragma clang diagnostic ignored "-Wconditional-uninitialized"
|
||||
# pragma clang diagnostic ignored "-Wcast-align"
|
||||
# pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
#endif
|
||||
|
||||
|
||||
/*============================ MACROS ========================================*/
|
||||
#ifndef PERF_CNT_COMPENSATION_THRESHOLD
|
||||
# define PERF_CNT_COMPENSATION_THRESHOLD 16
|
||||
#endif
|
||||
|
||||
#ifndef PERF_CNT_DELAY_US_COMPENSATION
|
||||
# define PERF_CNT_DELAY_US_COMPENSATION 90
|
||||
#endif
|
||||
|
||||
#define MAGIC_WORD_AGENT_LIST_VALID 0x8492A53C
|
||||
#define MAGIC_WORD_CANARY 0xDEADBEEF
|
||||
|
||||
/*============================ MACROFIED FUNCTIONS ===========================*/
|
||||
/*============================ TYPES =========================================*/
|
||||
|
||||
struct __task_cycle_info_t {
|
||||
task_cycle_info_t tInfo; //!< cycle information
|
||||
int64_t lLastTimeStamp; //!< previous timestamp
|
||||
task_cycle_info_agent_t tList; //!< the root of the agent list
|
||||
uint32_t wMagicWord; //!< an magic word for validation
|
||||
};
|
||||
|
||||
|
||||
/*============================ GLOBAL VARIABLES ==============================*/
|
||||
/*============================ LOCAL VARIABLES ===============================*/
|
||||
volatile int64_t g_lLastTimeStamp = 0;
|
||||
volatile static int64_t s_lOldTimestamp;
|
||||
volatile int32_t g_nOffset = 0;
|
||||
volatile static uint32_t s_wUSUnit = 1;
|
||||
volatile static uint32_t s_wMSUnit = 1;
|
||||
volatile static uint32_t s_wMSResidule = 0;
|
||||
volatile static uint32_t s_wUSResidule = 0;
|
||||
volatile static int64_t s_lSystemMS = 0;
|
||||
volatile static int64_t s_lSystemUS = 0;
|
||||
|
||||
volatile static int64_t s_lSystemClockCounts = 0;
|
||||
|
||||
/*============================ PROTOTYPES ====================================*/
|
||||
|
||||
/* low level interface for porting */
|
||||
extern
|
||||
uint32_t ticks_port_get_system_timer_freq(void);
|
||||
|
||||
extern
|
||||
int64_t ticks_port_get_system_timer_top(void);
|
||||
|
||||
extern
|
||||
bool ticks_port_is_system_timer_ovf_pending(void);
|
||||
|
||||
extern
|
||||
bool ticks_port_init_system_timer(bool bTimerOccupied);
|
||||
|
||||
extern
|
||||
int64_t ticks_port_get_system_timer_elapsed(void);
|
||||
|
||||
extern
|
||||
void ticks_port_clear_system_timer_ovf_pending(void);
|
||||
|
||||
extern
|
||||
void ticks_port_stop_system_timer_counting(void);
|
||||
|
||||
extern
|
||||
void ticks_port_clear_system_timer_counter(void);
|
||||
|
||||
/*============================ INCLUDES ======================================*/
|
||||
|
||||
void ticks_port_insert_to_system_timer_insert_ovf_handler(void) {
|
||||
int64_t lLoad = ticks_port_get_system_timer_top() + 1;
|
||||
s_lSystemClockCounts += lLoad;
|
||||
|
||||
// update system ms counter
|
||||
do {
|
||||
int64_t lTemp = s_wMSResidule + lLoad;
|
||||
|
||||
int64_t lMS = lTemp / s_wMSUnit;
|
||||
s_lSystemMS += lMS;
|
||||
s_wMSResidule = (uint32_t) ((int64_t) lTemp - (int64_t) lMS * s_wMSUnit);
|
||||
|
||||
} while (0);
|
||||
|
||||
// update system us counter
|
||||
do {
|
||||
int64_t lTemp = s_wUSResidule + lLoad;
|
||||
|
||||
int64_t lUS = lTemp / s_wUSUnit;
|
||||
s_lSystemUS += lUS;
|
||||
|
||||
s_wUSResidule = (uint32_t) ((int64_t) lTemp - (int64_t) lUS * s_wUSUnit);
|
||||
|
||||
} while (0);
|
||||
|
||||
}
|
||||
|
||||
uint32_t ticks_get_systimer_frequency(void) {
|
||||
return ticks_port_get_system_timer_freq();
|
||||
}
|
||||
|
||||
__WEAK
|
||||
void __perf_os_patch_init(void) {
|
||||
}
|
||||
|
||||
|
||||
void update_perf_counter(void) {
|
||||
uint32_t wSystemFrequency = ticks_port_get_system_timer_freq();
|
||||
s_wUSUnit = wSystemFrequency / 1000000ul;
|
||||
s_wMSUnit = wSystemFrequency / 1000ul;
|
||||
|
||||
__IRQ_SAFE {
|
||||
g_lLastTimeStamp = get_system_ticks();
|
||||
__ticks_sync_barrier__();
|
||||
g_nOffset = get_system_ticks() - g_lLastTimeStamp;
|
||||
}
|
||||
}
|
||||
|
||||
bool init_cycle_counter(bool bIsSysTickOccupied) {
|
||||
bool bResult = false;
|
||||
__IRQ_SAFE {
|
||||
bResult = ticks_port_init_system_timer(bIsSysTickOccupied); // use the longest period
|
||||
ticks_port_clear_system_timer_ovf_pending();
|
||||
}
|
||||
|
||||
update_perf_counter();
|
||||
s_lSystemClockCounts = 0; // reset system cycle counter
|
||||
s_lSystemMS = 0; // reset system millisecond counter
|
||||
s_lSystemUS = 0; // reset system microsecond counter
|
||||
s_lOldTimestamp = 0;
|
||||
|
||||
__perf_os_patch_init();
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/*! \note this function should only be called when irq is disabled
|
||||
* hence SysTick-LOAD and (SCB->ICSR & SCB_ICSR_PENDSTSET_Msk)
|
||||
* won't change.
|
||||
*/
|
||||
__STATIC_INLINE int64_t check_systick(void) {
|
||||
int64_t lLoad = ticks_port_get_system_timer_top() + 1;
|
||||
int64_t lTemp = ticks_port_get_system_timer_elapsed();
|
||||
|
||||
/* Since we cannot stop counting temporarily, there are several
|
||||
* conditions which we should take into consideration:
|
||||
* - Condition 1: when assigning nTemp with the register value (LOAD-VAL),
|
||||
* the underflow didn't happen but when we check the PENDSTSET bit,
|
||||
* the underflow happens, for this condition, we should not
|
||||
* do any compensation. When this happens, the (LOAD-nTemp) is
|
||||
* smaller than PERF_CNT_COMPENSATION_THRESHOLD (a small value) as
|
||||
* long as LOAD is bigger than (or equals to) the
|
||||
* PERF_CNT_COMPENSATION_THRESHOLD;
|
||||
* - Condition 2: when assigning nTemp with the register value (LOAD-VAL),
|
||||
* the VAL is zero and underflow happened and the PENDSTSET bit
|
||||
* is set, for this condition, we should not do any compensation.
|
||||
* When this happens, the (LOAD-nTemp) is equals to zero.
|
||||
* - Condition 3: when assigning nTemp with the register value (LOAD-VAL),
|
||||
* the underflow has already happened, hence the PENDSTSET
|
||||
* is set, for this condition, we should compensate the return
|
||||
* value. When this happens, the (LOAD-nTemp) is bigger than (or
|
||||
* equals to) PERF_CNT_COMPENSATION_THRESHOLD.
|
||||
* The following code implements an equivalent logic.
|
||||
*/
|
||||
if (ticks_port_is_system_timer_ovf_pending()) {
|
||||
if ((lLoad - lTemp) >= PERF_CNT_COMPENSATION_THRESHOLD) {
|
||||
lTemp += lLoad;
|
||||
}
|
||||
}
|
||||
|
||||
return lTemp;
|
||||
}
|
||||
|
||||
void before_cycle_counter_reconfiguration(void) {
|
||||
__IRQ_SAFE {
|
||||
ticks_port_stop_system_timer_counting();
|
||||
|
||||
if (ticks_port_is_system_timer_ovf_pending()) {
|
||||
ticks_port_clear_system_timer_ovf_pending(); /* clear pending bit */
|
||||
|
||||
ticks_port_insert_to_system_timer_insert_ovf_handler(); /* manually handle exception */
|
||||
|
||||
}
|
||||
s_lSystemClockCounts = get_system_ticks(); /* get the final cycle counter value */
|
||||
|
||||
ticks_port_clear_system_timer_counter();
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
void __perf_counter_init(void) {
|
||||
init_cycle_counter(true);
|
||||
}
|
||||
|
||||
|
||||
void delay_us(uint32_t wUs) {
|
||||
int64_t lUs = (int64_t) wUs * (int64_t) s_wUSUnit;
|
||||
int32_t iCompensate = g_nOffset > PERF_CNT_DELAY_US_COMPENSATION
|
||||
? g_nOffset
|
||||
: PERF_CNT_DELAY_US_COMPENSATION;
|
||||
|
||||
if (lUs <= iCompensate) {
|
||||
return;
|
||||
}
|
||||
|
||||
lUs -= iCompensate;
|
||||
|
||||
lUs += get_system_ticks();
|
||||
while (get_system_ticks() < lUs);
|
||||
}
|
||||
|
||||
void delay_ms(uint32_t wMs) {
|
||||
int64_t lMs = (int64_t) wMs * (int64_t) s_wMSUnit;
|
||||
int32_t iCompensate = g_nOffset > PERF_CNT_DELAY_US_COMPENSATION
|
||||
? g_nOffset
|
||||
: PERF_CNT_DELAY_US_COMPENSATION;
|
||||
|
||||
if (lMs <= iCompensate) {
|
||||
return;
|
||||
}
|
||||
|
||||
lMs -= iCompensate;
|
||||
|
||||
lMs += get_system_ticks();
|
||||
while (get_system_ticks() < lMs);
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
int64_t get_system_ticks(void) {
|
||||
int64_t lTemp = 0;
|
||||
|
||||
__IRQ_SAFE {
|
||||
lTemp = check_systick() + s_lSystemClockCounts;
|
||||
|
||||
/* When calling get_system_ticks() in an exception handler that has a
|
||||
* higher priority than the SysTick_Handler, in some rare cases, the
|
||||
* lTemp might be temporarily smaller than the previous value (i.e.
|
||||
* s_lOldTimestamp), to mitigate the adverse effects of this problem,
|
||||
* we use the following code to avoid time-rolling-back issue.
|
||||
*
|
||||
* NOTE: the issue mentioned above doesn't accumulate or have long-lasting
|
||||
* effects.
|
||||
*/
|
||||
if (lTemp < s_lOldTimestamp) {
|
||||
lTemp = s_lOldTimestamp;
|
||||
} else {
|
||||
s_lOldTimestamp = lTemp;
|
||||
}
|
||||
}
|
||||
|
||||
return lTemp;
|
||||
}
|
||||
|
||||
/*! \note the prototype of this clock() is different from the one defined in
|
||||
*! time.h. As clock_t is usually defined as unsigned int, it is
|
||||
*! not big enough in Cortex-M system to hold a time-stamp. clock()
|
||||
*! defined here returns the timestamp since the begining of main()
|
||||
*! and its unit is clock cycle (rather than 1ms). Hence, for a system
|
||||
*! running under several hundreds MHz or even 1GHz, e.g. RT10xx from
|
||||
*! NXP, it is very easy to see a counter overflow as clock_t is
|
||||
*! defined as uint32_t in timer.h.
|
||||
*! Since we are not allowed to change the defintion of clock_t in
|
||||
*! official header file, i.e. time.h, I use a compatible prototype
|
||||
*! after I checked the AAPCS spec. So, the return of the clock() is
|
||||
*! int64_t, which will use the R0 to store the lower 32bits and R1
|
||||
*! to store the higher 32bits. When you are using the prototype from
|
||||
*! timer.h, caller will only take the lower 32bits stored in R0 and
|
||||
*! the higher 32bits stored in R1 will be ignored.
|
||||
*!
|
||||
*! If you want to use the non-overflow version of this clock(), please
|
||||
*! 1) define the MACRO: __PERF_CNT_USE_LONG_CLOCK__ in your project
|
||||
*! and 2) do not include system header file <time.h>
|
||||
*!
|
||||
*/
|
||||
#if !defined(__IS_COMPILER_IAR__)
|
||||
|
||||
__attribute__((nothrow))
|
||||
#endif
|
||||
__attribute__((noinline))
|
||||
int64_t clock(void) {
|
||||
return get_system_ticks();
|
||||
}
|
||||
|
||||
int64_t get_system_ms(void) {
|
||||
int64_t lTemp = 0;
|
||||
|
||||
__IRQ_SAFE {
|
||||
lTemp = s_lSystemMS + ((check_systick() + (int64_t) s_wMSResidule) / s_wMSUnit);
|
||||
}
|
||||
|
||||
return lTemp;
|
||||
}
|
||||
|
||||
int64_t get_system_us(void) {
|
||||
int64_t lTemp = 0;
|
||||
|
||||
__IRQ_SAFE {
|
||||
lTemp = s_lSystemUS + ((check_systick() + (int64_t) s_wUSResidule) / s_wUSUnit);
|
||||
}
|
||||
|
||||
return lTemp;
|
||||
}
|
||||
|
||||
int64_t ticks_convert_ticks_to_ms(int64_t lTick) {
|
||||
return lTick / (int64_t) s_wMSUnit;
|
||||
}
|
||||
|
||||
int64_t ticks_convert_ms_to_ticks(uint32_t wMS) {
|
||||
int64_t lResult = (int64_t) s_wMSUnit * (int64_t) wMS;
|
||||
return lResult ? lResult : 1;
|
||||
}
|
||||
|
||||
int64_t ticks_convert_ticks_to_us(int64_t lTick) {
|
||||
return lTick / (int64_t) s_wUSUnit;
|
||||
}
|
||||
|
||||
int64_t ticks_convert_us_to_ticks(uint32_t wMS) {
|
||||
int64_t lResult = (int64_t) s_wUSUnit * (int64_t) wMS;
|
||||
return lResult ? lResult : 1;
|
||||
}
|
||||
|
||||
|
||||
bool __ticks_is_time_out(int64_t lPeriod, int64_t *plTimestamp, bool bAutoReload) {
|
||||
if (NULL == plTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t lTimestamp = get_system_ticks();
|
||||
|
||||
|
||||
if (0 == *plTimestamp) {
|
||||
*plTimestamp = lPeriod;
|
||||
*plTimestamp += lTimestamp;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lTimestamp >= *plTimestamp) {
|
||||
if (bAutoReload) {
|
||||
*plTimestamp = lPeriod + lTimestamp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Setup timer hardware.
|
||||
/// \return status (1=Success, 0=Failure)
|
||||
uint32_t EventRecorderTimerSetup(void) {
|
||||
/* doing nothing at all */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// Get timer frequency.
|
||||
/// \return timer frequency in Hz
|
||||
uint32_t EventRecorderTimerGetFreq(void) {
|
||||
return ticks_port_get_system_timer_freq();
|
||||
}
|
||||
|
||||
/// Get timer count.
|
||||
/// \return timer count (32-bit)
|
||||
uint32_t EventRecorderTimerGetCount(void) {
|
||||
return get_system_ticks();
|
||||
}
|
||||
|
||||
|
||||
__WEAK
|
||||
task_cycle_info_t *get_rtos_task_cycle_info(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_task_cycle_counter(void) {
|
||||
struct __task_cycle_info_t *ptRootAgent =
|
||||
(struct __task_cycle_info_t *) get_rtos_task_cycle_info();
|
||||
if (NULL == ptRootAgent) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(ptRootAgent, 0, sizeof(struct __task_cycle_info_t));
|
||||
|
||||
ptRootAgent->tList.ptInfo = &(ptRootAgent->tInfo);
|
||||
ptRootAgent->tInfo.lStart = get_system_ticks();
|
||||
ptRootAgent->wMagicWord = MAGIC_WORD_CANARY;
|
||||
}
|
||||
|
||||
bool ticks_check_task_stack_canary_safe(void) {
|
||||
struct __task_cycle_info_t *ptRootAgent =
|
||||
(struct __task_cycle_info_t *) get_rtos_task_cycle_info();
|
||||
do {
|
||||
if (NULL == ptRootAgent) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((MAGIC_WORD_CANARY == ptRootAgent->wMagicWord)
|
||||
|| (MAGIC_WORD_AGENT_LIST_VALID == ptRootAgent->wMagicWord)) {
|
||||
return true;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
task_cycle_info_t *init_task_cycle_info(task_cycle_info_t *ptInfo) {
|
||||
do {
|
||||
if (NULL == ptInfo) {
|
||||
break;
|
||||
}
|
||||
|
||||
memset(ptInfo, 0, sizeof(task_cycle_info_t));
|
||||
|
||||
ptInfo->bEnabled = true;
|
||||
} while (0);
|
||||
|
||||
return ptInfo;
|
||||
}
|
||||
|
||||
bool enable_task_cycle_info(task_cycle_info_t *ptInfo) {
|
||||
if (NULL == ptInfo) {
|
||||
return false;
|
||||
}
|
||||
bool bOrig;
|
||||
__IRQ_SAFE {
|
||||
bOrig = ptInfo->bEnabled;
|
||||
ptInfo->bEnabled = true;
|
||||
}
|
||||
return bOrig;
|
||||
}
|
||||
|
||||
bool disable_task_cycle_info(task_cycle_info_t *ptInfo) {
|
||||
if (NULL == ptInfo) {
|
||||
return false;
|
||||
}
|
||||
bool bOrig;
|
||||
__IRQ_SAFE {
|
||||
bOrig = ptInfo->bEnabled;
|
||||
ptInfo->bEnabled = false;
|
||||
}
|
||||
return bOrig;
|
||||
}
|
||||
|
||||
void resume_task_cycle_info(task_cycle_info_t *ptInfo, bool bEnabledStatus) {
|
||||
if (NULL == ptInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
ptInfo->bEnabled = bEnabledStatus;
|
||||
}
|
||||
|
||||
|
||||
task_cycle_info_agent_t *register_task_cycle_agent(task_cycle_info_t *ptInfo,
|
||||
task_cycle_info_agent_t *ptAgent) {
|
||||
__IRQ_SAFE {
|
||||
do {
|
||||
if (NULL == ptAgent || NULL == ptInfo) {
|
||||
break;
|
||||
}
|
||||
|
||||
struct __task_cycle_info_t *ptRootAgent =
|
||||
(struct __task_cycle_info_t *) get_rtos_task_cycle_info();
|
||||
if (NULL == ptRootAgent) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptRootAgent->wMagicWord = MAGIC_WORD_AGENT_LIST_VALID;
|
||||
|
||||
ptAgent->ptInfo = ptInfo;
|
||||
|
||||
// push to the stack
|
||||
do {
|
||||
// set next-list
|
||||
ptAgent->ptNext = ptRootAgent->tList.ptNext;
|
||||
ptRootAgent->tList.ptNext = ptAgent;
|
||||
|
||||
// set prev-list
|
||||
ptAgent->ptPrev = &(ptRootAgent->tList);
|
||||
if (NULL != ptAgent->ptNext) {
|
||||
ptAgent->ptNext->ptPrev = ptAgent;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
} while (0);
|
||||
}
|
||||
|
||||
return ptAgent;
|
||||
}
|
||||
|
||||
task_cycle_info_agent_t *
|
||||
unregister_task_cycle_agent(task_cycle_info_agent_t *ptAgent) {
|
||||
__IRQ_SAFE {
|
||||
do {
|
||||
if (NULL == ptAgent) {
|
||||
break;
|
||||
}
|
||||
|
||||
task_cycle_info_agent_t *ptPrev = ptAgent->ptPrev;
|
||||
if (NULL == ptPrev) {
|
||||
break; /* this should not happen */
|
||||
}
|
||||
if (ptPrev->ptNext != ptAgent) {
|
||||
// already removed
|
||||
break;
|
||||
}
|
||||
|
||||
//! remove agent from the next-list
|
||||
ptPrev->ptNext = ptAgent->ptNext;
|
||||
|
||||
if (NULL != ptAgent->ptNext) {
|
||||
// remove agent from the prev-list
|
||||
ptAgent->ptNext->ptPrev = ptPrev;
|
||||
}
|
||||
|
||||
ptAgent->ptNext = NULL;
|
||||
ptAgent->ptPrev = NULL;
|
||||
|
||||
} while (0);
|
||||
}
|
||||
|
||||
return ptAgent;
|
||||
}
|
||||
|
||||
|
||||
void __on_context_switch_in(uint32_t *pwStack) {
|
||||
struct __task_cycle_info_t *ptRootAgent = (struct __task_cycle_info_t *) pwStack;
|
||||
int64_t lTimeStamp = get_system_ticks();
|
||||
|
||||
ptRootAgent->lLastTimeStamp = lTimeStamp;
|
||||
ptRootAgent->tInfo.hwActiveCount++;
|
||||
|
||||
if (MAGIC_WORD_AGENT_LIST_VALID == ptRootAgent->wMagicWord) {
|
||||
// update all agents
|
||||
task_cycle_info_agent_t *ptAgent = ptRootAgent->tList.ptNext;
|
||||
while (NULL != ptAgent) {
|
||||
if (NULL != ptAgent->ptInfo) {
|
||||
if (ptAgent->ptInfo->bEnabled) {
|
||||
ptAgent->ptInfo->hwActiveCount++;
|
||||
}
|
||||
}
|
||||
ptAgent = ptAgent->ptNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __on_context_switch_out(uint32_t *pwStack) {
|
||||
struct __task_cycle_info_t *ptRootAgent = (struct __task_cycle_info_t *) pwStack;
|
||||
int64_t lCycleUsed = get_system_ticks() - ptRootAgent->lLastTimeStamp - g_nOffset;
|
||||
|
||||
ptRootAgent->tInfo.nUsedRecent = lCycleUsed;
|
||||
ptRootAgent->tInfo.lUsedTotal += lCycleUsed;
|
||||
|
||||
if (MAGIC_WORD_AGENT_LIST_VALID == ptRootAgent->wMagicWord) {
|
||||
// update all agents
|
||||
task_cycle_info_agent_t *ptAgent = ptRootAgent->tList.ptNext;
|
||||
while (NULL != ptAgent) {
|
||||
if (NULL != ptAgent->ptInfo) {
|
||||
if (ptAgent->ptInfo->bEnabled) {
|
||||
ptAgent->ptInfo->nUsedRecent = lCycleUsed;
|
||||
ptAgent->ptInfo->lUsedTotal += lCycleUsed;
|
||||
}
|
||||
}
|
||||
ptAgent = ptAgent->ptNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void __start_task_cycle_counter(task_cycle_info_t *ptInfo) {
|
||||
struct __task_cycle_info_t *ptRootAgent =
|
||||
(struct __task_cycle_info_t *) get_rtos_task_cycle_info();
|
||||
if (NULL == ptRootAgent) {
|
||||
return;
|
||||
}
|
||||
|
||||
__IRQ_SAFE {
|
||||
ptRootAgent->lLastTimeStamp = get_system_ticks();
|
||||
ptRootAgent->tInfo.lUsedTotal = 0;
|
||||
|
||||
if (NULL != ptInfo) {
|
||||
ptInfo->lUsedTotal = 0;
|
||||
ptInfo->bEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
int64_t __stop_task_cycle_counter(task_cycle_info_t *ptInfo) {
|
||||
struct __task_cycle_info_t *ptRootAgent =
|
||||
(struct __task_cycle_info_t *) get_rtos_task_cycle_info();
|
||||
if (NULL == ptRootAgent) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t lCycles = 0;
|
||||
|
||||
__IRQ_SAFE {
|
||||
int64_t lCycleUsed = get_system_ticks() - ptRootAgent->lLastTimeStamp - g_nOffset;
|
||||
ptRootAgent->tInfo.lUsedTotal += lCycleUsed;
|
||||
|
||||
if (NULL != ptInfo) {
|
||||
if (ptInfo->bEnabled) {
|
||||
ptInfo->nUsedRecent = lCycleUsed;
|
||||
ptInfo->lUsedTotal += lCycleUsed;
|
||||
ptInfo->bEnabled = false;
|
||||
}
|
||||
|
||||
lCycles = ptInfo->lUsedTotal;
|
||||
} else {
|
||||
lCycles = ptRootAgent->tInfo.lUsedTotal;
|
||||
}
|
||||
}
|
||||
|
||||
return lCycles;
|
||||
}
|
||||
@@ -74,20 +74,3 @@ float Str2Float(char *str) {
|
||||
decimal /= decimalWeight;
|
||||
return float(sign * (integer + decimal));
|
||||
}
|
||||
|
||||
void Test_RunTime(char *name, void (*pFunction)()) {
|
||||
clock_t start, end;
|
||||
double cpu_time_used;
|
||||
|
||||
printf("\n------< %s TEST >------\n", name);
|
||||
|
||||
start = clock();
|
||||
pFunction();
|
||||
end = clock();
|
||||
|
||||
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
|
||||
|
||||
printf("\n------< %s END >------\n", name);
|
||||
|
||||
printf("\nTime taken by %s: %f seconds\n", name, cpu_time_used);
|
||||
}
|
||||
@@ -8,27 +8,163 @@
|
||||
#include "t_list.h"
|
||||
#include "t_key.h"
|
||||
#include "t_oled.h"
|
||||
#include "t_lvgl.h"
|
||||
#include "t_tft.h"
|
||||
#include "tool.h"
|
||||
#include "sim_test.h"
|
||||
#include "t_lui.h"
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
|
||||
int main() {
|
||||
|
||||
#define POINTS_COUNT 4
|
||||
|
||||
static SDL_Point points[POINTS_COUNT] = {
|
||||
{320, 200},
|
||||
{300, 240},
|
||||
{340, 240},
|
||||
{320, 200}
|
||||
};
|
||||
|
||||
static SDL_Rect bigrect = {0, 0, 540, 380};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
srand((unsigned) time(NULL));
|
||||
|
||||
|
||||
// SDL_Log("Hello, SDL3!");
|
||||
// int count = SDL_GetNumRenderDrivers();
|
||||
// for (int i = 0; i < count; ++i) {
|
||||
// const char* name = SDL_GetRenderDriver(i);
|
||||
// SDL_Log("Render driver[%d]: %s", i, name);
|
||||
// }
|
||||
// if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
// SDL_Log("SDL_Init failed: %s", SDL_GetError());
|
||||
// return -1;
|
||||
// }
|
||||
// SDL_Window* window = SDL_CreateWindow("Hello, SDL3!", 800, 600, SDL_WINDOW_RESIZABLE);
|
||||
// if (!window) {
|
||||
// SDL_Log("Could not create a window: %s", SDL_GetError());
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
//
|
||||
// SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr);
|
||||
// if (!renderer) {
|
||||
// SDL_Log("Create renderer failed: %s", SDL_GetError());
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// SDL_SetRenderDrawColor(renderer, 16, 0, 16, 255);
|
||||
// SDL_RenderClear(renderer);
|
||||
// SDL_Delay(2000);
|
||||
// SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
||||
// for (int i = 0; i < 100; ++i) {
|
||||
// SDL_RenderPoint(renderer,i,i);
|
||||
// }
|
||||
// if(!SDL_RenderPoints(renderer,points,POINTS_COUNT)){
|
||||
// SDL_Log("Draw Renderer failed: %s", SDL_GetError());
|
||||
// return -1;
|
||||
// }
|
||||
// SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
||||
// SDL_FRect rect1 = { 1, 1, 500, 500 };
|
||||
// SDL_RenderFillRect(renderer, &rect1);
|
||||
//
|
||||
// SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
//
|
||||
// SDL_RenderLines(renderer, points, POINTS_COUNT);
|
||||
//
|
||||
// SDL_FRect rect = { 200, 300, 100, 100 };
|
||||
// SDL_RenderRect(renderer, &rect);
|
||||
//
|
||||
// SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255);
|
||||
// SDL_RenderFillRect(renderer, &rect);
|
||||
//
|
||||
// SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
|
||||
// SDL_RenderFillRect(renderer, &bigrect);
|
||||
//
|
||||
//
|
||||
// SDL_RenderPresent(renderer);
|
||||
// SDL_Delay(5000);
|
||||
// SDL_Event event;
|
||||
// bool keep_going = true;
|
||||
//
|
||||
// while (keep_going) {
|
||||
// while (SDL_PollEvent(&event)) {
|
||||
// switch (event.type) {
|
||||
// case SDL_EVENT_QUIT: {
|
||||
// keep_going = false;
|
||||
// break;
|
||||
// }
|
||||
// case SDL_EVENT_KEY_DOWN: {
|
||||
// keep_going = keep_going && (event.key.key != SDLK_ESCAPE);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//// SDL_Log("Event: %d", event.type);
|
||||
// }
|
||||
// SDL_RenderClear(renderer);
|
||||
// SDL_RenderPresent(renderer);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// SDL_DestroyRenderer(renderer);
|
||||
// SDL_DestroyWindow(window);
|
||||
// SDL_Quit();
|
||||
|
||||
|
||||
|
||||
// SIM_SDLInit("TEST1",480,320,2,&sdls[0]);
|
||||
// SIM_SDLInit("TEST2",480,320,1,&sdls[1]);
|
||||
// SIM_SDLInit("TEST3",320,320,1,&sdls[2]);
|
||||
// SIM_Color_t color;
|
||||
// color.full=0xffff0000;
|
||||
// for (int i = 0; i < 3; ++i) {
|
||||
// for (int j = 0; j < 100; ++j) {
|
||||
// SIM_SDL_Color_DrawPiexl(&sdls[i],j,j,color);
|
||||
// }
|
||||
// }
|
||||
// SDL_Event event;
|
||||
// bool keep_going = true;
|
||||
// while (keep_going) {
|
||||
// while (SDL_PollEvent(&event)) {
|
||||
// switch (event.type) {
|
||||
// case SDL_EVENT_QUIT: {
|
||||
// keep_going = false;
|
||||
// break;
|
||||
// }
|
||||
// case SDL_EVENT_KEY_DOWN: {
|
||||
// keep_going = keep_going && (event.key.key != SDLK_ESCAPE);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//// SDL_Log("Event: %d", event.type);
|
||||
// }
|
||||
// }
|
||||
// SIM_SDL_Stop(&sdls[0]);
|
||||
// SIM_SDL_Stop(&sdls[1]);
|
||||
// SIM_SDL_Stop(&sdls[2]);
|
||||
|
||||
// int i = 1;
|
||||
// POUT((++i) + (++i));
|
||||
//
|
||||
// char str[] = "123.456";
|
||||
// float result = Str2Float(str);
|
||||
// printf("Result: %.3f\n", result);
|
||||
// Test_RunTime("SPI", Test_spi);
|
||||
// Test_RunTime("IIC", Test_iic);
|
||||
// Test_RunTime("ArgPase", Test_argpase);
|
||||
// Test_RunTime("List", Test_List);
|
||||
// Test_Run("SPI", Test_spi,NULL);
|
||||
// Test_Run("IIC", Test_iic,NULL);
|
||||
// Test_Run("ArgPase", Test_argpase,NULL);
|
||||
// Test_Run("List", Test_List,NULL);
|
||||
// Test_RunTime("Key", Test_Key);
|
||||
// Test_RunTime("Queue", Test_Queue);
|
||||
// Test_RunTime("Task", Test_task);
|
||||
// Test_RunTime("OLED", Test_OLED);
|
||||
// Test_RunTime("OLED", Test_tft);
|
||||
// Test_RunTime("Hash", Test_Hash);
|
||||
// Test_RunTime("Task", Test_task);
|
||||
// Test_RunTime("OLED", Test_OLED);
|
||||
// Test_RunTime("LVGL", Test_lvgl);
|
||||
// Test_RunTime("TFT", Test_tft);
|
||||
Test_RunTime("LUI", Test_lui);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Created by lydxh on 24-9-21.
|
||||
//
|
||||
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include "sim_test.h"
|
||||
|
||||
void Test_RunTime(char *name, int (*pFunction)(void *)) {
|
||||
clock_t start, end;
|
||||
double cpu_time_used;
|
||||
|
||||
printf("\n------< %s TEST >------\n", name);
|
||||
|
||||
start = clock();
|
||||
pFunction(NULL);
|
||||
end = clock();
|
||||
|
||||
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
|
||||
|
||||
printf("\n------< %s END >------\n", name);
|
||||
|
||||
printf("\nTime taken by %s: %f seconds\n", name, cpu_time_used);
|
||||
}
|
||||
|
||||
SDL_Thread *Test_Run(char *name, int (*pFunction)(void *), void *arg) {
|
||||
printf("\n------< %s TEST >------\n", name);
|
||||
return ThreadCreat(pFunction, name, arg);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Created by lydxh on 24-9-21.
|
||||
//
|
||||
|
||||
#ifndef HW_LIB_SIM_TEST_H
|
||||
#define HW_LIB_SIM_TEST_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "sim_thread.h"
|
||||
/**
|
||||
* @brief 测试函数执行时间
|
||||
* @param name: [输入] 测试名称
|
||||
* @param pFunction: [输入] 指向待测试函数的指针
|
||||
* @return void
|
||||
* @example Test("FunctionName", functionName);
|
||||
**/
|
||||
void Test_RunTime(char *name, int (*pFunction)(void *));
|
||||
|
||||
SDL_Thread *Test_Run(char *name, int (*pFunction)(void *), void *arg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //HW_LIB_SIM_TEST_H
|
||||
+135
-5
@@ -1,14 +1,32 @@
|
||||
#include "sim_display.h"
|
||||
|
||||
|
||||
#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit)
|
||||
|
||||
uint32_t RGB565_to_ARGB8888(uint16_t rgb565, bool isBGR) {
|
||||
uint8_t r5 = (rgb565 >> 11) & 0x1F;
|
||||
uint8_t g6 = (rgb565 >> 5) & 0x3F;
|
||||
uint8_t b5 = rgb565 & 0x1F;
|
||||
|
||||
uint8_t r8 = (r5 * 527 + 23) >> 6;
|
||||
uint8_t g8 = (g6 * 259 + 33) >> 6;
|
||||
uint8_t b8 = (b5 * 527 + 23) >> 6;
|
||||
|
||||
if (isBGR) {
|
||||
return 0xFF000000 | (b8 << 16) | (g8 << 8) | r8;
|
||||
} else {
|
||||
return 0xFF000000 | (r8 << 16) | (g8 << 8) | b8;
|
||||
}
|
||||
}
|
||||
#ifndef USER_SDL3
|
||||
|
||||
#include "graphics.h"
|
||||
#include <conio.h>
|
||||
|
||||
|
||||
static uint32_t pixelColor, backgroundColor;
|
||||
static int scaleFactor, w, h;
|
||||
uint8_t border;
|
||||
|
||||
#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit)
|
||||
|
||||
void SIM_Display_INIT(int width, int height, uint32_t pixcolor, uint32_t backcolor, int scale, uint8_t b)
|
||||
{
|
||||
w = width * scale;
|
||||
@@ -60,6 +78,25 @@ void SIM_OneColor_DrawFromBuffer(uint8_t* buf, uint16_t width, uint16_t height)
|
||||
EndBatchDraw();
|
||||
}
|
||||
|
||||
void SIM_Color_DrawPiexl(uint32_t buf, uint16_t x, uint16_t y) {
|
||||
BeginBatchDraw();
|
||||
// cleardevice();
|
||||
setfillcolor(buf);
|
||||
drawPixel(x, y);
|
||||
EndBatchDraw();
|
||||
}
|
||||
|
||||
void SIM_Color_DrawHLineBuffer(uint32_t *buf, uint16_t x, uint16_t y, uint16_t width) {
|
||||
BeginBatchDraw();
|
||||
// cleardevice();
|
||||
for (int x_ = 0; x_ < width; x_++) {
|
||||
setfillcolor(*buf);
|
||||
drawPixel(x + x_, y);
|
||||
buf++;
|
||||
}
|
||||
EndBatchDraw();
|
||||
}
|
||||
|
||||
void SIM_Color_DrawFromBuffer(uint32_t* buf, uint16_t width, uint16_t height)
|
||||
{
|
||||
BeginBatchDraw();
|
||||
@@ -79,7 +116,7 @@ void SIM_Color_DrawFromBuffer(uint32_t* buf, uint16_t width, uint16_t height)
|
||||
void SIM_Color_ImgFromBuffer(uint32_t* buf, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
|
||||
{
|
||||
BeginBatchDraw();
|
||||
cleardevice();
|
||||
// cleardevice();
|
||||
for (int y_i = 0; y_i < height; y_i++)
|
||||
{
|
||||
for (int x_i = 0; x_i < width; x_i++)
|
||||
@@ -95,7 +132,7 @@ void SIM_Color_ImgFromBuffer(uint32_t* buf, uint16_t x, uint16_t y, uint16_t wid
|
||||
void SIM_Color_FillFromBuffer(uint32_t* buf, uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye)
|
||||
{
|
||||
BeginBatchDraw();
|
||||
cleardevice();
|
||||
// cleardevice();
|
||||
for (int y_i = ys; y_i < ye; y_i++)
|
||||
{
|
||||
for (int x_i = xs; x_i < xe; x_i++)
|
||||
@@ -107,3 +144,96 @@ void SIM_Color_FillFromBuffer(uint32_t* buf, uint16_t xs, uint16_t ys, uint16_t
|
||||
}
|
||||
EndBatchDraw();
|
||||
}
|
||||
#else
|
||||
|
||||
bool SIM_Display_Init(char *name, int width, int height, uint32_t pixcolor, uint32_t backcolor, int scale,
|
||||
SIM_Display_t *display) {
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
SDL_Log("SDL_Init failed: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
display->scale = scale;
|
||||
display->pixelcolor.full = pixcolor;
|
||||
display->backcolor.full = backcolor;
|
||||
display->window = SDL_CreateWindow(name, width * scale, height * scale, SDL_WINDOW_RESIZABLE);
|
||||
if (!display->window) {
|
||||
SDL_Log("Could not create a window: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
SDL_SetWindowPosition(display->window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
display->renderer = SDL_CreateRenderer(display->window, nullptr);
|
||||
if (!display->renderer) {
|
||||
SDL_Log("Create renderer failed: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
SDL_SetRenderDrawColor(display->renderer, 0, 0, 0, 0);
|
||||
SDL_RenderClear(display->renderer);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SIM_Color_DrawPiexl(SIM_Display_t *display, SIM_Color_t color, uint16_t x, uint16_t y) {
|
||||
SDL_SetRenderDrawColor(display->renderer, color.ch.red, color.ch.green, color.ch.blue, color.ch.alpha);
|
||||
SDL_FRect rect1 = {(x * display->scale) * 1.0f, (y * display->scale) * 1.0f, display->scale * 1.0f,
|
||||
display->scale * 1.0f};
|
||||
SDL_RenderFillRect(display->renderer, &rect1);
|
||||
// for (int y_ = y * display->scale; y_ < (y * display->scale) + display->scale; ++y_) {
|
||||
// for (int x_ = x * display->scale; x_ < (x * display->scale) + display->scale; ++x_) {
|
||||
// SDL_RenderPoint(display->renderer, x_, y_);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void SIM_OneColor_DrawFromBuffer(SIM_Display_t *display, uint8_t *buf, uint16_t width, uint16_t height) {
|
||||
SIM_Color_t color;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
uint8_t byteData = buf[y * width + x];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t bit = GET_BIT(byteData, i);
|
||||
if (bit)color = display->pixelcolor;
|
||||
else color = display->backcolor;
|
||||
SIM_Color_DrawPiexl(display, color, x, y * 8 + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_RenderPresent(display->renderer);
|
||||
}
|
||||
|
||||
|
||||
void SIM_Color_ImgFromBuffer(SIM_Display_t *display, uint32_t *buf, uint16_t x, uint16_t y, uint16_t width,
|
||||
uint16_t height) {
|
||||
SIM_Color_t color;
|
||||
for (int y_i = 0; y_i < height; y_i++) {
|
||||
for (int x_i = 0; x_i < width; x_i++) {
|
||||
color.full = *buf;
|
||||
SIM_Color_DrawPiexl(display, color, x + x_i, y + y_i);
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
SDL_RenderPresent(display->renderer);
|
||||
}
|
||||
|
||||
void
|
||||
SIM_Color_FillFromBuffer(SIM_Display_t *display, uint32_t *buf, uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye) {
|
||||
SIM_Color_t color;
|
||||
for (int y_i = ys; y_i <= ye; y_i++) {
|
||||
for (int x_i = xs; x_i <= xe; x_i++) {
|
||||
color.full = *buf;
|
||||
SIM_Color_DrawPiexl(display, color, x_i, y_i);
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
SDL_RenderPresent(display->renderer);
|
||||
}
|
||||
|
||||
void SIM_Display_Refresh(SIM_Display_t *display) {
|
||||
SDL_RenderPresent(display->renderer);
|
||||
}
|
||||
|
||||
void SIM_Display_STOP(SIM_Display_t *display) {
|
||||
SDL_DestroyRenderer(display->renderer);
|
||||
SDL_DestroyWindow(display->window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+117
-1
@@ -9,6 +9,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
//是否启用SDL3画图
|
||||
#define USER_SDL3
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 定义颜色常量值,用于模拟显示
|
||||
@@ -30,7 +34,7 @@ extern "C" {
|
||||
#define YELLOW 0x55FFFF // 黄色
|
||||
#define WHITE 0xFFFFFF // 白色
|
||||
|
||||
|
||||
#ifndef USER_SDL3
|
||||
/**
|
||||
* @brief 初始化模拟 显示
|
||||
* @param width: [输入] 显示宽度
|
||||
@@ -68,6 +72,16 @@ void SIM_Display_STOP();
|
||||
**/
|
||||
void SIM_OneColor_DrawFromBuffer(uint8_t *buf, uint16_t width, uint16_t height);
|
||||
|
||||
/**
|
||||
* @brief 在指定的坐标位置绘制一个像素点
|
||||
* @param color 颜色
|
||||
* @param x x坐标
|
||||
* @param y y坐标
|
||||
*/
|
||||
void SIM_Color_DrawPiexl(uint32_t color, uint16_t x, uint16_t y);
|
||||
|
||||
void SIM_Color_DrawHLineBuffer(uint32_t *buf, uint16_t x, uint16_t y, uint16_t width);
|
||||
|
||||
/**
|
||||
* @brief 从缓冲区绘制到显示
|
||||
* @param buf: [输入] 缓冲区指针
|
||||
@@ -101,6 +115,108 @@ void SIM_Color_ImgFromBuffer(uint32_t* buf, uint16_t x, uint16_t y, uint16_t wid
|
||||
* @example SIM_Color_FillFromBuffer(buf, 50, 30, 150, 100);
|
||||
**/
|
||||
void SIM_Color_FillFromBuffer(uint32_t* buf, uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye);
|
||||
#else
|
||||
#include "SDL3/SDL.h"
|
||||
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t blue;
|
||||
uint8_t green;
|
||||
uint8_t red;
|
||||
uint8_t alpha;
|
||||
} ch;
|
||||
uint32_t full;
|
||||
} SIM_Color_t;
|
||||
|
||||
typedef struct {
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Event *event;
|
||||
int scale;
|
||||
SIM_Color_t pixelcolor;
|
||||
SIM_Color_t backcolor;
|
||||
} SIM_Display_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化模拟 显示
|
||||
* @param name: [输入] 窗口名称
|
||||
* @param width: [输入] 显示宽度
|
||||
* @param height: [输入] 显示高度
|
||||
* @param pixcolor: [输入] 像素颜色
|
||||
* @param backcolor: [输入] 背景颜色
|
||||
* @param scale: [输入] 显示缩放比例
|
||||
* @param display: [输入] 输入窗口实例
|
||||
* @return bool: true[成功] false[失败]
|
||||
* @example SIM_Display_Init(128, 64, 0xFFFF00, 0x000000, 10, 1);
|
||||
**/
|
||||
bool SIM_Display_Init(char *name, int width, int height, uint32_t pixcolor, uint32_t backcolor, int scale,
|
||||
SIM_Display_t *display);
|
||||
|
||||
/**
|
||||
* @brief 在指定的坐标位置绘制一个像素点
|
||||
* @param display: [输入] 输入窗口实例
|
||||
* @param color 颜色
|
||||
* @param x x坐标
|
||||
* @param y y坐标
|
||||
*/
|
||||
void SIM_Color_DrawPiexl(SIM_Display_t *display, SIM_Color_t color, uint16_t x, uint16_t y);
|
||||
|
||||
/**
|
||||
* @brief 从颜色缓冲区绘制单色图像到模拟显示器
|
||||
* @param display 模拟显示器指针
|
||||
* @param buf 颜色缓冲区指针
|
||||
* @param width 绘制区域宽度
|
||||
* @param height 绘制区域高度
|
||||
*/
|
||||
void SIM_OneColor_DrawFromBuffer(SIM_Display_t *display, uint8_t *buf, uint16_t width, uint16_t height);
|
||||
|
||||
/**
|
||||
* @brief 从缓冲区中填充图像
|
||||
* @param display: [输入] 输入窗口实例
|
||||
* @param buf: [输入] 缓冲区指针
|
||||
* @param x: [输入] 图像起始横坐标
|
||||
* @param y: [输入] 图像起始纵坐标
|
||||
* @param width: [输入] 图像宽度
|
||||
* @param height: [输入] 图像高度
|
||||
* @return void
|
||||
* @example SIM_Color_ImgFromBuffer(buf, 100, 50, 320, 240);
|
||||
**/
|
||||
void SIM_Color_ImgFromBuffer(SIM_Display_t *display, uint32_t *buf, uint16_t x, uint16_t y,
|
||||
uint16_t width, uint16_t height);
|
||||
|
||||
/**
|
||||
* @brief 从缓冲区中填充颜色
|
||||
* @param display: [输入] 输入窗口实例
|
||||
* @param buf: [输入] 缓冲区指针
|
||||
* @param xs: [输入] 填充区域起始横坐标
|
||||
* @param ys: [输入] 填充区域起始纵坐标
|
||||
* @param xe: [输入] 填充区域结束横坐标
|
||||
* @param ye: [输入] 填充区域结束纵坐标
|
||||
* @return void
|
||||
* @example SIM_Color_FillFromBuffer(buf, 50, 30, 150, 100);
|
||||
**/
|
||||
void
|
||||
SIM_Color_FillFromBuffer(SIM_Display_t *display, uint32_t *buf, uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye);
|
||||
|
||||
/**
|
||||
* @brief 刷新模拟显示器
|
||||
*
|
||||
* @param display 模拟显示器指针
|
||||
*/
|
||||
void SIM_Display_Refresh(SIM_Display_t *display);
|
||||
|
||||
/**
|
||||
* @brief 停止模拟 显示
|
||||
* @return void
|
||||
* @example SIM_OLED_STOP();
|
||||
**/
|
||||
void SIM_Display_STOP(SIM_Display_t *display);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t RGB565_to_ARGB8888(uint16_t rgb565, bool isBGR);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+142
-1
@@ -1,6 +1,7 @@
|
||||
#include "sim_key.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef USER_SDL3
|
||||
#include<easyx.h>
|
||||
#include<conio.h>
|
||||
|
||||
@@ -80,4 +81,144 @@ uint8_t SIM_Key_SET(uint8_t) {
|
||||
|
||||
uint8_t SIM_Key_RESET(uint8_t) {
|
||||
return GetAsyncKeyState(VK_END);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#include "SDL3/SDL.h"
|
||||
|
||||
uint8_t SIM_Key_Scan() {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_Q)key = SIM_KEY_SET;
|
||||
if (event.key.key == SDLK_UP || event.key.key == SDLK_W)key = SIM_KEY_UP;
|
||||
if (event.key.key == SDLK_DOWN || event.key.key == SDLK_S)key = SIM_KEY_DOWN;
|
||||
if (event.key.key == SDLK_LEFT || event.key.key == SDLK_A)key = SIM_KEY_LEFT;
|
||||
if (event.key.key == SDLK_RIGHT || event.key.key == SDLK_D)key = SIM_KEY_RIGHT;
|
||||
if (event.key.key == SDLK_R)key = SIM_KEY_RESET;
|
||||
if (event.key.key == SDLK_KP_ENTER || event.key.key == SDLK_E)key = SIM_KEY_ENABLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
uint8_t SIM_Key_UP(uint8_t) {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_UP || event.key.key == SDLK_W)key = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t SIM_Key_DOWN(uint8_t l) {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_DOWN || event.key.key == SDLK_S)key = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t SIM_Key_LEFT(uint8_t) {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_LEFT || event.key.key == SDLK_A)key = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t SIM_Key_RIGHT(uint8_t) {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_RIGHT || event.key.key == SDLK_D)key = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t SIM_Key_ENABLE(uint8_t) {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_KP_ENTER || event.key.key == SDLK_E)key = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t SIM_Key_SET(uint8_t) {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_Q)key = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t SIM_Key_RESET(uint8_t) {
|
||||
SDL_Event event;
|
||||
uint8_t key = 0;
|
||||
SDL_PollEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
return 0;
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
if (event.key.key == SDLK_R)key = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,9 @@ extern "C" {
|
||||
#endif
|
||||
#include "stdint.h"
|
||||
|
||||
//是否启用SDL3获取按键事件
|
||||
#define USER_SDL3
|
||||
|
||||
typedef enum Key_map {
|
||||
SIM_KEY_UP = 1,
|
||||
SIM_KEY_DOWN,
|
||||
|
||||
+2
-2
@@ -230,7 +230,7 @@
|
||||
*-----------*/
|
||||
|
||||
/*Enable the log module*/
|
||||
#define LV_USE_LOG 1
|
||||
#define LV_USE_LOG 0
|
||||
#if LV_USE_LOG
|
||||
|
||||
/*How important log should be added:
|
||||
@@ -736,7 +736,7 @@
|
||||
====================*/
|
||||
|
||||
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
|
||||
#define LV_USE_DEMO_WIDGETS 0
|
||||
#define LV_USE_DEMO_WIDGETS 1
|
||||
#if LV_USE_DEMO_WIDGETS
|
||||
#define LV_DEMO_WIDGETS_SLIDESHOW 0
|
||||
#endif
|
||||
|
||||
+20
-21
@@ -44,7 +44,7 @@ static void disp_flush(lv_disp_drv_t* disp_drv, const lv_area_t* area, lv_color_
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
SIM_Display_t lvgl_display;
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
@@ -91,17 +91,17 @@ void lv_port_disp_init(void)
|
||||
// lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
|
||||
|
||||
// /* Example for 2) */
|
||||
// static lv_disp_draw_buf_t draw_buf_dsc_2;
|
||||
// static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
|
||||
// static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10]; /*An other buffer for 10 rows*/
|
||||
// lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
|
||||
static lv_disp_draw_buf_t draw_buf_dsc_2;
|
||||
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
|
||||
static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10]; /*An other buffer for 10 rows*/
|
||||
lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
|
||||
|
||||
/* Example for 3) also set disp_drv.full_refresh = 1 below*/
|
||||
static lv_disp_draw_buf_t draw_buf_dsc_3;
|
||||
static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*A screen sized buffer*/
|
||||
static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*Another screen sized buffer*/
|
||||
lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
|
||||
MY_DISP_VER_RES * MY_DISP_HOR_RES); /*Initialize the display buffer*/
|
||||
// static lv_disp_draw_buf_t draw_buf_dsc_3;
|
||||
// static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*A screen sized buffer*/
|
||||
// static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*Another screen sized buffer*/
|
||||
// lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
|
||||
// MY_DISP_VER_RES * MY_DISP_HOR_RES); /*Initialize the display buffer*/
|
||||
|
||||
/*-----------------------------------
|
||||
* Register the display in LVGL
|
||||
@@ -120,7 +120,7 @@ void lv_port_disp_init(void)
|
||||
disp_drv.flush_cb = disp_flush;
|
||||
|
||||
/*Set a display buffer*/
|
||||
disp_drv.draw_buf = &draw_buf_dsc_3;
|
||||
disp_drv.draw_buf = &draw_buf_dsc_2;
|
||||
|
||||
/*Required for Example 3)*/
|
||||
//disp_drv.full_refresh = 1;
|
||||
@@ -142,8 +142,7 @@ void lv_port_disp_init(void)
|
||||
static void disp_init(void)
|
||||
{
|
||||
/*You code here*/
|
||||
SIM_Display_INIT(MY_DISP_HOR_RES,MY_DISP_VER_RES, 0xffffff, BLACK, 1, false);
|
||||
SIM_Display_START();
|
||||
SIM_Display_Init("LVGL", MY_DISP_HOR_RES, MY_DISP_VER_RES, 0xffffff, BLACK, 2, &lvgl_display);
|
||||
}
|
||||
|
||||
volatile bool disp_flush_enabled = true;
|
||||
@@ -166,7 +165,7 @@ void colortorgb24(lv_color_t* color_p, uint32_t* color, size_t len)
|
||||
{
|
||||
while (len)
|
||||
{
|
||||
*color = (uint32_t)RGB(color_p->ch.red, color_p->ch.green, color_p->ch.blue) | (color_p->ch.alpha << 24);
|
||||
*color = RGB565_to_ARGB8888(color_p->full, false);
|
||||
color_p++;
|
||||
color++;
|
||||
len--;
|
||||
@@ -181,13 +180,13 @@ static void disp_flush(lv_disp_drv_t* disp_drv, const lv_area_t* area, lv_color_
|
||||
if (disp_flush_enabled)
|
||||
{
|
||||
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
|
||||
uint32_t* color;
|
||||
size_t l = (area->x2 - area->x1) * (area->y2 - area->y1);
|
||||
color = (uint32_t*)malloc(sizeof(uint32_t) * l);
|
||||
|
||||
colortorgb24(color_p, color, l);
|
||||
SIM_Color_FillFromBuffer(color, area->x1, area->y1, area->x2, area->y2);
|
||||
free(color);
|
||||
// uint32_t* color;
|
||||
size_t l = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1);
|
||||
// color = (uint32_t*)malloc(sizeof(uint32_t) * l);
|
||||
//
|
||||
// colortorgb24(color_p, color, l);
|
||||
SIM_Color_FillFromBuffer(&lvgl_display, (uint32_t *) color_p, area->x1, area->y1, area->x2, area->y2);
|
||||
// free(color);
|
||||
}
|
||||
|
||||
/*IMPORTANT!!!
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
*********************/
|
||||
#include "lv_port_indev.h"
|
||||
#include "lvgl.h"
|
||||
#include "graphics.h"
|
||||
#include <easyx.h>
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
@@ -253,8 +251,8 @@ static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
|
||||
static bool mouse_is_pressed(void)
|
||||
{
|
||||
/*Your code comes here*/
|
||||
ExMessage msg;peekmessage(&msg, EM_MOUSE);
|
||||
if(msg.message==WM_LBUTTONDOWN) return true;
|
||||
// ExMessage msg;peekmessage(&msg, EM_MOUSE);
|
||||
// if(msg.message==WM_LBUTTONDOWN) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -262,13 +260,13 @@ static bool mouse_is_pressed(void)
|
||||
static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y)
|
||||
{
|
||||
/*Your code comes here*/
|
||||
ExMessage msg;
|
||||
if(peekmessage(&msg, EM_MOUSE))
|
||||
{
|
||||
(*x) = msg.x;
|
||||
(*y) = msg.y;
|
||||
printf("\nX:%d,Y:%d",*x,*y);
|
||||
}
|
||||
// ExMessage msg;
|
||||
// if(peekmessage(&msg, EM_MOUSE))
|
||||
// {
|
||||
// (*x) = msg.x;
|
||||
// (*y) = msg.y;
|
||||
// printf("\nX:%d,Y:%d",*x,*y);
|
||||
// }
|
||||
}
|
||||
|
||||
/*------------------
|
||||
|
||||
+4
-11
@@ -1,22 +1,15 @@
|
||||
#include "sim_oled.h"
|
||||
#include "graphics.h"
|
||||
#include <conio.h>
|
||||
|
||||
static SIM_Display_t oled_display;
|
||||
void SIM_OLED_INIT(int width, int height, uint32_t pixcolor, uint32_t backcolor, int scale, uint8_t b) {
|
||||
SIM_Display_INIT(width,height,pixcolor,backcolor,scale,b);
|
||||
SIM_Display_Init("OLED", width, height, pixcolor, backcolor, scale, &oled_display);
|
||||
}
|
||||
|
||||
void SIM_OLED_START() {
|
||||
SIM_Display_START();
|
||||
}
|
||||
|
||||
void SIM_OLED_STOP() {
|
||||
SIM_Display_STOP();
|
||||
SIM_Display_STOP(&oled_display);
|
||||
}
|
||||
|
||||
void SIM_OLED_DrawFromBuffer(uint8_t *buf, uint8_t width, uint8_t height) {
|
||||
SIM_OneColor_DrawFromBuffer(buf,width,height);
|
||||
SIM_OneColor_DrawFromBuffer(&oled_display, buf, width, height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,13 +19,6 @@ extern "C" {
|
||||
**/
|
||||
void SIM_OLED_INIT(int width, int height, uint32_t pixcolor, uint32_t backcolor, int scale, uint8_t border);
|
||||
|
||||
/**
|
||||
* @brief 开始模拟 OLED 显示
|
||||
* @return void
|
||||
* @example SIM_OLED_START();
|
||||
**/
|
||||
void SIM_OLED_START();
|
||||
|
||||
/**
|
||||
* @brief 停止模拟 OLED 显示
|
||||
* @return void
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*Thread_Func_t)(void *pArg);
|
||||
#include "SDL3/SDL.h"
|
||||
|
||||
void ThreadCreat(Thread_Func_t func, unsigned int stackSize, void *pArg);
|
||||
void ThreadStop();
|
||||
typedef int (*Thread_Func_t)(void *pArg);
|
||||
|
||||
SDL_Thread *ThreadCreat(Thread_Func_t func, char *name, void *pArg);
|
||||
|
||||
void ThreadStop(SDL_Thread *t);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+11
-5
@@ -1,11 +1,17 @@
|
||||
#include "sim_thread.h"
|
||||
#include <windows.h>
|
||||
|
||||
#include <process.h>
|
||||
|
||||
void ThreadCreat(Thread_Func_t func, unsigned int stackSize, void *pArg) {
|
||||
_beginthread(func, stackSize, pArg);
|
||||
SDL_Thread *ThreadCreat(Thread_Func_t func, char *name, void *pArg) {
|
||||
SDL_Thread *t = SDL_CreateThread(func, name, NULL);
|
||||
if (!t) {
|
||||
SDL_Log("CreateThread: %s", SDL_GetError);
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void ThreadStop() {
|
||||
_endthread();
|
||||
void ThreadStop(SDL_Thread *t) {
|
||||
SDL_WaitThread(t, NULL);
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user