Compare commits

..

72 Commits

Author SHA1 Message Date
Ze-Hou
d3e26999ce bsp: k230: add dma support to the i2c driver
1. add dma support to the I2C driver to improve efficiency.

Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-11-25 22:12:24 +08:00
dongly
583d7f47c7 [soft_rtc]修正GET_TIMESPEC/GET_TIMEVAL 获取 ns/us 的错误; 优化soft_rtc实现 2025-11-25 09:44:07 +08:00
guozhanxin
6695599afc [tool] fixed scons --target=xmake 2025-11-23 22:31:56 +08:00
Chuan
af6e310b61 docs(utest):Add standardized documentation for Mailbox Test
Signed-off-by: ChuanN-sudo <fjchuanil@gmail.com>
2025-11-23 15:14:14 +08:00
wdfk-prog
0a02fd4545 docs:[STM32][drv_gpio] Add detailed Doxygen comments for GET_PIN macro 2025-11-22 10:11:38 +08:00
wdfk-prog
836eecc2f9 fix:[STM32][drv_can] Suppress unused variable warning in send error path 2025-11-22 10:11:38 +08:00
4444x
4e7a78ee0b [docs]:Add standardized function comment blocks for mutex_tc 2025-11-22 10:10:32 +08:00
liuyucai
29fb860ad4 finsh: replace str/mem functions with rt-prefixed versions
Replace standard string and memory functions with RT-Thread's rt-prefixed
equivalents where available:

- strcpy -> rt_strcpy
- strncpy -> rt_strncpy
- strcmp -> rt_strcmp
- strncmp -> rt_strncmp
- strlen -> rt_strlen
- strstr -> rt_strstr
- memcpy -> rt_memcpy
- memcmp -> rt_memcmp

Functions like strcat, strchr remain unchanged as RT-Thread does not provide
rt-prefixed versions.
2025-11-22 09:31:37 +08:00
蒙蒙plus
6ab057be41 🐞 fix(at_socket):修复socket 在开启server下的connect连接
修复accept在错误执行过程中返回无效socket问题
2025-11-21 17:23:54 +08:00
R b b666
25e98bd3f2 [utest]Refactor object_tc.c, add stress and error-path coverage (#10961) 2025-11-21 11:01:36 +08:00
Tm-C-mT
573c5489fa [docs][utest]:Add explanatory comments for the utest of thread allocation for idle harts
Add explanatory comments for the utest of smp_assigned_idle_cores.

Signed-off-by: Mengchen Teng <teng_mengchen@163.com>
2025-11-19 16:15:47 +08:00
Tm-C-mT
9308564a92 [utest]: Modify the utest logic for thread allocation of idle harts
Currently, this utest cannot determine whether threads are evenly distributed
across idle harts by observing the result of list_thread(). This is because
the presence of rt_thread_delay(5); causes all other threads to be in the
suspended state when thread information is printed. For example, if RT_CPUS_NR=4,
T0 executes list_thread() to print information, while T1~T3 are in hibernation
and thus it is impossible to observe which hart they are running on.

Solution:Here, the completion judgment condition has been modified. For example,
when RT_CPUS_NR=4, only RT_CPUS_NR-1 threads will be created (i.e., T0 to T2),
because running the utest occupies one hart. The execution is judged as completed
when finish_flag=0x0007, and the thread running the utest will call list_thread()
to print the information. Observe whether T0 to T2 are running on different
harts simultaneously.

Signed-off-by: Mengchen Teng <teng_mengchen@163.com>
2025-11-19 16:15:47 +08:00
Copilot
45f2246f73 [Kernel][Object] Remove object name assertions, use rt_strncpy for safe truncation #10943 2025-11-19 14:10:43 +08:00
Ze-Hou
75f1d8d0dc feature: utest: add standardized utest documentation to messagequeue_tc
Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-11-19 10:49:17 +08:00
Ze-Hou
c745319c56 feature: utest: add standardized utest documentation to timer_tc
Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-11-19 10:23:34 +08:00
R b b666
59e55f543c [utest]Fixed assertion failure in the smp_affinity_pri2_tc use case caused by improper priority configuration. (#10956) 2025-11-18 18:02:03 +08:00
Rbb666
e484f56b6c [utest]Fixed assertion failure in the smp_affinity_pri1_tc use case caused by improper priority configuration. 2025-11-18 17:22:43 +08:00
David Frisbee
6073c22164 [docs]utest]:Add standardized utest documentation to atomic_tc and mtsafe_kprint_tc #10945 2025-11-18 17:22:03 +08:00
Rbb666
0af3b3eec1 [utest]Fixed compilation warning issues in smp/smp_affinity_prix_tc. 2025-11-18 16:57:43 +08:00
CYFS
514bc130eb [copilot]:Improve the copilot guide 2025-11-18 11:34:06 +08:00
wdfk-prog
e1f609fe3a feat(ulog): Add a one-time warning when the log line buffer is insufficient 2025-11-18 09:55:37 +08:00
Ze-Hou
de784f7cf2 feature: utest: add standardized utest documentation to event_tc
Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-11-18 09:47:46 +08:00
David Frisbee
4103870b74 [fix][utest] correct spelling of 'pref_test' to 'perf_test' (#10937)
* [fix][utest] correct spelling of ''pref_test' to 'perf_test'
2025-11-17 16:40:00 +08:00
Copilot
30e1e5e9dc Reorganize Group names in build system for clarity and IDE integration #10923 2025-11-16 11:40:53 +08:00
Chuan
ae2a5758bc bsp: k230: add spi driver
Requirement: The BSP for the k230 platform in the RT-Thread repository does not yet have an spi driver.

Solution: Provide spi driver for the k230 platform in the RT-Thread repository.

- Supports SPI0(OSPI) controller with 1/2/4/8 data lines.
- Supports SPI1(QSPI0) and SPI2(QSPI1) controllers with 1/2/4 data lines.
- Implements DMA-based transfers for OSPI, QSPI, and DSPI modes.
- Falls back to standard IRQ-driven transfers for legacy SPI mode (single line).
- Updates documentation in bsp/README.md

Signed-off-by: ChuanN-sudo <fjchuanil@gmail.com>
2025-11-16 11:37:32 +08:00
Chuan
ee20484759 docs(utest):Add standardized documentation for Drivers Core Test
Signed-off-by: ChuanN-sudo <fjchuanil@gmail.com>
2025-11-16 10:28:46 +08:00
ibvqeibob
4e41e700f0 doxygen: add comments for lwp shared memory APIs
Add Doxygen-style comments for the lwp shared memory public APIs
in components/lwp/lwp_shm.c and the related control structure.
This change is documentation-only and does not modify any runtime
behavior or logic.

Signed-off-by: ibvqeibob <2601187225@qq.com>
2025-11-15 14:20:36 +08:00
CYFS
327006cb88 [docs][utest]:Add standardized utest documentation block for serialv2_tc 2025-11-15 14:18:44 +08:00
CYFS
92377190ba [docs][utest]:Add standardized utest documentation block for slab_tc 2025-11-14 23:32:08 +08:00
CYFS
b53293863d [docs][utest]:Add standardized utest documentation block for object_tc 2025-11-14 12:44:52 +08:00
CYFS
6a5489f947 [docs][utest]:Add standardized utest documentation block for mem_tc 2025-11-14 12:43:09 +08:00
CYFS
832fe803df [docs][utest]:Add standardized utest documentation block for memheap_tc 2025-11-14 12:43:09 +08:00
MuChenger
8286196d9f [bsp/xuantie][fix] 修正Bsp Kconfig配置 2025-11-13 18:44:24 +08:00
Ze-Hou
ec5e72c59a feature: utest: add standardized utest documentation to thread_tc
Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-11-13 18:42:13 +08:00
Ze-Hou
538e5ff6d5 feature: utest: add standardized utest documentation to hooklist_tc
Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-11-13 16:23:15 +08:00
wdfk-prog
ddfe2cd61c feat[spi]: enable interrupt-safe operations using spinlocks 2025-11-13 15:41:41 +08:00
wdfk-prog
ec27e09df8 feat:[stm32][can]: enhance control logic and refactor sendmsg 2025-11-13 15:31:05 +08:00
wdfk-prog
f56875fff5 fix[components]: 修复日志输出的gcc编译警告 2025-11-13 15:16:49 +08:00
rcitach
9150317539 Fixed PWM assertion error caused by using DM 2025-11-13 11:11:59 +08:00
westcity-YOLO
32d2cf17c7 clang format ignore migration 2025-11-13 10:33:25 +08:00
R b b666
0d78fa460e [BSP][Documentation] Add comprehensive BSP driver support summary table (#10925)
* List of RT-Thread BSP Support Additions.
2025-11-13 09:55:13 +08:00
Yonggang Luo
a81023b88d [components/ktime]: Remove unused rt_ktime_cputimer_getstep
Can use rt_ktime_cputimer_getfrq() / RT_TICK_PER_SECOND instead.
2025-11-12 12:59:29 +08:00
Copilot
e525c38cb8 [libcpu][cortex-a] Refactor FPU stack initialization for maintainability (#10919)
* Initial plan

* [libcpu][cortex-a] Improve FPU stack initialization implementation

Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>

* [libcpu][cortex-a] Replace FPU init loop with rt_memset

Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
2025-11-12 04:34:34 +08:00
Teng mengchen
284081fe4c [utest]: [signal]: Add Standardized function comment blocks. (#10914)
* [utest]: [signal]:Standardized function comment blocks have been added.

Added comments to the utest for the signal module, including: test purpose,
usage scenarios, dependency configurations, expected outcomes, and expected
behaviors.

Signed-off-by: Mengchen Teng <teng_mengchen@163.com>

* [utest]: [signal]:Correct issues including grammatical errors, spelling mistakes, and ambiguities in function names.

Fixed the issue of grammatical errors in words; changed the variable 'recive_sig' to 'receive_sig'.
Originally, rt_signal_unmask_test was testing the masking function of rt_signal_mask, while
rt_signal_mask_test was verifying whether signals could be sent correctly during unmasking——the
function names were exactly opposite to their functions. Now the two function names have been swapped,
and the corresponding comments have also been updated accordingly.After modification, it has been
verified that the signal-related utests can be executed correctly.

Signed-off-by: Mengchen Teng <teng_mengchen@163.com>

---------

Signed-off-by: Mengchen Teng <teng_mengchen@163.com>
2025-11-11 21:46:19 +08:00
Dailingxiang1
11a2f7eac6 bsp: add stm32f407-micu support
Update bsp/stm32/stm32f407-micu/rtconfig.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Update bsp/stm32/stm32f407-micu/rtconfig.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Update bsp/stm32/stm32f407-micu/project.uvproj

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Update bsp/stm32/stm32f407-micu/project.uvproj

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Update bsp/stm32/stm32f407-micu/board/board.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

add ci

Delete bsp/stm32/stm32f407-micu/project.uvgui.dlx

	modified:   MAINTAINERS
	deleted:    bsp/stm32/stm32f407-micu/figures/board.png.png
	deleted:    bsp/stm32/stm32f407-micu/project.uvopt
	modified:   bsp/stm32/stm32f407-micu/project.uvoptx
	modified:   bsp/stm32/stm32f407-micu/project.uvprojx
2025-11-11 12:35:33 +08:00
lhxj
d80c211075 docs(utest): Add standardized documentation for core.irq (irq_tc.c) (#10913)
* docs(utest): Add standardized documentation for core.irq (irq_tc.c)

Most test cases in `src/utest` lack standardized functional
documentation, as tracked in issue #10895. This leads to high
maintenance costs, difficulty for new contributors, and inefficient
code reviews.

Solution:
This patch adds the full, standardized documentation block to
`src/utest/irq_tc.c`, following the approved template.

The documentation details:
- Test Objectives and tested APIs
- Test Scenarios (for `irq_test` and `interrupt_test`)
- Verification Metrics (the `uassert` criteria)
- Dependencies (Kconfig options and hardware)
- Test Execution command and Expected Results

This makes the test case's purpose and behavior immediately clear
to future maintainers and reviewers.

Relates to #10895

Signed-off-by: lhxj <2743257167@qq.com>

* Update src/utest/irq_tc.c

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Signed-off-by: lhxj <2743257167@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-10 21:49:05 +08:00
rbb666
5119fc5433 update:rtthread version number to v5.3.0 2025-11-10 16:56:22 +08:00
Rbb666
596f0a8c37 action:Fixed assertion failure when running utest/messagequeue_tc multiple times. 2025-11-10 11:25:56 +08:00
wdfk-prog
44cf90a4ef fix(can): Resolve potential race condition in message transmission
Setting the send status flag `sndchange` after calling the can->ops->sendmsg function
could lead to a race condition if a transmission timeout occurs, resulting in incorrect state handling.
This patch moves the operation of setting the `sndchange` flag to before the call to can->ops->sendmsg.
This ensures that the mailbox's status is correctly marked as "sending" before the hardware begins transmission,
making the driver's state management more robust and reliable, especially in handling exceptions like timeouts.

Additionally, new macros for CAN filter modes have been added in dev_can.h.
2025-11-08 11:52:25 +08:00
Rbb666
2c9257831e utest:Fix signal info node leak in signal_tc when running multiple times. 2025-11-08 10:41:55 +08:00
RyanCW
6e184553d1 [bsp][gd32] 串口 tx buf应该可以设置为0 (#10908) 2025-11-08 10:39:25 +08:00
CYFS
cbe9f5d82c fix:stm32 can build error (#10909) 2025-11-08 10:38:42 +08:00
ChengyangMa
5b87ac609e [libc][syscall] add detailed function comments for memory management 2025-11-07 20:52:08 -05:00
Liu Changjie
8153fe5fd9 [libc][syscalls] 新手PR任务_增加文件操作相关函数的文档注释 2025-11-07 20:50:13 -05:00
Copilot
c631b39317 [Components] Remove vbus component and realview-a8-vmm libcpu (#10863)
* Initial plan

* Remove vbus component and related code

Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
2025-11-07 17:03:05 +08:00
Pcb-yun
96a125ca41 [bsp] [stm32] 添加鹿小班STM32H723开发板的BSP (#10842)
* [bsp] [stm32] 添加鹿小班STM32H723开发板的BSP

* fix(bsp): 修正链接脚本中的拼写错误并启用环境变量配置

修复链接脚本中'excetion'拼写错误为'execution'
启用rtconfig.py中的环境变量配置选项

* fix(bsp): 重新添加开发板IAR、GCC链接脚本

链接脚本中包含了所有寄存器,除flash与主sarm外其余寄存器已注释

* refactor(bsp): 移除冗余的SOC_STM32H723ZGT6配置选项
2025-11-07 17:01:51 +08:00
thomax2
2e1cf8d981 utilize the clang-format-ignore mechanism in bsp/nxp 2025-11-07 17:00:33 +08:00
wdfk-prog
95f7287313 fix:[dfs]ls在文件名太长时打印出来的文件名与大小连接在一起,无法区分 2025-11-07 16:59:23 +08:00
Copilot
d39a439603 [klibc] 将函数签名与标准 libc 对齐以修复类型冲突 #10890 2025-11-07 15:48:51 +08:00
wdfk-prog
4ee00eba9b feat[ulog]: 增加 Kconfig 选项以控制 Finsh/MSH 命令 2025-11-07 11:16:46 +08:00
CYFS
934c8195f4 [serialv2]:Fixed the issue where the serialv2 terminal did not have the enable stream mode 2025-11-07 09:52:55 +08:00
RyanCW
97f316f5d0 [bsp][gd32][serial_v2] 增加GD32F5支持 (#10840)
[bsp][gd32][serial_v2] 增加 GD32F5 支持
2025-11-07 09:28:59 +08:00
wdfk-prog
55306ad133 fix(finsh): Correct stack usage display format in list_thread command 2025-11-06 19:50:17 +08:00
lhxj
e3640ffc3d fix(doc): Exclude 'src/utest/perf/README.md' from Doxygen build (RT-Thread#10888)
Problem description:
The file 'src/utest/perf/README.md' was incorrectly appearing as a root-level page in the Doxygen documentation output.

Problem analysis:
This file was unintentionally included by the Doxygen build process following commit 7499790. It is an internal README for performance tests and is not intended to be part of the generated documentation.

Solution:
The issue is resolved by explicitly excluding this file from the build. The path '../src/utest/perf/README.md' has been added to the EXCLUDE list in both 'documentation/Doxyfile.1.9.1' and 'documentation/Doxyfile.1.9.8'.

This issue was originally introduced by the following commit:
Commit: 7499790
Title: utest: core: move perf testcase from example to src

Signed-off-by: lhxj <2743257167@qq.com>
2025-11-06 10:43:28 +08:00
kurisaw
fa6f86eda3 [ci]: disable the post-ci-status enabling option for regarding the relevant CI 2025-11-04 11:16:13 +08:00
Yuqiang Wang
925eab78df [ci]: disable auto-run status ci 2025-11-04 08:22:42 +08:00
CYFS
e458c0df7e Add a token to fix the 403 error 2025-11-02 16:31:46 +08:00
Yucai Liu
c91a7f46f5 [libcpu/arm/cortex-m33]: Fix incorrect CPU architecture in GCC context switch
The context_gcc.S file was incorrectly marked as cortex-m4 in both the
doxygen comment and .cpu directive, while the IAR and KEIL versions
correctly specify cortex-m33. This file uses ARMv8-M specific features
(PSPLIM register, TrustZone support) that are not available in Cortex-M4.

Changes:
- Update doxygen group from cortex-m4 to cortex-m33
- Change .cpu directive from cortex-m4 to cortex-m33
2025-11-02 16:23:31 +08:00
CYFS
d3ba09a0d7 [log]Update V5.2.2 Released Changelog. 2025-10-31 16:36:32 +08:00
Yuqiang Wang
ba509f92c2 [ci]: Introduce a regular inspection mechanism for abnormal CI reports (#10852) 2025-10-30 09:19:36 +08:00
Ze-Hou
666fa243f2 feature: k230: Add other existing drivers to the ci.attachconfig.yml file (#10869)
Resolve issue #10857

Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-10-30 06:20:37 +08:00
Copilot
a10922b01b [Feature] Add automated CI results comment to pull requests (#10856)
* Initial plan

* Add CI results comment workflow

Co-authored-by: supperthomas <60349489+supperthomas@users.noreply.github.com>

* Improve CI results comment formatting and PR detection

Co-authored-by: supperthomas <60349489+supperthomas@users.noreply.github.com>

* Add documentation for CI results comment feature

Co-authored-by: supperthomas <60349489+supperthomas@users.noreply.github.com>

* Add ToolsCI and pkgs_test to monitored workflows

Co-authored-by: supperthomas <60349489+supperthomas@users.noreply.github.com>

* Add immediate CI status comment via direct workflow integration

Co-authored-by: supperthomas <60349489+supperthomas@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: supperthomas <60349489+supperthomas@users.noreply.github.com>
2025-10-30 06:18:47 +08:00
451 changed files with 35217 additions and 6469 deletions

View File

@@ -160,6 +160,7 @@
"stm32/stm32f407-atk-explorer", "stm32/stm32f407-atk-explorer",
"stm32/stm32f407-robomaster-c", "stm32/stm32f407-robomaster-c",
"stm32/stm32f407-st-discovery", "stm32/stm32f407-st-discovery",
"stm32/stm32f407-micu",
"stm32/stm32f410-st-nucleo", "stm32/stm32f410-st-nucleo",
"stm32/stm32f411-st-nucleo", "stm32/stm32f411-st-nucleo",
"stm32/stm32f411-atk-nano", "stm32/stm32f411-atk-nano",
@@ -195,6 +196,7 @@
"stm32/stm32h563-st-nucleo", "stm32/stm32h563-st-nucleo",
"stm32/stm32h503-st-nucleo", "stm32/stm32h503-st-nucleo",
"stm32/stm32h723-st-nucleo", "stm32/stm32h723-st-nucleo",
"stm32/stm32h723-lxb-disco",
"stm32/stm32h730-esphosted-evb", "stm32/stm32h730-esphosted-evb",
"stm32/stm32h743-armfly-v7", "stm32/stm32h743-armfly-v7",
"stm32/stm32h743-atk-apollo", "stm32/stm32h743-atk-apollo",

View File

@@ -6,6 +6,8 @@ RT-Thread is a real-time operating system (RTOS) for embedded devices. When work
RT-Thread 是一个面向嵌入式设备的实时操作系统RTOS。在处理 RT-Thread 代码时,请遵循以下指南以确保高质量的贡献。 RT-Thread 是一个面向嵌入式设备的实时操作系统RTOS。在处理 RT-Thread 代码时,请遵循以下指南以确保高质量的贡献。
**When reviewing Pull Requests (PRs), you MUST check all items in the PR Review Checklist section and provide feedback according to the PR Review Instructions. / 在审查 Pull Request (PR) 时,必须检查 PR 审查清单部分中的所有项目,并根据 PR 审查指令提供反馈。**
## Code Review Guidelines / 代码审查指南 ## Code Review Guidelines / 代码审查指南
### Language Requirements / 语言要求 ### Language Requirements / 语言要求
@@ -26,21 +28,162 @@ When reviewing code, provide feedback in **both English and Chinese** to ensure
- Follow RT-Thread coding standards / 遵循 RT-Thread 编码标准 - Follow RT-Thread coding standards / 遵循 RT-Thread 编码标准
- Maintain consistent naming conventions / 保持一致的命名约定 - Maintain consistent naming conventions / 保持一致的命名约定
- Ensure proper code comments (not documentation) / 确保适当的代码注释(而非文档) - Ensure proper code comments (not documentation) / 确保适当的代码注释(而非文档)
4. **PR Title Naming Guidelines / PR 标题命名规范** 4. **PR Review Checklist / PR 审查清单**
- **Specify the module or keyword / 明确模块或关键字** - **PR Title Review / PR 标题审查**
- 标题需明确指出涉及的具体模块、子系统或关键字,例如具体的 BSPBoard Support Package或芯片厂商名称如 STM32, ESP32, NXP 等)。 - Check if PR title has proper prefix format / 检查 PR 标题是否有正确的前缀格式
- 示例:[STM32][I2C] Fix Kconfig parsing error 而非 fix:I2C——Kconfig修改。 - Verify prefix follows pattern: `[module/vendor][subsystem]` or `[module/vendor]` in lowercase / 验证前缀遵循格式:小写的 `[模块/厂商][子系统]``[模块/厂商]`
- **Clearly describe the content being repaired or modified / 清晰描述修复或更改内容** - Verify title describes changes based on modified files / 验证标题基于修改的文件描述变更
- 标题需简洁清晰地描述修复问题、添加的功能或修改的内容,避免模糊或过于简略的描述。 - Check if title is specific enough (avoid vague terms like "fix bug", "optimize code") / 检查标题是否足够具体(避免模糊术语如"修复问题"、"代码优化"
- 示例:[STM32][SPI] Fix buffer overflow in SPI driver 而非 SPI bug fix。 - If title lacks prefix or uses incorrect format, suggest: "PR title should follow format: `[module][subsystem] Description`. Example: `[stm32][drivers] Fix UART interrupt handling issue`" / 如果标题缺少前缀或格式错误,建议:"PR 标题应遵循格式:`[模块][子系统] 描述`。示例:`[stm32][drivers] Fix UART interrupt handling issue`"
- **Format Recommendations / 格式建议** - **PR Description Review / PR 内容审查**
- 推荐使用 [模块/厂商][子系统] 具体描述 的格式,确保标题结构化且信息完整。 - Check if PR description provides overview of modified files / 检查 PR 描述是否提供了修改文件的总概
- 使用英文描述问题(除非项目明确要求使用其他语言),以提高国际化可读性。 - Verify description explains: What (what changes), Why (why needed), How (which files modified) / 验证描述是否说明What做了什么修改、Why为什么需要、How修改了哪些文件
- 示例:[NXP][UART] Add timeout handling for UART receive。 - If description is missing or insufficient, suggest adding description with modified files list / 如果描述缺失或不充分,建议添加包含修改文件列表的描述
- **Issues to Avoid / 避免的问题** - **PR File Modification Review / PR 修改文件审查**
- 不要使用模糊的术语,如“修复问题”或“代码优化”,需具体说明问题或优化的内容。 - Check if PR contains multiple unrelated features / 检查 PR 是否包含多个不相关的特性
- 避免使用不规范的符号(如 ——),建议使用标准英文字符(如 - 或 :)。 - If PR mixes multiple features, suggest splitting into separate PRs / 如果 PR 混杂多个特性,建议拆分为多个 PR
- 不要省略关键上下文信息,如 BSP 或芯片厂商。 - Verify all file changes are related to the same feature/bug fix / 验证所有文件修改是否与同一功能/错误修复相关
- **PR Commit Review / PR Commit 审查**
- Check commit message format (should follow PR title format) / 检查 commit 消息格式(应遵循 PR 标题格式)
- Verify if commits are properly organized / 验证 commit 是否组织得当
- If routine changes (style fixes, minor bugs, docs, typos) are split into multiple commits, suggest squashing them / 如果常规修改(风格修复、小错误、文档、拼写)被拆分为多个 commit建议压缩它们
- Important commits (major features, refactoring, critical bugs) can remain separate / 重要提交(主要功能、重构、关键错误)可以保持独立
- If commit messages don't follow format, suggest: "Commit message should follow format: `[module][subsystem] Description`. Consider squashing routine changes into one commit." / 如果 commit 消息不符合格式,建议:"Commit 消息应遵循格式:`[模块][子系统] 描述`。考虑将常规修改压缩为一个 commit。"
### PR Review Instructions / PR 审查指令
**When reviewing a PR, you MUST systematically check the following items and provide feedback for any violations / 审查 PR 时,必须系统性地检查以下项目,并对任何违规行为提供反馈:**
#### Step 1: PR Title Check / 步骤 1PR 标题检查
1. **Check prefix format / 检查前缀格式**:
- Extract the PR title from the PR / 从 PR 中提取 PR 标题
- Verify if it starts with `[module][subsystem]` or `[module]` pattern in lowercase / 验证是否以小写的 `[模块][子系统]``[模块]` 格式开头
- Check if prefix matches the modified files (e.g., if files are in `bsp/stm32/drivers/`, prefix should be `[stm32][drivers]` or similar) / 检查前缀是否与修改的文件匹配(例如,如果文件在 `bsp/stm32/drivers/`,前缀应为 `[stm32][drivers]` 或类似)
- If prefix is missing, incorrect case (e.g., `[STM32]`), or doesn't match files, provide feedback / 如果前缀缺失、大小写错误(如 `[STM32]`)或不匹配文件,提供反馈
- **Feedback template / 反馈模板**:
```
🟡 [PR Title/PR 标题]: Missing or incorrect prefix format / 缺少或错误的前缀格式
English: PR title should follow format: `[module][subsystem] Description` in lowercase.
Current title: `{current_title}`.
Based on modified files, suggested title: `{suggested_title}`.
中文PR 标题应遵循格式:小写的 `[模块][子系统] 描述`。
当前标题:`{current_title}`。
基于修改的文件,建议标题:`{suggested_title}`。
```
2. **Check title specificity / 检查标题具体性**:
- Analyze modified files to understand what changes were made / 分析修改的文件以了解所做的更改
- Verify if title accurately describes changes based on modified files / 验证标题是否基于修改的文件准确描述更改
- Check for vague terms: "fix bug", "optimize code", "update", "modify", etc. / 检查模糊术语:"修复问题"、"代码优化"、"更新"、"修改"等
- If title is vague or doesn't match modified files, suggest a more specific title / 如果标题模糊或不匹配修改的文件,建议更具体的标题
- **Feedback template / 反馈模板**:
```
🟡 [PR Title/PR 标题]: Title is too vague or doesn't match modified files / 标题过于模糊或不匹配修改的文件
English: PR title should specifically describe changes based on modified files.
Current title: `{current_title}`.
Suggested: `{suggested_title}` based on files: {list_modified_files}.
中文PR 标题应基于修改的文件具体描述更改。
当前标题:`{current_title}`。
建议:基于文件 {list_modified_files} 的 `{suggested_title}`。
```
#### Step 2: PR Description Check / 步骤 2PR 内容检查
1. **Check description completeness / 检查描述完整性**:
- Read the PR description / 阅读 PR 描述
- Verify if it includes: / 验证是否包含:
- Overview of modified files / 修改文件的总概
- What changes were made / 做了什么修改
- Why changes are needed / 为什么需要这些修改
- List of modified files (optional but recommended) / 修改文件列表(可选但推荐)
- If description is missing, empty, or insufficient, provide feedback / 如果描述缺失、为空或不充分,提供反馈
- **Feedback template / 反馈模板**:
```
🟢 [PR Description/PR 描述]: Missing or insufficient description / 缺少或不充分的描述
English: PR description should include: (1) Overview of modified files, (2) What changes were made, (3) Why changes are needed, (4) List of modified files (optional).
Please add/modify the PR description.
中文PR 描述应包含:(1) 修改文件的总概,(2) 做了什么修改,(3) 为什么需要这些修改,(4) 修改文件列表(可选)。
请添加/修改 PR 描述。
Example format / 示例格式:
## Description / 描述
This PR fixes the UART interrupt handling issue in STM32 serial driver.
本次 PR 修复了 STM32 串口驱动中的中断处理问题。
## Modified Files / 修改文件
- `bsp/stm32/drivers/drv_usart.c`: Fixed interrupt handler logic
- `bsp/stm32/drivers/drv_usart.h`: Updated function declarations
```
#### Step 3: PR File Modification Check / 步骤 3PR 修改文件检查
1. **Check feature separation / 检查特性分离**:
- List all modified files in the PR / 列出 PR 中的所有修改文件
- Group files by feature/functionality / 按特性/功能对文件进行分组
- Identify if multiple unrelated features are mixed / 识别是否混杂了多个不相关的特性
- Unrelated features include: different drivers, different subsystems, unrelated bug fixes, etc. / 不相关的特性包括:不同的驱动、不同的子系统、不相关的错误修复等
- If multiple unrelated features are found, provide feedback with specific suggestions / 如果发现多个不相关的特性,提供具体建议的反馈
- **Feedback template / 反馈模板**:
```
🟡 [PR Structure/PR 结构]: Multiple unrelated features in one PR / 一个 PR 中包含多个不相关的特性
English: This PR contains multiple unrelated features: {list_features}.
Please split into separate PRs, each focusing on one feature.
Suggested PRs:
- PR 1: `[module1][subsystem1] {feature1_description}` (files: {list_files1})
- PR 2: `[module2][subsystem2] {feature2_description}` (files: {list_files2})
中文:此 PR 包含多个不相关的特性:{list_features}。
请拆分为多个 PR每个专注于一个特性。
建议的 PR
- PR 1: `[模块1][子系统1] {特性1描述}` (文件: {list_files1})
- PR 2: `[模块2][子系统2] {特性2描述}` (文件: {list_files2})
```
#### Step 4: PR Commit Check / 步骤 4PR Commit 检查
1. **Check commit message format / 检查 commit 消息格式**:
- Review all commit messages in the PR / 审查 PR 中的所有 commit 消息
- Verify if each commit message follows format: `[module][subsystem] Description` / 验证每个 commit 消息是否遵循格式:`[module][subsystem] 描述`
- Check if commit message prefix matches PR title prefix / 检查 commit 消息前缀是否与 PR 标题前缀匹配
- If commit messages don't follow format, provide feedback / 如果 commit 消息不符合格式,提供反馈
- **Feedback template / 反馈模板**:
```
🟡 [Commit Message/Commit 消息]: Commit message format violation / Commit 消息格式违规
English: Commit message should follow format: `[module][subsystem] Description`.
Invalid commits: {list_invalid_commits}.
Example: `[stm32][drivers] Fix UART interrupt handling issue`.
中文Commit 消息应遵循格式:`[模块][子系统] 描述`。
无效的 commit{list_invalid_commits}。
示例:`[stm32][drivers] Fix UART interrupt handling issue`。
```
2. **Check commit organization / 检查 commit 组织**:
- Identify routine changes: style fixes, minor bugs, documentation updates, typo corrections / 识别常规修改:风格修复、小错误、文档更新、拼写错误修正
- Identify important changes: major features, significant refactoring, critical bug fixes / 识别重要更改:主要功能、重大重构、关键错误修复
- Check if routine changes are split into multiple commits / 检查常规修改是否被拆分为多个 commit
- If routine changes are split, suggest squashing them / 如果常规修改被拆分,建议压缩它们
- **Feedback template / 反馈模板**:
```
🟢 [Commit Organization/Commit 组织]: Routine changes should be squashed / 常规修改应压缩
English: Routine changes (style fixes, minor bugs, docs, typos) should be squashed into one commit.
Commits to squash: {list_commits_to_squash}.
Please use `git rebase -i` to squash these commits.
中文:常规修改(风格修复、小错误、文档、拼写)应压缩为一个 commit。
要压缩的 commit{list_commits_to_squash}。
请使用 `git rebase -i` 压缩这些 commit。
```
### Review Comment Format / 审查评论格式 ### Review Comment Format / 审查评论格式
@@ -59,6 +202,8 @@ Example/示例:
// Your code example here / 你的代码示例 // Your code example here / 你的代码示例
``` ```
``` ```
**For PR-related issues, use severity level 🟡 Minor or 🟢 Suggestion / 对于 PR 相关的问题,使用严重程度级别 🟡 Minor 或 🟢 Suggestion**
### Common Issues to Check / 常见问题检查 ### Common Issues to Check / 常见问题检查
1. **Resource Management / 资源管理** 1. **Resource Management / 资源管理**

139
.github/workflows/README_CI_RESULTS.md vendored Normal file
View File

@@ -0,0 +1,139 @@
# CI Results Comment Workflow
## Overview / 概述
This feature automatically posts CI test results as comments on Pull Requests, making it easier for contributors and reviewers to see the status of all CI checks at a glance.
此功能自动将 CI 测试结果作为评论发布到 Pull Request 中,使贡献者和审阅者更容易一目了然地看到所有 CI 检查的状态。
## Implementation / 实现方式
The feature uses **two complementary approaches** to ensure CI results are always visible:
该功能使用**两种互补方法**来确保 CI 结果始终可见:
### 1. Direct Workflow Integration (Immediate) / 直接工作流集成(立即生效)
Each main CI workflow includes a `post-ci-status` job that:
每个主要 CI 工作流都包含一个 `post-ci-status` 作业,它:
- ✅ Works immediately on PR branches (no merge required) / 立即在 PR 分支上生效(无需合并)
- 📝 Updates a single comment with workflow status / 使用工作流状态更新单个评论
- 🔄 Runs after each workflow completes / 在每个工作流完成后运行
**Modified Workflows:**
- `bsp_buildings.yml`
- `static_code_analysis.yml`
- `format_check.yml`
- `utest_auto_run.yml`
### 2. Workflow Run Trigger (After Merge) / 工作流运行触发器(合并后)
The `ci_results_comment.yml` workflow:
`ci_results_comment.yml` 工作流:
- ⏰ Triggers when CI workflows complete / 在 CI 工作流完成时触发
- 📊 Provides comprehensive summary of all workflows / 提供所有工作流的全面摘要
- 🔍 Shows detailed job-level information / 显示详细的作业级信息
- ⚠️ **Only works after merged to master** / **仅在合并到 master 后才有效**
## Features / 功能特性
1. **Automatic Updates / 自动更新**: The comment is automatically created when CI workflows complete and updated as new workflows finish.
/ 当 CI 工作流完成时自动创建评论,并在新工作流完成时更新。
2. **Comprehensive Summary / 全面总结**: Shows the status of all major CI workflows including:
/ 显示所有主要 CI 工作流的状态,包括:
- RT-Thread BSP Static Build Check / BSP 静态构建检查
- Static code analysis / 静态代码分析
- Check File Format and License / 文件格式和许可证检查
- utest_auto_run / 单元测试自动运行
3. **Status Indicators / 状态指示器**:
- ✅ Success / 成功
- ❌ Failure / 失败
- 🟠 Queued / 排队中
- 🟡 In Progress / 进行中
- ⏭️ Skipped / 已跳过
4. **Detailed Information / 详细信息**: Expandable sections show individual job results within each workflow.
/ 可展开的部分显示每个工作流中的各个作业结果。
## How It Works / 工作原理
1. The workflow is triggered when any of the monitored CI workflows complete.
/ 当任何受监控的 CI 工作流完成时,将触发此工作流。
2. It collects the status of all workflows and jobs for the associated Pull Request.
/ 它收集关联 Pull Request 的所有工作流和作业的状态。
3. A formatted comment is posted (or updated if one already exists) with the current CI status.
/ 发布(或更新已存在的)格式化评论,显示当前 CI 状态。
## Comment Format / 评论格式
The comment includes:
评论包括:
- **Overall Summary / 总体摘要**: Quick statistics showing count of passed, failed, queued, in-progress, and skipped workflows.
/ 快速统计数据,显示通过、失败、排队、进行中和跳过的工作流数量。
- **Detailed Results / 详细结果**: Collapsible sections for each workflow with links to individual jobs.
/ 每个工作流的可折叠部分,包含指向各个作业的链接。
## Benefits / 优势
1. **Visibility / 可见性**: Contributors can immediately see which CI checks have passed or failed without navigating to the Actions tab.
/ 贡献者无需导航到 Actions 选项卡即可立即查看哪些 CI 检查通过或失败。
2. **Efficiency / 效率**: Reviewers can quickly assess the CI status before reviewing the code.
/ 审阅者可以在审查代码之前快速评估 CI 状态。
3. **Transparency / 透明度**: All stakeholders have a clear view of the PR's CI status.
/ 所有利益相关者都可以清楚地了解 PR 的 CI 状态。
## Permissions Required / 所需权限
The workflow requires the following permissions:
工作流需要以下权限:
- `pull-requests: write` - To create and update comments / 创建和更新评论
- `issues: write` - To post comments on PR issues / 在 PR 问题上发布评论
- `actions: read` - To read workflow run status / 读取工作流运行状态
- `checks: read` - To read check run status / 读取检查运行状态
## Configuration / 配置
The workflow monitors the following workflows by default:
工作流默认监控以下工作流:
```yaml
workflows:
- "RT-Thread BSP Static Build Check"
- "Static code analysis"
- "Check File Format and License"
- "utest_auto_run"
```
To add more workflows to monitor, edit the `.github/workflows/ci_results_comment.yml` file and add workflow names to the `workflows` list.
要监控更多工作流,请编辑 `.github/workflows/ci_results_comment.yml` 文件并将工作流名称添加到 `workflows` 列表中。
## Troubleshooting / 故障排除
### Comment not appearing / 评论未出现
1. Ensure the workflow has the required permissions / 确保工作流具有所需权限
2. Check that the PR is from a branch in the repository (not a fork) / 检查 PR 是否来自存储库中的分支(而非分支)
3. Verify the workflow is enabled in the repository settings / 验证工作流在存储库设置中已启用
### Comment not updating / 评论未更新
1. The comment updates when a monitored workflow completes / 当受监控的工作流完成时,评论会更新
2. Check the Actions tab to see if the workflow is running / 检查 Actions 选项卡以查看工作流是否正在运行
3. Look for errors in the workflow logs / 在工作流日志中查找错误
## Contributing / 贡献
Contributions to improve this workflow are welcome! Please follow the standard contribution process outlined in the CONTRIBUTING.md file.
欢迎改进此工作流的贡献!请遵循 CONTRIBUTING.md 文件中概述的标准贡献流程。

View File

@@ -13,9 +13,6 @@ name: RT-Thread BSP Static Build Check
# Controls when the action will run. Triggers the workflow on push or pull request # Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the RT-Thread organization master branch # events but only for the RT-Thread organization master branch
on: on:
# Runs at 16:00 UTC (BeiJing 00:00) every day
schedule:
- cron: '0 16 * * *'
push: push:
branches: branches:
- master - master
@@ -46,6 +43,12 @@ on:
types: types:
- online-pkgs-static-building-trigger-event - online-pkgs-static-building-trigger-event
workflow_dispatch: workflow_dispatch:
inputs:
trigger_type:
description: '触发类型'
required: false
default: 'manual'
type: string
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -289,3 +292,16 @@ jobs:
with: with:
name: 00_all_bsp_output_${{ github.sha }} name: 00_all_bsp_output_${{ github.sha }}
path: output/ path: output/
# # Post CI status to PR comment
# post-ci-status:
# needs: build
# if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread'
# uses: ./.github/workflows/post_ci_status.yml
# with:
# workflow_name: "RT-Thread BSP Static Build Check"
# workflow_status: ${{ needs.build.result }}
# pr_number: ${{ github.event.pull_request.number }}
# permissions:
# pull-requests: write
# issues: write

303
.github/workflows/ci_results_comment.yml vendored Normal file
View File

@@ -0,0 +1,303 @@
#
# Copyright (c) 2025, RT-Thread Development Team
#
# SPDX-License-Identifier: Apache-2.0
#
# Change Logs:
# Date Author Notes
# 2025-10-27 GitHub Copilot Post CI results to PR comments
name: CI Results Comment
# on:
# workflow_run:
# workflows:
# - "RT-Thread BSP Static Build Check"
# - "Static code analysis"
# - "Check File Format and License"
# - "utest_auto_run"
# - "ToolsCI"
# - "pkgs_test"
# types:
# - completed
permissions:
pull-requests: write
issues: write
actions: read
checks: read
jobs:
comment-ci-results:
runs-on: ubuntu-22.04
if: github.event.workflow_run.event == 'pull_request' && github.repository_owner == 'RT-Thread'
steps:
- name: Get PR number
id: get-pr
uses: actions/github-script@v7
with:
script: |
// Get PR number from workflow_run
const prNumber = context.payload.workflow_run.pull_requests[0]?.number;
if (!prNumber) {
console.log('No PR found in workflow_run');
// Fallback: search for PR by branch
const pulls = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`
});
if (pulls.data.length === 0) {
console.log('No open PR found for this branch');
return null;
}
const pr = pulls.data[0];
console.log(`Found PR #${pr.number}`);
return pr.number;
}
console.log(`Found PR #${prNumber}`);
return prNumber;
- name: Get workflow run details
if: steps.get-pr.outputs.result != 'null'
id: workflow-details
uses: actions/github-script@v7
with:
script: |
const prNumber = ${{ steps.get-pr.outputs.result }};
if (!prNumber) {
return { success: false, message: 'No PR found' };
}
// Get all workflow runs for this PR
const workflowRuns = await github.rest.actions.listWorkflowRunsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
event: 'pull_request',
per_page: 100
});
// Filter runs for this specific PR
const prRuns = workflowRuns.data.workflow_runs.filter(run => {
return run.pull_requests.some(pr => pr.number === prNumber);
});
// Get the latest run for each workflow
const workflowMap = new Map();
for (const run of prRuns) {
const existing = workflowMap.get(run.name);
if (!existing || new Date(run.created_at) > new Date(existing.created_at)) {
workflowMap.set(run.name, run);
}
}
// Prepare results summary
const results = [];
for (const [name, run] of workflowMap) {
let status = '🟡';
let statusText = 'In Progress';
if (run.status === 'completed') {
if (run.conclusion === 'success') {
status = '✅';
statusText = 'Success';
} else if (run.conclusion === 'failure') {
status = '❌';
statusText = 'Failure';
} else if (run.conclusion === 'cancelled') {
status = '⏭️';
statusText = 'Cancelled';
} else if (run.conclusion === 'skipped') {
status = '⏭️';
statusText = 'Skipped';
}
} else if (run.status === 'queued') {
status = '🟠';
statusText = 'Queued';
}
results.push({
name: name,
status: status,
statusText: statusText,
url: run.html_url,
conclusion: run.conclusion,
runId: run.id
});
}
return {
success: true,
results: results,
prNumber: prNumber
};
- name: Get job details
if: steps.get-pr.outputs.result != 'null'
id: job-details
uses: actions/github-script@v7
with:
script: |
const workflowDetails = ${{ steps.workflow-details.outputs.result }};
if (!workflowDetails || !workflowDetails.success) {
return { jobs: [] };
}
const allJobs = [];
for (const result of workflowDetails.results) {
try {
const jobs = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: result.runId,
per_page: 100
});
for (const job of jobs.data.jobs) {
let jobStatus = '⌛';
if (job.status === 'completed') {
if (job.conclusion === 'success') {
jobStatus = '✅';
} else if (job.conclusion === 'failure') {
jobStatus = '❌';
} else if (job.conclusion === 'skipped') {
jobStatus = '⏭️';
}
} else if (job.status === 'in_progress') {
jobStatus = '🔄';
} else if (job.status === 'queued') {
jobStatus = '🟠';
}
allJobs.push({
workflow: result.name,
name: job.name,
status: jobStatus,
conclusion: job.conclusion || job.status,
url: job.html_url
});
}
} catch (error) {
console.log(`Error getting jobs for workflow ${result.name}: ${error.message}`);
}
}
return { jobs: allJobs };
- name: Post or update comment
if: steps.get-pr.outputs.result != 'null'
uses: actions/github-script@v7
with:
script: |
const prNumber = ${{ steps.get-pr.outputs.result }};
const workflowDetails = ${{ steps.workflow-details.outputs.result }};
const jobDetails = ${{ steps.job-details.outputs.result }};
if (!workflowDetails || !workflowDetails.success) {
console.log('No workflow details available');
return;
}
// Prepare comment body
const now = new Date();
const timestamp = now.toISOString();
const results = workflowDetails.results;
const jobs = jobDetails.jobs || [];
let commentBody = '<!-- CI Results Comment -->\n';
commentBody += '## 🤖 CI Test Results\n\n';
commentBody += `**Last Updated:** ${timestamp}\n\n`;
commentBody += '### Test Spec & Results:\n\n';
commentBody += '✅ Success | ❌ Failure | 🟠 Queued | 🟡 Progress | ⏭️ Skipped | ⚠️ Quarantine\n\n';
// Group jobs by workflow
const jobsByWorkflow = new Map();
for (const job of jobs) {
if (!jobsByWorkflow.has(job.workflow)) {
jobsByWorkflow.set(job.workflow, []);
}
jobsByWorkflow.get(job.workflow).push(job);
}
// Calculate overall statistics
let totalSuccess = 0;
let totalFailure = 0;
let totalQueued = 0;
let totalProgress = 0;
let totalSkipped = 0;
for (const result of results) {
if (result.conclusion === 'success') totalSuccess++;
else if (result.conclusion === 'failure') totalFailure++;
else if (result.statusText === 'Queued') totalQueued++;
else if (result.statusText === 'In Progress') totalProgress++;
else if (result.conclusion === 'skipped' || result.conclusion === 'cancelled') totalSkipped++;
}
// Summary line
commentBody += '#### Overall Summary\n\n';
commentBody += `- ✅ **Success:** ${totalSuccess}\n`;
commentBody += `- ❌ **Failure:** ${totalFailure}\n`;
commentBody += `- 🟠 **Queued:** ${totalQueued}\n`;
commentBody += `- 🟡 **In Progress:** ${totalProgress}\n`;
commentBody += `- ⏭️ **Skipped:** ${totalSkipped}\n\n`;
commentBody += '---\n\n';
commentBody += '### Detailed Results\n\n';
// Build detailed results
for (const result of results) {
commentBody += `<details>\n`;
commentBody += `<summary>${result.status} <strong>${result.name}</strong> - ${result.statusText}</summary>\n\n`;
commentBody += `**Workflow:** [${result.name}](${result.url})\n\n`;
// Show jobs for this workflow
const workflowJobs = jobsByWorkflow.get(result.name) || [];
if (workflowJobs.length > 0) {
commentBody += '**Jobs:**\n\n';
for (const job of workflowJobs) {
commentBody += `- ${job.status} [${job.name}](${job.url})\n`;
}
}
commentBody += '\n</details>\n\n';
}
commentBody += '\n---\n';
commentBody += '*🤖 This comment is automatically generated and updated by the CI system.*\n';
// Check if comment already exists
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber
});
const existingComment = comments.data.find(comment =>
comment.user.login === 'github-actions[bot]' &&
comment.body.includes('<!-- CI Results Comment -->')
);
if (existingComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: commentBody
});
console.log(`Updated comment ${existingComment.id} on PR #${prNumber}`);
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: commentBody
});
console.log(`Created new comment on PR #${prNumber}`);
}

View File

@@ -30,3 +30,16 @@ jobs:
run: | run: |
pip install click chardet PyYaml pip install click chardet PyYaml
python tools/ci/file_check.py check 'https://github.com/RT-Thread/rt-thread' 'master' python tools/ci/file_check.py check 'https://github.com/RT-Thread/rt-thread' 'master'
# # Post CI status to PR comment
# post-ci-status:
# needs: scancode_job
# if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread'
# uses: ./.github/workflows/post_ci_status.yml
# with:
# workflow_name: "Check File Format and License"
# workflow_status: ${{ needs.scancode_job.result }}
# pr_number: ${{ github.event.pull_request.number }}
# permissions:
# pull-requests: write
# issues: write

110
.github/workflows/post_ci_status.yml vendored Normal file
View File

@@ -0,0 +1,110 @@
#
# Copyright (c) 2025, RT-Thread Development Team
#
# SPDX-License-Identifier: Apache-2.0
#
# Change Logs:
# Date Author Notes
# 2025-10-27 GitHub Copilot Reusable workflow to post CI status
name: Post CI Status Comment
# on:
# workflow_call:
# inputs:
# workflow_name:
# description: 'Name of the workflow'
# required: true
# type: string
# workflow_status:
# description: 'Status of the workflow (success/failure)'
# required: true
# type: string
# pr_number:
# description: 'Pull request number'
# required: true
# type: number
permissions:
pull-requests: write
issues: write
jobs:
post-comment:
runs-on: ubuntu-22.04
if: github.repository_owner == 'RT-Thread'
steps:
- name: Post or update CI status comment
uses: actions/github-script@v7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
script: |
const prNumber = ${{ inputs.pr_number }};
const workflowName = '${{ inputs.workflow_name }}';
const workflowStatus = '${{ inputs.workflow_status }}';
// Status emoji mapping
const statusEmoji = workflowStatus === 'success' ? '✅' : '❌';
const timestamp = new Date().toISOString();
// Try to find existing comment
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber
});
const botComment = comments.data.find(comment =>
comment.user.login === 'github-actions[bot]' &&
comment.body.includes('<!-- CI Status Comment -->')
);
// Get all workflow runs for this PR to build comprehensive status
let allStatuses = {};
if (botComment) {
// Parse existing statuses from comment
const statusRegex = /- (✅|❌|🟡) \*\*(.+?)\*\*/g;
let match;
while ((match = statusRegex.exec(botComment.body)) !== null) {
allStatuses[match[2]] = match[1];
}
}
// Update current workflow status
allStatuses[workflowName] = statusEmoji;
// Build comment body
let commentBody = '<!-- CI Status Comment -->\n';
commentBody += '## 🤖 CI Test Results\n\n';
commentBody += `**Last Updated:** ${timestamp}\n\n`;
commentBody += '### Workflow Status:\n\n';
for (const [name, emoji] of Object.entries(allStatuses)) {
commentBody += `- ${emoji} **${name}**\n`;
}
commentBody += '\n---\n';
commentBody += '✅ Success | ❌ Failure | 🟡 In Progress\n\n';
commentBody += '*This comment is automatically updated as CI workflows complete.*\n';
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
console.log(`Updated comment ${botComment.id} on PR #${prNumber}`);
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: commentBody
});
console.log(`Created new comment on PR #${prNumber}`);
}

View File

@@ -0,0 +1,200 @@
name: Weekly CI Scheduler
on:
# Runs at 08:00 Beijing time every day
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
inputs:
debug:
description: 'Debug mode'
required: false
default: 'false'
env:
TARGET_WORKFLOWS: '["RT-Thread BSP Static Build Check", "utest_auto_run"]'
DISCUSSION_CATEGORY: "Github Action Exception Reports"
jobs:
trigger-and-monitor:
name: Trigger and Monitor CIs
runs-on: ubuntu-latest
outputs:
failed_workflows: ${{ steps.collect-results.outputs.failed_workflows }}
total_workflows: ${{ steps.collect-results.outputs.total_workflows }}
has_results: ${{ steps.collect-results.outputs.has_results }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Record start time
id: start-time
run: |
echo "start_time=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "Start time: $(date -u +'%Y-%m-%dT%H:%M:%SZ')"
- name: Trigger CI workflows directly
id: trigger-ci
run: |
python tools/ci/scheduled-ci-trigger/trigger_workflows_direct.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARGET_WORKFLOWS: ${{ env.TARGET_WORKFLOWS }}
- name: Wait for workflows to appear
id: wait-for-workflows
run: |
echo "Waiting for workflows to appear in API..."
python tools/ci/scheduled-ci-trigger/wait_for_workflows.py "${{ steps.start-time.outputs.start_time }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARGET_WORKFLOWS: ${{ env.TARGET_WORKFLOWS }}
- name: Monitor CI workflows
id: monitor-ci
run: |
python tools/ci/scheduled-ci-trigger/monitor_workflows.py "${{ steps.start-time.outputs.start_time }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARGET_WORKFLOWS: ${{ env.TARGET_WORKFLOWS }}
- name: Collect monitoring results
id: collect-results
run: |
echo "Checking for monitoring results..."
if [ -f "monitoring_results.json" ]; then
echo "monitoring_results.json found"
FAILED_COUNT=$(python -c "import json; data=json.load(open('monitoring_results.json')); print(len([w for w in data if w.get('conclusion') == 'failure']))")
TOTAL_COUNT=$(python -c "import json; data=json.load(open('monitoring_results.json')); print(len(data))")
echo "failed_workflows=$FAILED_COUNT" >> $GITHUB_OUTPUT
echo "total_workflows=$TOTAL_COUNT" >> $GITHUB_OUTPUT
echo "has_results=true" >> $GITHUB_OUTPUT
echo "Results: $FAILED_COUNT failed out of $TOTAL_COUNT total"
else
echo "monitoring_results.json not found"
echo "failed_workflows=0" >> $GITHUB_OUTPUT
echo "total_workflows=0" >> $GITHUB_OUTPUT
echo "has_results=false" >> $GITHUB_OUTPUT
fi
- name: Generate detailed report
if: steps.collect-results.outputs.has_results == 'true' && steps.collect-results.outputs.failed_workflows != '0'
id: generate-report
run: |
echo "Generating detailed report..."
python tools/ci/scheduled-ci-trigger/generate_report.py
echo "Report generation completed"
- name: Upload report artifact
if: steps.collect-results.outputs.has_results == 'true' && steps.collect-results.outputs.failed_workflows != '0'
uses: actions/upload-artifact@v4
with:
name: ci-failure-report
path: |
monitoring_results.json
failure_details.md
retention-days: 7
create-discussion:
name: Create Discussion Report
needs: trigger-and-monitor
if: needs.trigger-and-monitor.outputs.has_results == 'true' && needs.trigger-and-monitor.outputs.failed_workflows != '0'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download report artifact
uses: actions/download-artifact@v4
with:
name: ci-failure-report
- name: Create Discussion
uses: actions/github-script@v6
env:
DISCUSSION_CATEGORY: ${{ env.DISCUSSION_CATEGORY }}
with:
script: |
const fs = require('fs');
const reportPath = './failure_details.md';
let reportContent = fs.readFileSync(reportPath, 'utf8');
// 提取日期从第一行: # YYYYMMDD_ci_integration-failed-report
const lines = reportContent.split('\n');
const firstLine = lines[0].trim();
const dateMatch = firstLine.match(/# (\d{8})_ci_integration-failed-report/);
if (!dateMatch) {
console.error('Failed to extract date from first line:', firstLine);
process.exit(1);
}
const dateString = dateMatch[1];
const discussionTitle = `${dateString}_ci_integration-failed-report`;
// === 关键修复:移除第一行(用于提取的隐藏行) ===
reportContent = lines.slice(1).join('\n').trim();
// 获取仓库ID和分类ID
const getRepoQuery = `
query($owner: String!, $repo: String!) {
repository(owner: $owner, name: $repo) {
id
discussionCategories(first: 20) {
nodes {
id
name
}
}
}
}
`;
const repoData = await github.graphql(getRepoQuery, {
owner: context.repo.owner,
repo: context.repo.repo
});
const repositoryId = repoData.repository.id;
const categories = repoData.repository.discussionCategories.nodes;
const targetCategory = categories.find(cat => cat.name === process.env.DISCUSSION_CATEGORY);
if (!targetCategory) {
console.error('Category not found:', process.env.DISCUSSION_CATEGORY);
process.exit(1);
}
const createDiscussionMutation = `
mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!) {
createDiscussion(input: {
repositoryId: $repositoryId
categoryId: $categoryId
title: $title
body: $body
}) {
discussion {
id
title
url
}
}
}
`;
const result = await github.graphql(createDiscussionMutation, {
repositoryId: repositoryId,
categoryId: targetCategory.id,
title: discussionTitle,
body: reportContent // 使用清理后的内容(无第一行)
});
console.log('Discussion created successfully:', result.createDiscussion.discussion.url);

View File

@@ -55,3 +55,16 @@ jobs:
cppcheck --version cppcheck --version
cd .. cd ..
python tools/ci/cpp_check.py check python tools/ci/cpp_check.py check
# # Post CI status to PR comment
# post-ci-status:
# needs: scancode_job
# if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread'
# uses: ./.github/workflows/post_ci_status.yml
# with:
# workflow_name: "Static code analysis"
# workflow_status: ${{ needs.scancode_job.result }}
# pr_number: ${{ github.event.pull_request.number }}
# permissions:
# pull-requests: write
# issues: write

View File

@@ -18,6 +18,13 @@ on:
- documentation/** - documentation/**
- '**/README.md' - '**/README.md'
- '**/README_zh.md' - '**/README_zh.md'
workflow_dispatch:
inputs:
trigger_type:
description: '触发类型'
required: false
default: 'manual'
type: string
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -298,3 +305,15 @@ jobs:
break break
fi fi
done done
# # Post CI status to PR comment
# post-ci-status:
# needs: test
# if: always() && github.event_name == 'pull_request' && github.repository_owner == 'RT-Thread'
# uses: ./.github/workflows/post_ci_status.yml
# with:
# workflow_name: "utest_auto_run"
# workflow_status: ${{ needs.test.result }}
# pr_number: ${{ github.event.pull_request.number }}
# permissions:
# pull-requests: write
# issues: write

View File

@@ -147,6 +147,10 @@ tag: bsp_stm32f429-atk-apollo
path: bsp/stm32/stm32f429-atk-apollo path: bsp/stm32/stm32f429-atk-apollo
owners: lizhen9880(lizhen9880)<lizhen9880@126.com> owners: lizhen9880(lizhen9880)<lizhen9880@126.com>
tag: bsp_stm32f407-micu
path: bsp/stm32/stm32f407-micu
owners: DaiLingxiang(Dailingxiang1)<3070269033@qq.com>
tag: bsp_stm32h723-st-nucleo tag: bsp_stm32h723-st-nucleo
path: bsp/stm32/stm32h723-st-nucleo path: bsp/stm32/stm32h723-st-nucleo
owners: 下里巴人(hywing)<hywing.sir@qq.com> owners: 下里巴人(hywing)<hywing.sir@qq.com>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
# 从 .ignore_format.yml 迁移的规则
/v85xx*/Libraries/CMSIS/
/v85xx*/Libraries/VangoV85xx*_standard_peripheral/

View File

@@ -28,6 +28,5 @@ extern int __bss_end;
#define HEAP_END (void*)(0x20000000 + 0xA0000) #define HEAP_END (void*)(0x20000000 + 0xA0000)
void rt_hw_board_init(void); void rt_hw_board_init(void);
int rt_vbus_do_init(void);
#endif #endif

View File

@@ -34,55 +34,63 @@ menu "On-chip Peripheral Drivers"
config BSP_UART0_RX_USING_DMA config BSP_UART0_RX_USING_DMA
bool "Enable UART0 RX DMA" bool "Enable UART0 RX DMA"
depends on BSP_USING_UART0 depends on BSP_USING_UART0 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART0_TX_USING_DMA config BSP_UART0_TX_USING_DMA
bool "Enable UART0 TX DMA" bool "Enable UART0 TX DMA"
depends on BSP_USING_UART0 depends on BSP_USING_UART0 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART0_DMA_PING_BUFSIZE
int "Set UART0 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART0 && RT_USING_SERIAL_V2 && BSP_UART0_RX_USING_DMA
default 64
config BSP_UART0_RX_BUFSIZE config BSP_UART0_RX_BUFSIZE
int "Set UART0 RX buffer size" int "Set UART0 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART0 && RT_USING_SERIAL_V2 depends on BSP_USING_UART0 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART0_TX_BUFSIZE config BSP_UART0_TX_BUFSIZE
int "Set UART0 TX buffer size" int "Set UART0 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART0 && RT_USING_SERIAL_V2 depends on BSP_USING_UART0 && RT_USING_SERIAL_V2
default 0 default 128
config BSP_USING_UART1 config BSP_USING_UART1
bool "Enable UART1" bool "Enable UART1"
default n default y
config BSP_UART1_RX_USING_DMA config BSP_UART1_RX_USING_DMA
bool "Enable UART1 RX DMA" bool "Enable UART1 RX DMA"
depends on BSP_USING_UART1 depends on BSP_USING_UART1 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART1_TX_USING_DMA config BSP_UART1_TX_USING_DMA
bool "Enable UART1 TX DMA" bool "Enable UART1 TX DMA"
depends on BSP_USING_UART1 depends on BSP_USING_UART1 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART1_DMA_PING_BUFSIZE
int "Set UART1 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2 && BSP_UART1_RX_USING_DMA
default 64
config BSP_UART1_RX_BUFSIZE config BSP_UART1_RX_BUFSIZE
int "Set UART1 RX buffer size" int "Set UART1 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2 depends on BSP_USING_UART1 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART1_TX_BUFSIZE config BSP_UART1_TX_BUFSIZE
int "Set UART1 TX buffer size" int "Set UART1 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2 depends on BSP_USING_UART1 && RT_USING_SERIAL_V2
default 0 default 128
config BSP_USING_UART2 config BSP_USING_UART2
bool "Enable UART2" bool "Enable UART2"
@@ -90,27 +98,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART2_RX_USING_DMA config BSP_UART2_RX_USING_DMA
bool "Enable UART2 RX DMA" bool "Enable UART2 RX DMA"
depends on BSP_USING_UART2 depends on BSP_USING_UART2 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART2_TX_USING_DMA config BSP_UART2_TX_USING_DMA
bool "Enable UART2 TX DMA" bool "Enable UART2 TX DMA"
depends on BSP_USING_UART2 depends on BSP_USING_UART2 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART2_DMA_PING_BUFSIZE
int "Set UART2 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2 && BSP_UART2_RX_USING_DMA
default 64
config BSP_UART2_RX_BUFSIZE config BSP_UART2_RX_BUFSIZE
int "Set UART2 RX buffer size" int "Set UART2 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2 depends on BSP_USING_UART2 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART2_TX_BUFSIZE config BSP_UART2_TX_BUFSIZE
int "Set UART2 TX buffer size" int "Set UART2 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2 depends on BSP_USING_UART2 && RT_USING_SERIAL_V2
default 0 default 128
config BSP_USING_UART3 config BSP_USING_UART3
bool "Enable UART3" bool "Enable UART3"
@@ -118,27 +130,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART3_RX_USING_DMA config BSP_UART3_RX_USING_DMA
bool "Enable UART3 RX DMA" bool "Enable UART3 RX DMA"
depends on BSP_USING_UART3 depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART3_TX_USING_DMA config BSP_UART3_TX_USING_DMA
bool "Enable UART3 TX DMA" bool "Enable UART3 TX DMA"
depends on BSP_USING_UART3 depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART3_DMA_PING_BUFSIZE
int "Set UART3 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && BSP_UART3_RX_USING_DMA
default 64
config BSP_UART3_RX_BUFSIZE config BSP_UART3_RX_BUFSIZE
int "Set UART3 RX buffer size" int "Set UART3 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 depends on BSP_USING_UART3 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART3_TX_BUFSIZE config BSP_UART3_TX_BUFSIZE
int "Set UART3 TX buffer size" int "Set UART3 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 depends on BSP_USING_UART3 && RT_USING_SERIAL_V2
default 0 default 128
config BSP_USING_UART4 config BSP_USING_UART4
bool "Enable UART4" bool "Enable UART4"
@@ -146,27 +162,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART4_RX_USING_DMA config BSP_UART4_RX_USING_DMA
bool "Enable UART4 RX DMA" bool "Enable UART4 RX DMA"
depends on BSP_USING_UART4 depends on BSP_USING_UART4 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART4_TX_USING_DMA config BSP_UART4_TX_USING_DMA
bool "Enable UART4 TX DMA" bool "Enable UART4 TX DMA"
depends on BSP_USING_UART4 depends on BSP_USING_UART4 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART4_DMA_PING_BUFSIZE
int "Set UART4 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART4 && RT_USING_SERIAL_V2 && BSP_UART4_RX_USING_DMA
default 64
config BSP_UART4_RX_BUFSIZE config BSP_UART4_RX_BUFSIZE
int "Set UART4 RX buffer size" int "Set UART4 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART4 && RT_USING_SERIAL_V2 depends on BSP_USING_UART4 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART4_TX_BUFSIZE config BSP_UART4_TX_BUFSIZE
int "Set UART4 TX buffer size" int "Set UART4 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART4 && RT_USING_SERIAL_V2 depends on BSP_USING_UART4 && RT_USING_SERIAL_V2
default 0 default 128
config BSP_USING_UART5 config BSP_USING_UART5
bool "Enable UART5" bool "Enable UART5"
@@ -174,27 +194,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART5_RX_USING_DMA config BSP_UART5_RX_USING_DMA
bool "Enable UART5 RX DMA" bool "Enable UART5 RX DMA"
depends on BSP_USING_UART5 depends on BSP_USING_UART5 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART5_TX_USING_DMA config BSP_UART5_TX_USING_DMA
bool "Enable UART5 TX DMA" bool "Enable UART5 TX DMA"
depends on BSP_USING_UART5 depends on BSP_USING_UART5 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART5_DMA_PING_BUFSIZE
int "Set UART5 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART5 && RT_USING_SERIAL_V2 && BSP_UART5_RX_USING_DMA
default 64
config BSP_UART5_RX_BUFSIZE config BSP_UART5_RX_BUFSIZE
int "Set UART5 RX buffer size" int "Set UART5 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART5 && RT_USING_SERIAL_V2 depends on BSP_USING_UART5 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART5_TX_BUFSIZE config BSP_UART5_TX_BUFSIZE
int "Set UART5 TX buffer size" int "Set UART5 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART5 && RT_USING_SERIAL_V2 depends on BSP_USING_UART5 && RT_USING_SERIAL_V2
default 0 default 128
config BSP_USING_UART6 config BSP_USING_UART6
bool "Enable UART6" bool "Enable UART6"
@@ -202,27 +226,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART6_RX_USING_DMA config BSP_UART6_RX_USING_DMA
bool "Enable UART6 RX DMA" bool "Enable UART6 RX DMA"
depends on BSP_USING_UART6 depends on BSP_USING_UART6 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART6_TX_USING_DMA config BSP_UART6_TX_USING_DMA
bool "Enable UART6 TX DMA" bool "Enable UART6 TX DMA"
depends on BSP_USING_UART6 depends on BSP_USING_UART6 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART6_DMA_PING_BUFSIZE
int "Set UART6 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART6 && RT_USING_SERIAL_V2 && BSP_UART6_RX_USING_DMA
default 64
config BSP_UART6_RX_BUFSIZE config BSP_UART6_RX_BUFSIZE
int "Set UART6 RX buffer size" int "Set UART6 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART6 && RT_USING_SERIAL_V2 depends on BSP_USING_UART6 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART6_TX_BUFSIZE config BSP_UART6_TX_BUFSIZE
int "Set UART6 TX buffer size" int "Set UART6 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART6 && RT_USING_SERIAL_V2 depends on BSP_USING_UART6 && RT_USING_SERIAL_V2
default 0 default 128
config BSP_USING_UART7 config BSP_USING_UART7
bool "Enable UART7" bool "Enable UART7"
@@ -230,27 +258,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART7_RX_USING_DMA config BSP_UART7_RX_USING_DMA
bool "Enable UART7 RX DMA" bool "Enable UART7 RX DMA"
depends on BSP_USING_UART7 depends on BSP_USING_UART7 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART7_TX_USING_DMA config BSP_UART7_TX_USING_DMA
bool "Enable UART7 TX DMA" bool "Enable UART7 TX DMA"
depends on BSP_USING_UART7 depends on BSP_USING_UART7 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
select RT_SERIAL_USING_DMA
default n default n
config BSP_UART7_DMA_PING_BUFSIZE
int "Set UART7 RX DMA ping-pong buffer size"
range 16 65535
depends on BSP_USING_UART7 && RT_USING_SERIAL_V2 && BSP_UART7_RX_USING_DMA
default 64
config BSP_UART7_RX_BUFSIZE config BSP_UART7_RX_BUFSIZE
int "Set UART7 RX buffer size" int "Set UART7 RX buffer size"
range 64 65535 range 64 65535
depends on BSP_USING_UART7 && RT_USING_SERIAL_V2 depends on BSP_USING_UART7 && RT_USING_SERIAL_V2
default 64 default 128
config BSP_UART7_TX_BUFSIZE config BSP_UART7_TX_BUFSIZE
int "Set UART7 TX buffer size" int "Set UART7 TX buffer size"
range 0 65535 range 0 65535
depends on BSP_USING_UART7 && RT_USING_SERIAL_V2 depends on BSP_USING_UART7 && RT_USING_SERIAL_V2
default 0 default 128
endif endif
menuconfig BSP_USING_SPI menuconfig BSP_USING_SPI

View File

@@ -263,7 +263,6 @@ static void dma_recv_isr (struct rt_serial_device *serial)
RT_ASSERT(serial != RT_NULL); RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct gd32_uart, serial); uart = rt_container_of(serial, struct gd32_uart, serial);
recv_len = 0;
level = rt_hw_interrupt_disable(); level = rt_hw_interrupt_disable();
#if defined SOC_SERIES_GD32E23x #if defined SOC_SERIES_GD32E23x
counter = dma_transfer_number_get(uart->dma.rx.channel); counter = dma_transfer_number_get(uart->dma.rx.channel);
@@ -297,21 +296,14 @@ static void usart_isr (struct rt_serial_device *serial)
if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_RBNE) != RESET) if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_RBNE) != RESET)
{ {
struct rt_serial_rx_fifo *rx_fifo; rt_uint8_t chr = usart_data_receive(uart->periph);
rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; rt_hw_serial_control_isr(serial, RT_HW_SERIAL_CTRL_PUTC, (void *)&chr);
RT_ASSERT(rx_fifo != RT_NULL);
char chr = usart_data_receive(uart->periph);
rt_hw_serial_control_isr(serial, RT_HW_SERIAL_CTRL_PUTC, &chr);
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
/* Clear RXNE interrupt flag */
usart_interrupt_flag_clear(uart->periph, USART_INT_FLAG_RBNE);
} }
else if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_TBE) != RESET) else if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_TBE) != RESET)
{ {
rt_uint8_t put_char = 0; rt_uint8_t put_char = 0;
if (rt_hw_serial_control_isr(serial, RT_HW_SERIAL_CTRL_GETC, &put_char) == RT_EOK) if (rt_hw_serial_control_isr(serial, RT_HW_SERIAL_CTRL_GETC, (void *)&put_char) == RT_EOK)
{ {
usart_data_transmit(uart->periph, put_char); usart_data_transmit(uart->periph, put_char);
} }
@@ -320,7 +312,6 @@ static void usart_isr (struct rt_serial_device *serial)
usart_interrupt_disable(uart->periph, USART_INT_TBE); usart_interrupt_disable(uart->periph, USART_INT_TBE);
usart_interrupt_enable(uart->periph, USART_INT_TC); usart_interrupt_enable(uart->periph, USART_INT_TC);
} }
usart_interrupt_flag_clear(uart->periph, USART_INT_FLAG_TBE);
} }
else if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_TC) != RESET) else if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_TC) != RESET)
{ {
@@ -334,10 +325,9 @@ static void usart_isr (struct rt_serial_device *serial)
#ifdef RT_SERIAL_USING_DMA #ifdef RT_SERIAL_USING_DMA
else if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_IDLE) != RESET) else if (usart_interrupt_flag_get(uart->periph, USART_INT_FLAG_IDLE) != RESET)
{ {
volatile uint8_t data = (uint8_t)usart_data_receive(uart->periph); volatile uint8_t idle_clear_dummy = (uint8_t)usart_data_receive(uart->periph);
RT_UNUSED(idle_clear_dummy);
dma_recv_isr(serial); dma_recv_isr(serial);
usart_interrupt_flag_clear(uart->periph, USART_INT_FLAG_IDLE); usart_interrupt_flag_clear(uart->periph, USART_INT_FLAG_IDLE);
} }
#endif #endif
@@ -595,8 +585,8 @@ void UART7_IRQHandler (void)
} }
#endif /* BSP_USING_UART7 */ #endif /* BSP_USING_UART7 */
#if define SOC_SERIES_GD32E23x #if defined SOC_SERIES_GD32E23x
#if define BSP_UART0_RX_USING_DMA || define BSP_UART0_TX_USING_DMA #if defined BSP_UART0_RX_USING_DMA || defined BSP_UART0_TX_USING_DMA
void DMA_Channel1_2_IRQHandler(void) void DMA_Channel1_2_IRQHandler(void)
{ {
/* enter interrupt */ /* enter interrupt */
@@ -906,6 +896,9 @@ static void _uart_dma_receive (struct gd32_uart *uart, rt_uint8_t *buffer, rt_ui
dma_interrupt_enable(uart->dma.rx.channel, DMA_CHXCTL_HTFIE); dma_interrupt_enable(uart->dma.rx.channel, DMA_CHXCTL_HTFIE);
dma_interrupt_enable(uart->dma.rx.channel, DMA_CHXCTL_FTFIE); dma_interrupt_enable(uart->dma.rx.channel, DMA_CHXCTL_FTFIE);
/* enable circular mode */
dma_circulation_enable(uart->dma.rx.channel);
/* enable dma channel */ /* enable dma channel */
dma_channel_enable(uart->dma.rx.channel); dma_channel_enable(uart->dma.rx.channel);
@@ -953,8 +946,12 @@ static void _uart_dma_receive (struct gd32_uart *uart, rt_uint8_t *buffer, rt_ui
usart_interrupt_enable(uart->periph, USART_INT_IDLE); usart_interrupt_enable(uart->periph, USART_INT_IDLE);
/* enable dma receive */ /* enable dma receive */
#if defined SOC_SERIES_GD32F5xx
usart_dma_receive_config(uart->periph, USART_DENR_ENABLE);
#else
usart_dma_receive_config(uart->periph, USART_RECEIVE_DMA_ENABLE); usart_dma_receive_config(uart->periph, USART_RECEIVE_DMA_ENABLE);
#endif #endif
#endif
} }
static void _uart_dma_transmit (struct gd32_uart *uart, rt_uint8_t *buffer, rt_uint32_t size) static void _uart_dma_transmit (struct gd32_uart *uart, rt_uint8_t *buffer, rt_uint32_t size)
@@ -972,7 +969,11 @@ static void _uart_dma_transmit (struct gd32_uart *uart, rt_uint8_t *buffer, rt_u
DMA_CHCNT(uart->dma.tx.periph, uart->dma.tx.channel) = size; DMA_CHCNT(uart->dma.tx.periph, uart->dma.tx.channel) = size;
/* enable dma transmit */ /* enable dma transmit */
#if defined SOC_SERIES_GD32F5xx
usart_dma_transmit_config(uart->periph, USART_DENT_ENABLE);
#else
usart_dma_transmit_config(uart->periph, USART_TRANSMIT_DMA_ENABLE); usart_dma_transmit_config(uart->periph, USART_TRANSMIT_DMA_ENABLE);
#endif
/* enable dma channel */ /* enable dma channel */
dma_channel_enable(uart->dma.tx.periph, uart->dma.tx.channel); dma_channel_enable(uart->dma.tx.periph, uart->dma.tx.channel);
@@ -1057,7 +1058,7 @@ static void gd32_dma_config (struct rt_serial_device *serial, rt_ubase_t flag)
if (flag == RT_DEVICE_FLAG_DMA_RX) if (flag == RT_DEVICE_FLAG_DMA_RX)
{ {
rt_uint8_t *ptr = NULL; rt_uint8_t *ptr = NULL;
rt_hw_serial_control_isr(serial, RT_HW_SERIAL_CTRL_GET_DMA_PING_BUF, &ptr); rt_hw_serial_control_isr(serial, RT_HW_SERIAL_CTRL_GET_DMA_PING_BUF, (void *)&ptr);
/* start dma transfer */ /* start dma transfer */
_uart_dma_receive(uart, ptr, serial->config.dma_ping_bufsz); _uart_dma_receive(uart, ptr, serial->config.dma_ping_bufsz);

View File

@@ -32,12 +32,12 @@ struct gd32_uart
rcu_periph_enum tx_gpio_clk; rcu_periph_enum tx_gpio_clk;
rcu_periph_enum rx_gpio_clk; rcu_periph_enum rx_gpio_clk;
uint32_t tx_port; uint32_t tx_port;
#if defined SOC_SERIES_GD32F4xx || defined SOC_SERIES_GD32E23x #if defined SOC_SERIES_GD32F4xx || defined SOC_SERIES_GD32E23x || defined SOC_SERIES_GD32F5xx
uint16_t tx_af; uint16_t tx_af;
#endif #endif
uint16_t tx_pin; uint16_t tx_pin;
uint32_t rx_port; uint32_t rx_port;
#if defined SOC_SERIES_GD32F4xx || defined SOC_SERIES_GD32E23x #if defined SOC_SERIES_GD32F4xx || defined SOC_SERIES_GD32E23x || defined SOC_SERIES_GD32F5xx
uint16_t rx_af; uint16_t rx_af;
#endif #endif
uint16_t rx_pin; uint16_t rx_pin;

View File

@@ -1,9 +1,55 @@
scons.args: &scons scons.args: &scons
scons_arg: scons_arg:
- '--strict' - '--strict'
devices.spi:
<<: *scons
kconfig:
- CONFIG_RT_USING_SPI=y
- CONFIG_BSP_USING_SPI=y
- CONFIG_BSP_USING_SPI0=y
devices.i2c: devices.i2c:
<<: *scons <<: *scons
kconfig: kconfig:
- CONFIG_RT_USING_I2C=y - CONFIG_RT_USING_I2C=y
- CONFIG_BSP_USING_I2C=y - CONFIG_BSP_USING_I2C=y
- CONFIG_BSP_USING_I2C0=y - CONFIG_BSP_USING_I2C0=y
- CONFIG_BSP_USING_I2C_DMA=y
devices.adc:
<<: *scons
kconfig:
- CONFIG_RT_USING_ADC=y
- CONFIG_BSP_USING_ADC=y
devices.hwtimer:
<<: *scons
kconfig:
- CONFIG_RT_USING_HWTIMER=y
- CONFIG_BSP_USING_TIMERS=y
- CONFIG_BSP_USING_TIMER0=y
devices.pdma:
<<: *scons
kconfig:
- CONFIG_RT_USING_PDMA=y
- CONFIG_BSP_USING_PDMA=y
- CONFIG_BSP_USING_PDMA_CHANNEL0=y
devices.pwm:
<<: *scons
kconfig:
- CONFIG_RT_USING_PWM=y
- CONFIG_BSP_USING_PWM=y
- CONFIG_BSP_USING_PWM0=y
devices.rtc:
<<: *scons
kconfig:
- CONFIG_RT_USING_RTC=y
- CONFIG_BSP_USING_RTC=y
devices.ts:
<<: *scons
kconfig:
- CONFIG_RT_USING_TS=y
- CONFIG_BSP_USING_TS=y
devices.wdt:
<<: *scons
kconfig:
- CONFIG_RT_USING_WDT=y
- CONFIG_BSP_USING_WDT=y
- CONFIG_BSP_USING_WDT0=y

View File

@@ -534,8 +534,6 @@ CONFIG_RT_USING_ADT_REF=y
# CONFIG_RT_USING_RT_LINK is not set # CONFIG_RT_USING_RT_LINK is not set
# end of Utilities # end of Utilities
# CONFIG_RT_USING_VBUS is not set
# #
# Memory management # Memory management
# #
@@ -1619,6 +1617,7 @@ CONFIG_PKG_ZLIB_VER="latest"
# #
# Drivers Configuration # Drivers Configuration
# #
# CONFIG_BSP_USING_SPI is not set
# CONFIG_BSP_USING_I2C is not set # CONFIG_BSP_USING_I2C is not set
# CONFIG_BSP_USING_RTC is not set # CONFIG_BSP_USING_RTC is not set
# CONFIG_BSP_USING_ADC is not set # CONFIG_BSP_USING_ADC is not set

View File

@@ -1,10 +1,41 @@
menu "Drivers Configuration" menu "Drivers Configuration"
menuconfig BSP_USING_SPI
bool "Enable SPI"
select RT_USING_SPI
select RT_USING_QSPI
default n
if BSP_USING_SPI
config BSP_USING_SPI0
bool "Enable SPI0"
help
Support 1, 2, 4 and 8 lines, Max clock frequency is 200 Mhz.
default n
config BSP_USING_SPI1
bool "Enable SPI1"
help
Support 1, 2, and 4 lines, Max clock frequency is 100 Mhz.
default n
config BSP_USING_SPI2
bool "Enable SPI2"
help
Support 1, 2, and 4 lines, Max clock frequency is 100 Mhz.
default n
endif
menuconfig BSP_USING_I2C menuconfig BSP_USING_I2C
bool "Enable I2C" bool "Enable I2C"
select RT_USING_I2C select RT_USING_I2C
default n default n
if BSP_USING_I2C if BSP_USING_I2C
config BSP_USING_I2C_DMA
bool "Enable I2C with DMA"
default n
config BSP_USING_I2C0 config BSP_USING_I2C0
bool "Enable I2C0" bool "Enable I2C0"
default n default n

View File

@@ -33,9 +33,11 @@
#include <rtdevice.h> #include <rtdevice.h>
#include <riscv_io.h> #include <riscv_io.h>
#include <ioremap.h> #include <ioremap.h>
#include <mmu.h>
#include "board.h" #include "board.h"
#include "drv_i2c.h" #include "drv_i2c.h"
#include "sysctl_clk.h" #include "sysctl_clk.h"
#include "drv_pdma.h"
#undef DBG_TAG #undef DBG_TAG
#undef DBG_LVL #undef DBG_LVL
@@ -43,6 +45,42 @@
#define DBG_LVL DBG_INFO #define DBG_LVL DBG_INFO
#include <rtdbg.h> #include <rtdbg.h>
/*
* Note:
* - When DMA is enabled, the PDMA driver requires both the address and
* data to be 4-byte aligned.(Address alignment is handled internally
* by this driver, so application developers do not need to worry about
* address alignment.) Therefore, when using DMA for read/write operations,
* if the data size is not 4-byte aligned, even with DMA enabled, the driver
* will actually use CPU polling for read/write. Application code should be
* aware of this and handle it accordingly. For example, if the data length
* to be read or written is not 4-byte aligned, you can split the data into
* an aligned part and an unaligned part, use DMA for the aligned part, and
* use CPU polling for the unaligned part.
*/
#ifdef BSP_USING_I2C_DMA
#define K230_I2C_PDMA_CH_INVALID 0xFF
#define K230_I2C_PDMA_CACHE_LINE_SIZE 64
struct _i2c_pdma_cfg
{
rt_event_t event;
rt_uint8_t ch;
usr_pdma_cfg_t cfg;
device_sel_e tx_dev;
device_sel_e rx_dev;
};
typedef enum
{
K230_I2C_PDMA_EVENT_NONE = 0x00,
K230_I2C_PDMA_EVENT_COMPLETE = 0x01,
K230_I2C_PDMA_EVENT_TIMEOUT = 0x02,
} k230_i2c_pdma_event_t;
#endif
struct _i2c_speed_cfg struct _i2c_speed_cfg
{ {
rt_uint16_t hcnt; rt_uint16_t hcnt;
@@ -55,13 +93,22 @@ struct k230_i2c_dev
struct rt_i2c_bus_device dev; struct rt_i2c_bus_device dev;
const char *name; const char *name;
rt_ubase_t base; rt_ubase_t base;
rt_ubase_t base_pa;
size_t size; size_t size;
int vector; int vector;
rt_uint32_t clock; rt_uint32_t clock;
struct rt_i2c_msg *msg; struct rt_i2c_msg *msg;
struct _i2c_speed_cfg speed_cfg; struct _i2c_speed_cfg speed_cfg;
#ifdef BSP_USING_I2C_DMA
struct _i2c_pdma_cfg pdma_cfg;
#endif
}; };
#ifdef BSP_USING_I2C_DMA
static rt_err_t k230_i2c_pdma_read(struct k230_i2c_dev *dev);
static rt_err_t k230_i2c_pdma_write(struct k230_i2c_dev *dev);
#endif
static rt_size_t k230_i2c_get_timer(rt_size_t base) static rt_size_t k230_i2c_get_timer(rt_size_t base)
{ {
return rt_tick_get() - base ; return rt_tick_get() - base ;
@@ -226,7 +273,6 @@ static int k230_i2c_wait_for_bus_busy(struct k230_i2c_dev *dev)
static int k230_i2c_xfer_init(struct k230_i2c_dev *dev) static int k230_i2c_xfer_init(struct k230_i2c_dev *dev)
{ {
volatile i2c_t *i2c = (i2c_t *)dev->base; volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint8_t addr = 0;
if (k230_i2c_wait_for_bus_busy(dev) != RT_EOK) if (k230_i2c_wait_for_bus_busy(dev) != RT_EOK)
{ {
@@ -267,8 +313,15 @@ static int k230_i2c_xfer_finish(struct k230_i2c_dev *dev)
return RT_EOK; return RT_EOK;
} }
static int _k230_i2c_read(struct k230_i2c_dev *dev) static int k230_i2c_read(struct k230_i2c_dev *dev)
{ {
#ifdef BSP_USING_I2C_DMA
if (dev->msg->len % 4 == 0)
{
return k230_i2c_pdma_read(dev);
}
#endif
volatile i2c_t *i2c = (i2c_t *)dev->base; volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_size_t start_time_rx = 0; rt_size_t start_time_rx = 0;
rt_uint32_t recv_len = dev->msg->len; rt_uint32_t recv_len = dev->msg->len;
@@ -317,14 +370,20 @@ static int _k230_i2c_read(struct k230_i2c_dev *dev)
return k230_i2c_xfer_finish(dev); return k230_i2c_xfer_finish(dev);
} }
static int _k230_i2c_write(struct k230_i2c_dev *dev) static int k230_i2c_write(struct k230_i2c_dev *dev)
{ {
#ifdef BSP_USING_I2C_DMA
if (dev->msg->len % 4 == 0)
{
return k230_i2c_pdma_write(dev);
}
#endif
volatile i2c_t *i2c = (i2c_t *)dev->base; volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_size_t start_time_tx = 0; rt_size_t start_time_tx = 0;
rt_uint32_t tran_len = dev->msg->len; rt_uint32_t tran_len = dev->msg->len;
rt_uint8_t *buffer = dev->msg->buf; rt_uint8_t *buffer = dev->msg->buf;
rt_uint32_t cmd = 0; rt_uint32_t cmd = 0;
rt_uint32_t cut = 0;
if (k230_i2c_xfer_init(dev) != RT_EOK) if (k230_i2c_xfer_init(dev) != RT_EOK)
{ {
@@ -383,12 +442,13 @@ static rt_ssize_t k230_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg
if (msgs->flags & RT_I2C_RD) if (msgs->flags & RT_I2C_RD)
{ {
ret = _k230_i2c_read(i2c_dev); ret = k230_i2c_read(i2c_dev);
} }
else else
{ {
ret = _k230_i2c_write(i2c_dev); ret = k230_i2c_write(i2c_dev);
} }
if (ret != RT_EOK) if (ret != RT_EOK)
{ {
return -RT_EIO; return -RT_EIO;
@@ -467,52 +527,372 @@ static struct k230_i2c_dev k230_i2c_devs[] =
#ifdef BSP_USING_I2C0 #ifdef BSP_USING_I2C0
{ {
.name = "i2c0", .name = "i2c0",
.base = I2C0_BASE_ADDR, .base_pa = I2C0_BASE_ADDR,
.size = I2C0_IO_SIZE, .size = I2C0_IO_SIZE,
.vector = K230_IRQ_I2C0, .vector = K230_IRQ_I2C0,
#ifdef BSP_USING_I2C_DMA
.pdma_cfg.tx_dev = I2C0_TX,
.pdma_cfg.rx_dev = I2C0_RX,
#endif
}, },
#endif #endif
#ifdef BSP_USING_I2C1 #ifdef BSP_USING_I2C1
{ {
.name = "i2c1", .name = "i2c1",
.base = I2C1_BASE_ADDR, .base_pa = I2C1_BASE_ADDR,
.size = I2C1_IO_SIZE, .size = I2C1_IO_SIZE,
.vector = K230_IRQ_I2C1, .vector = K230_IRQ_I2C1,
#ifdef BSP_USING_I2C_DMA
.pdma_cfg.tx_dev = I2C1_TX,
.pdma_cfg.rx_dev = I2C1_RX,
#endif
}, },
#endif #endif
#ifdef BSP_USING_I2C2 #ifdef BSP_USING_I2C2
{ {
.name = "i2c2", .name = "i2c2",
.base = I2C2_BASE_ADDR, .base_pa = I2C2_BASE_ADDR,
.size = I2C2_IO_SIZE, .size = I2C2_IO_SIZE,
.vector = K230_IRQ_I2C2, .vector = K230_IRQ_I2C2,
#ifdef BSP_USING_I2C_DMA
.pdma_cfg.tx_dev = I2C2_TX,
.pdma_cfg.rx_dev = I2C2_RX,
#endif
}, },
#endif #endif
#ifdef BSP_USING_I2C3 #ifdef BSP_USING_I2C3
{ {
.name = "i2c3", .name = "i2c3",
.base = I2C3_BASE_ADDR, .base_pa = I2C3_BASE_ADDR,
.size = I2C3_IO_SIZE, .size = I2C3_IO_SIZE,
.vector = K230_IRQ_I2C3, .vector = K230_IRQ_I2C3,
#ifdef BSP_USING_I2C_DMA
.pdma_cfg.tx_dev = I2C3_TX,
.pdma_cfg.rx_dev = I2C3_RX,
#endif
}, },
#endif #endif
#ifdef BSP_USING_I2C4 #ifdef BSP_USING_I2C4
{ {
.name = "i2c4", .name = "i2c4",
.base = I2C4_BASE_ADDR, .base_pa = I2C4_BASE_ADDR,
.size = I2C4_IO_SIZE, .size = I2C4_IO_SIZE,
.vector = K230_IRQ_I2C4, .vector = K230_IRQ_I2C4,
#ifdef BSP_USING_I2C_DMA
.pdma_cfg.tx_dev = I2C4_TX,
.pdma_cfg.rx_dev = I2C4_RX,
#endif
}, },
#endif #endif
}; };
#ifdef BSP_USING_I2C_DMA
static void k230_i2c_pdma_call_back(rt_uint8_t ch, rt_bool_t is_done)
{
k230_i2c_pdma_event_t event_type = is_done ? K230_I2C_PDMA_EVENT_COMPLETE : K230_I2C_PDMA_EVENT_TIMEOUT;
for (rt_uint8_t i = 0; i < sizeof(k230_i2c_devs)/sizeof(k230_i2c_devs[0]); i++)
{
struct k230_i2c_dev *dev = &k230_i2c_devs[i];
if (dev->pdma_cfg.event != RT_NULL && dev->pdma_cfg.ch == ch && dev->pdma_cfg.ch != K230_I2C_PDMA_CH_INVALID)
{
rt_event_send(dev->pdma_cfg.event, event_type);
return;
}
}
}
static void k230_i2c_pdma_cleanup(struct k230_i2c_dev *dev)
{
rt_uint8_t ch = dev->pdma_cfg.ch;
if (ch == K230_I2C_PDMA_CH_INVALID)
{
return;
}
dev->pdma_cfg.ch = K230_I2C_PDMA_CH_INVALID;
k230_pdma_release_channel(ch);
}
static rt_err_t k230_i2c_pdma_read(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint8_t *buffer = dev->msg->buf;
rt_uint8_t *buf;
void *buf_pa;
rt_err_t err;
rt_uint8_t ch;
rt_uint32_t recv_event, read_len;
rt_size_t start_time_tx = 0;
rt_uint32_t cmd = 0;
err = k230_pdma_request_channel(&ch);
if (err != RT_EOK)
{
LOG_E("i2c pdma request channel failed");
return err;
}
dev->pdma_cfg.ch = ch;
err = k230_pdma_set_callback(ch, k230_i2c_pdma_call_back);
if (err != RT_EOK)
{
LOG_E("i2c pdma set callback failed");
k230_i2c_pdma_cleanup(dev);
return err;
}
read_len = dev->msg->len;
buf = (rt_uint8_t *)rt_malloc_align(read_len, K230_I2C_PDMA_CACHE_LINE_SIZE);
if (buf == RT_NULL)
{
LOG_E("i2c pdma malloc buffer failed");
k230_i2c_pdma_cleanup(dev);
return -RT_ENOMEM;
}
buf_pa = rt_kmem_v2p(buf);
if (buf_pa == RT_NULL)
{
LOG_E("i2c pdma get phy addr failed");
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return -RT_ERROR;
}
rt_event_control(dev->pdma_cfg.event, RT_IPC_CMD_RESET, NULL);
dev->pdma_cfg.cfg.device = dev->pdma_cfg.rx_dev;
dev->pdma_cfg.cfg.src_addr = (rt_uint8_t *)(dev->base_pa + 0x10);
dev->pdma_cfg.cfg.dst_addr = (rt_uint8_t *)buf_pa;
dev->pdma_cfg.cfg.line_size = read_len;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_src_type = FIXED;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dev_hsize = PSBYTE1;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dat_endian = PDEFAULT;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dev_blen = PBURST_LEN_4;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_priority = 7;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dev_tout = 0xFFF;
err = k230_pdma_config(ch, &dev->pdma_cfg.cfg);
if (err != RT_EOK)
{
LOG_E("i2c pdma config failed");
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return err;
}
/* If no start condition is sent before reading, then send a repeated start. */
if (dev->msg->flags & RT_I2C_NO_START)
{
cmd |= I2C_DATA_CMD_RESTART;
}
else
{
if (k230_i2c_xfer_init(dev) != RT_EOK)
{
LOG_E("i2c pdma xfer init failed");
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return -RT_EBUSY;
}
}
start_time_tx = k230_i2c_get_timer(0);
err = k230_pdma_start(ch);
if (err != RT_EOK)
{
LOG_E("i2c pdma start failed");
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return err;
}
for (rt_uint32_t i = 0; i < read_len; i++)
{
while (i2c->status.tfnf == 0);
/* Write stop when the last byte */
cmd = i == (read_len - 1) ? I2C_DATA_CMD_STOP : 0;
/* Write to data cmd register to trigger i2c */
writel(cmd | I2C_DATA_CMD_READ, &i2c->data_cmd);
cmd = 0;
}
err = rt_event_recv(dev->pdma_cfg.event,
K230_I2C_PDMA_EVENT_COMPLETE | K230_I2C_PDMA_EVENT_TIMEOUT,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER,
&recv_event);
if (err != RT_EOK || (recv_event & K230_I2C_PDMA_EVENT_TIMEOUT))
{
LOG_E("i2c pdma read timeout");
k230_pdma_stop(ch);
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return -RT_ETIMEOUT;
}
rt_memcpy(buffer, buf, read_len);
k230_pdma_stop(ch);
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
if (k230_i2c_get_timer(start_time_tx) > dev->dev.timeout)
{
return -RT_ETIMEOUT;
}
return k230_i2c_xfer_finish(dev);
}
static inline rt_uint32_t k230_i2c_make_data_cmd(rt_uint8_t data, rt_uint32_t flags)
{
return (rt_uint32_t)data | flags;
}
static rt_err_t k230_i2c_pdma_write(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint8_t *buffer = dev->msg->buf;
rt_uint32_t *buf;
void *buf_pa;
rt_err_t err;
rt_uint8_t ch;
rt_uint32_t recv_event, tran_len, flags;
rt_size_t start_time_tx = 0;
err = k230_pdma_request_channel(&ch);
if (err != RT_EOK)
{
LOG_E("i2c pdma request channel failed");
return err;
}
dev->pdma_cfg.ch = ch;
err = k230_pdma_set_callback(ch, k230_i2c_pdma_call_back);
if (err != RT_EOK)
{
LOG_E("i2c pdma set callback failed");
k230_i2c_pdma_cleanup(dev);
return err;
}
tran_len = dev->msg->len;
buf = (rt_uint32_t *)rt_malloc_align(tran_len * sizeof(rt_uint32_t), K230_I2C_PDMA_CACHE_LINE_SIZE);
if (buf == RT_NULL)
{
LOG_E("i2c pdma malloc buffer failed");
k230_i2c_pdma_cleanup(dev);
return -RT_ENOMEM;
}
for (rt_uint32_t i = 0; i < tran_len; i++)
{
flags = 0;
if (i == (tran_len - 1) && !(dev->msg->flags & RT_I2C_NO_STOP))
{
flags |= I2C_DATA_CMD_STOP;
}
buf[i] = k230_i2c_make_data_cmd(buffer[i], flags);
}
buf_pa = rt_kmem_v2p(buf);
if (buf_pa == RT_NULL)
{
LOG_E("i2c pdma get phy addr failed");
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return -RT_ERROR;
}
rt_event_control(dev->pdma_cfg.event, RT_IPC_CMD_RESET, NULL);
dev->pdma_cfg.cfg.device = dev->pdma_cfg.tx_dev;
dev->pdma_cfg.cfg.src_addr = (rt_uint8_t *)buf_pa;
dev->pdma_cfg.cfg.dst_addr = (rt_uint8_t *)(dev->base_pa + 0x10);
dev->pdma_cfg.cfg.line_size = tran_len * sizeof(rt_uint32_t);
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_src_type = CONTINUE;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dev_hsize = PSBYTE4;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dat_endian = PDEFAULT;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dev_blen = PBURST_LEN_4;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_priority = 7;
dev->pdma_cfg.cfg.pdma_ch_cfg.ch_dev_tout = 0xFFF;
err = k230_pdma_config(ch, &dev->pdma_cfg.cfg);
if (err != RT_EOK)
{
LOG_E("i2c pdma config failed");
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return err;
}
if (k230_i2c_xfer_init(dev) != RT_EOK)
{
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return -RT_EBUSY;
}
start_time_tx = k230_i2c_get_timer(0);
err = k230_pdma_start(ch);
if (err != RT_EOK)
{
LOG_E("i2c pdma start failed");
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return err;
}
err = rt_event_recv(dev->pdma_cfg.event,
K230_I2C_PDMA_EVENT_COMPLETE | K230_I2C_PDMA_EVENT_TIMEOUT,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER,
&recv_event);
if (err != RT_EOK || (recv_event & K230_I2C_PDMA_EVENT_TIMEOUT))
{
LOG_E("i2c pdma write timeout");
k230_pdma_stop(ch);
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
return -RT_ETIMEOUT;
}
k230_pdma_stop(ch);
k230_i2c_pdma_cleanup(dev);
rt_free_align(buf);
if (k230_i2c_get_timer(start_time_tx) > dev->dev.timeout)
{
return -RT_ETIMEOUT;
}
return RT_EOK;
}
static void k230_i2c_pdma_init(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
i2c->dma_cr.tdmae = 1;
i2c->dma_cr.rdmae = 1;
i2c->dma_tdlr.dmatdl = 15;
i2c->dma_rdlr.dmardl = 3;
}
#endif
int rt_hw_i2c_init(void) int rt_hw_i2c_init(void)
{ {
int i; int i;
for (i = 0; i < sizeof(k230_i2c_devs) / sizeof(k230_i2c_devs[0]); i++) for (i = 0; i < sizeof(k230_i2c_devs) / sizeof(k230_i2c_devs[0]); i++)
{ {
k230_i2c_devs[i].base = (rt_ubase_t)rt_ioremap((void *)k230_i2c_devs[i].base, k230_i2c_devs[i].size); k230_i2c_devs[i].base = (rt_ubase_t)rt_ioremap((void *)k230_i2c_devs[i].base_pa, k230_i2c_devs[i].size);
k230_i2c_devs[i].dev.ops = &k230_i2c_ops; k230_i2c_devs[i].dev.ops = &k230_i2c_ops;
k230_i2c_devs[i].clock = sysctl_clk_get_leaf_freq(SYSCTL_CLK_I2C0_CORE + i); k230_i2c_devs[i].clock = sysctl_clk_get_leaf_freq(SYSCTL_CLK_I2C0_CORE + i);
@@ -521,6 +901,21 @@ int rt_hw_i2c_init(void)
k230_i2c_set_bus_speed(&k230_i2c_devs[i], I2C_DEFAULT_SPEED); k230_i2c_set_bus_speed(&k230_i2c_devs[i], I2C_DEFAULT_SPEED);
rt_i2c_bus_device_register(&k230_i2c_devs[i].dev, k230_i2c_devs[i].name); rt_i2c_bus_device_register(&k230_i2c_devs[i].dev, k230_i2c_devs[i].name);
LOG_I("i2c%d master mode, i2c%d clock=%dHz\n", i, i, k230_i2c_devs[i].clock); LOG_I("i2c%d master mode, i2c%d clock=%dHz\n", i, i, k230_i2c_devs[i].clock);
#ifdef BSP_USING_I2C_DMA
k230_i2c_pdma_init(&k230_i2c_devs[i]);
k230_i2c_devs[i].pdma_cfg.ch = K230_I2C_PDMA_CH_INVALID;
k230_i2c_devs[i].pdma_cfg.event = rt_event_create(k230_i2c_devs[i].name, RT_IPC_FLAG_FIFO);
if (k230_i2c_devs[i].pdma_cfg.event == RT_NULL)
{
LOG_E("i2c pdma event(%s) create failed", k230_i2c_devs[i].name);
for (int j = 0; j < i; j++)
{
rt_event_delete(k230_i2c_devs[j].pdma_cfg.event);
}
return -RT_ENOMEM;
}
#endif
} }
return RT_EOK; return RT_EOK;

View File

@@ -0,0 +1,11 @@
# RT-Thread building script for SPI component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('SPI', src, depend = ['BSP_USING_SPI'], CPPPATH = CPPPATH)
Return('group')

View File

@@ -0,0 +1,734 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 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 THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* 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.
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_spi.h"
#include <drivers/dev_spi.h>
#include <string.h>
#include "drv_gpio.h"
#include "riscv_io.h"
#include "board.h"
#include "ioremap.h"
#include "sysctl_rst.h"
#include "sysctl_clk.h"
#include "cache.h"
#define DBG_TAG "spi"
#include <rtdbg.h>
struct k230_spi_dev
{
struct rt_spi_bus dev;
void *base;
const char *name;
const char *event_name;
rt_ubase_t pa_base;
rt_uint32_t size;
rt_uint8_t idx;
rt_uint8_t rdse;
rt_uint8_t rdsd;
rt_uint8_t max_line;
rt_uint32_t max_hz;
struct rt_event event;
void *send_buf;
void *recv_buf;
rt_size_t send_length;
rt_size_t recv_length;
rt_uint8_t cell_size;
int vector;
};
static rt_err_t k230_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);
struct k230_spi_dev *qspi_bus = (struct k230_spi_dev *)device->bus;
k230_spi_reg_t *qspi_reg = (k230_spi_reg_t *)qspi_bus->base;
struct rt_qspi_device *dev = (struct rt_qspi_device *)device;
struct rt_qspi_configuration *qspi_cfg = &dev->config;
struct rt_spi_configuration *qspi_cfg_parent = &dev->config.parent;
rt_uint8_t dfs, mode, spi_ff;
rt_uint32_t max_hz, qspi_clk;
if (qspi_cfg->qspi_dl_width > qspi_bus->max_line || qspi_cfg->qspi_dl_width == 0)
{
return -RT_EINVAL;
}
if (qspi_cfg_parent->data_width < 4 || qspi_cfg_parent->data_width > 32)
{
return -RT_EINVAL;
}
/* Check if the clock frequency exceeds the hardware limits */
max_hz = qspi_cfg_parent->max_hz;
if (max_hz > qspi_bus->max_hz)
{
max_hz = qspi_bus->max_hz;
}
/* Get QSPI Controller Clock Frequency */
if (qspi_bus->idx == 0)
{
qspi_clk = sysctl_clk_get_leaf_freq(SYSCTL_CLK_SSI0);
}
else if (qspi_bus->idx == 1)
{
qspi_clk = sysctl_clk_get_leaf_freq(SYSCTL_CLK_SSI1);
}
else if (qspi_bus->idx == 2)
{
qspi_clk = sysctl_clk_get_leaf_freq(SYSCTL_CLK_SSI2);
}
else
{
return -RT_EINVAL;
}
/* Set SPI_FRF to config SPI mode*/
if (qspi_cfg->qspi_dl_width == 1)
{
spi_ff = SPI_FRF_STD_SPI;
}
else if (qspi_cfg->qspi_dl_width == 2)
{
spi_ff = SPI_FRF_DUAL_SPI;
}
else if (qspi_cfg->qspi_dl_width == 4)
{
spi_ff = SPI_FRF_QUAD_SPI;
}
else if (qspi_cfg->qspi_dl_width == 8)
{
spi_ff = SPI_FRF_OCT_SPI;
}
else
{
return -RT_EINVAL;
}
/*
* dfs: Data Frame Size, Write dfs into bits 8-9 of the register ctrlr0
* mode: SPI mode(CPOL and CPHA)Write mode into bits 0-4 of the register ctrlr0
*/
mode = qspi_cfg_parent->mode & RT_SPI_MODE_3;
dfs = qspi_cfg_parent->data_width - 1;
qspi_reg->ssienr = 0;
qspi_reg->ser = 0;
qspi_reg->baudr = qspi_clk / max_hz;
qspi_reg->rx_sample_delay = qspi_bus->rdse << 16 | qspi_bus->rdsd;
qspi_reg->axiawlen = SSIC_AXI_BLW << 8;
qspi_reg->axiarlen = SSIC_AXI_BLW << 8;
qspi_reg->ctrlr0 = (dfs) | (mode << 8) | (spi_ff << 22);
return RT_EOK;
}
static rt_ssize_t k230_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
struct k230_spi_dev *qspi_bus = (struct k230_spi_dev *)device->bus;
k230_spi_reg_t *qspi_reg = (k230_spi_reg_t *)qspi_bus->base;
struct rt_qspi_device *dev = (struct rt_qspi_device *)device;
struct rt_qspi_configuration *qspi_cfg = &dev->config;
struct rt_spi_configuration *qspi_cfg_parent = &dev->config.parent;
struct rt_qspi_message *msg = (struct rt_qspi_message *)message;
struct rt_spi_message *msg_parent = message;
/* Multi-line SPI transfers (2, 4, or 8 lines) DSPI QSPI OSPI */
if (msg->qspi_data_lines > 1)
{
rt_uint8_t trans_type = 0;
if (msg->qspi_data_lines > qspi_cfg->qspi_dl_width)
{
LOG_E("data line is invalid");
return 0;
}
/* Check other parameters */
if (qspi_cfg_parent->data_width & (msg->qspi_data_lines - 1))
{
LOG_E("data line and data width do not match");
return 0;
}
if (msg->instruction.qspi_lines != 1 && msg->instruction.qspi_lines != msg->qspi_data_lines)
{
LOG_E("instruction line is invalid");
return 0;
}
if (msg->address.size & 3 || msg->address.size > 32)
{
LOG_E("address size is invalid");
return 0;
}
if (msg->address.size && msg->address.qspi_lines != 1 && msg->address.qspi_lines != msg->qspi_data_lines)
{
LOG_E("address line is invalid");
return 0;
}
if (msg_parent->length > 0x10000)
{
LOG_E("data length is invalid, more than 0x10000");
return 0;
}
if (msg->instruction.qspi_lines != 1)
{
trans_type = 2;
}
if (msg->address.size)
{
if (msg->address.qspi_lines != 1)
{
trans_type = trans_type ? trans_type : 1;
}
else if (trans_type != 0)
{
LOG_E("instruction or address line is invalid");
return 0;
}
}
if (msg->dummy_cycles > 31)
{
LOG_E("dummy cycle is invalid");
return 0;
}
rt_uint8_t tmod = msg_parent->recv_buf ? SPI_TMOD_RO : SPI_TMOD_TO;
rt_size_t length = msg_parent->length;
rt_size_t txfthr = length > (SSIC_TX_ABW / 2) ? (SSIC_TX_ABW / 2) : length - 1;
rt_uint8_t cell_size = (qspi_cfg_parent->data_width + 7) >> 3;
rt_uint8_t *buf = RT_NULL;
/* Allocate buffer for DMA transfer */
if (length)
{
buf = rt_malloc_align(CACHE_ALIGN_TOP(length * cell_size), L1_CACHE_BYTES);
if (buf == RT_NULL)
{
LOG_E("alloc mem error");
return 0;
}
}
/* msg->address.size & ~0x03: Round address.size down to the nearest multiple of 4 and write it to ADDR_L[5:2] */
qspi_reg->spi_ctrlr0 = trans_type | (msg->address.size & ~0x03) | (0x2 << 8) | (msg->dummy_cycles << 11);
qspi_reg->ctrlr0 &= ~((3 << 22) | (3 << 10));
/* Config SPI frame format and transmission mode */
if (length)
{
qspi_reg->ctrlr0 |= (tmod << 10);
qspi_reg->txftlr = (txfthr << 16) | (SSIC_TX_ABW / 2);
qspi_reg->rxftlr = (SSIC_RX_ABW - 1);
qspi_reg->imr = (1 << 11) | (1 << 8);
qspi_reg->dmacr = (1 << 6) | (3 << 3) | (1 << 2);
qspi_reg->ctrlr1 = length - 1;
qspi_reg->spidr = msg->instruction.content;
qspi_reg->spiar = msg->address.content;
if (tmod == SPI_TMOD_TO)
{
rt_memcpy(buf, msg_parent->send_buf, length * cell_size);
rt_hw_cpu_dcache_clean(buf, CACHE_ALIGN_TOP(length * cell_size));
}
qspi_reg->axiar0 = (rt_uint32_t)((uint64_t)buf);
qspi_reg->axiar1 = (rt_uint32_t)((uint64_t)buf >> 32);
}
else
{
tmod = SPI_TMOD_TO;
qspi_reg->ctrlr0 |= (tmod << 10);
qspi_reg->txftlr = ((SSIC_TX_ABW - 1) << 16) | (SSIC_TX_ABW - 1);
qspi_reg->rxftlr = (SSIC_RX_ABW - 1);
qspi_reg->imr = 0;
qspi_reg->dmacr = 0;
}
rt_event_control(&qspi_bus->event, RT_IPC_CMD_RESET, 0);
qspi_reg->ser = 1;
qspi_reg->ssienr = 1;
rt_uint32_t event;
rt_err_t err;
/*
* Config QSPI address and instruction,
* if data is empty, unable dma and send address and instruction by write data register.
*/
if (length)
{
err = rt_event_recv(&qspi_bus->event, BIT(SSI_DONE) | BIT(SSI_AXIE),
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 1000, &event);
}
else
{
err = RT_EOK;
event = 0;
qspi_reg->dr[0] = msg->instruction.content;
length++;
if (msg->address.size)
{
qspi_reg->dr[0] = msg->address.content;
length++;
}
qspi_reg->txftlr = 0;
/* Wait for SPI transfer to complete (busy-wait) */
while ((qspi_reg->sr & 0x5) != 0x4)
{
/* Busy wait */
}
}
qspi_reg->ser = 0;
qspi_reg->ssienr = 0;
if (err == -RT_ETIMEOUT)
{
LOG_E("qspi%d transfer data timeout", qspi_bus->idx);
if (buf)
{
rt_free_align(buf);
}
return 0;
}
if (event & BIT(SSI_AXIE))
{
LOG_E("qspi%d dma error", qspi_bus->idx);
if (buf)
{
rt_free_align(buf);
}
return 0;
}
/* Read data from FIFO */
if (tmod == SPI_TMOD_RO)
{
rt_hw_cpu_dcache_invalidate(buf, CACHE_ALIGN_TOP(length * cell_size));
rt_memcpy(msg_parent->recv_buf, buf, length * cell_size);
}
if (buf)
{
rt_free_align(buf);
}
return length;
}
/* Standard SPI transfers */
else
{
if (msg_parent->length == 0)
{
return 0;
}
rt_uint8_t cell_size = (qspi_cfg_parent->data_width + 7) >> 3;
rt_size_t length = msg_parent->length;
rt_size_t count = length > 0x10000 ? 0x10000 : length;
rt_size_t send_single = 0, send_length = 0, recv_single = 0, recv_length = 0;
void *send_buf = (void *)msg_parent->send_buf;
void *recv_buf = msg_parent->recv_buf;
rt_uint8_t tmod = send_buf ? SPI_TMOD_TO : SPI_TMOD_EPROMREAD;
tmod = recv_buf ? tmod & SPI_TMOD_RO : tmod;
/* Check Qspi Parameters */
if (tmod == SPI_TMOD_EPROMREAD)
{
LOG_E("send_buf and recv_buf cannot both be empty");
return 0;
}
if (tmod == SPI_TMOD_RO && qspi_cfg_parent->data_width == 8)
{
if ((msg->address.size & 7) || (msg->dummy_cycles & 7))
{
LOG_E("instruction, address, dummy_cycles invalid");
LOG_E("For read-only mode the instruction, address, dummy_cycles must be set to zero");
LOG_E("For eeprom-read mode the instruction, address, dummy_cycles must be set to multiples of 8");
return 0;
}
else if (msg->address.size)
{
if (length > 0x10000)
{
LOG_E("For eeprom-read mode, data length cannot exceed 0x10000");
return 0;
}
tmod = SPI_TMOD_EPROMREAD;
}
}
/* Prepare the send buffer*/
if (send_buf)
{
send_single = count;
send_buf = rt_malloc(count * cell_size);
if (send_buf == RT_NULL)
{
LOG_E("alloc mem error");
return 0;
}
rt_memcpy(send_buf, msg_parent->send_buf, count * cell_size);
}
else if (tmod == SPI_TMOD_EPROMREAD)
{
send_single = 1 + msg->address.size / 8 + msg->dummy_cycles / 8;
send_buf = rt_malloc(send_single);
if (send_buf == RT_NULL)
{
LOG_E("alloc mem error");
return 0;
}
rt_uint8_t *temp = send_buf;
*temp++ = msg->instruction.content;
for (int i = msg->address.size / 8; i; i--)
{
*temp++ = msg->address.content >> ((i - 1) * 8);
}
for (int i = msg->dummy_cycles / 8; i; i--)
{
*temp++ = 0xFF;
}
}
/* Prepare the receive buffer*/
if (recv_buf)
{
recv_single = count;
recv_buf = rt_malloc(count * cell_size);
if (recv_buf == RT_NULL)
{
LOG_E("alloc mem error");
if (send_buf)
{
rt_free(send_buf);
}
return 0;
}
}
send_length = 0;
recv_length = 0;
qspi_bus->cell_size = cell_size;
qspi_bus->send_buf = send_buf;
qspi_bus->recv_buf = recv_buf;
qspi_bus->send_length = send_single;
qspi_bus->recv_length = recv_single;
qspi_reg->ctrlr0 &= ~((3 << 22) | (3 << 10));
qspi_reg->ctrlr0 |= (tmod << 10);
qspi_reg->ctrlr1 = count - 1;
qspi_reg->txftlr = ((SSIC_TX_ABW / 2) << 16) | (SSIC_TX_ABW / 2);
qspi_reg->rxftlr = count >= (SSIC_RX_ABW / 2) ? (SSIC_RX_ABW / 2 - 1) : count - 1;
qspi_reg->dmacr = 0;
/* Interrupt transmit or receive */
qspi_reg->imr = (1 << 4) | (1 << 0);
rt_event_control(&qspi_bus->event, RT_IPC_CMD_RESET, 0);
qspi_reg->ser = 1;
qspi_reg->ssienr = 1;
if (tmod == SPI_TMOD_RO)
qspi_reg->dr[0] = 0;
rt_uint32_t event;
rt_err_t err;
while (RT_TRUE)
{
/* Waiting for transfer events */
err = rt_event_recv(&qspi_bus->event, BIT(SSI_TXE) | BIT(SSI_RXF),
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 10000, &event);
if (err == -RT_ETIMEOUT)
{
LOG_E("qspi%d transfer data timeout", qspi_bus->idx);
length = 0;
if (send_buf)
{
rt_free(send_buf);
}
if (recv_buf)
{
rt_free(recv_buf);
}
return 0;
}
/* Handle Transmit buffer empty */
if (event & BIT(SSI_TXE))
{
send_length += send_single;
if (send_length < length && tmod <= SPI_TMOD_TO)
{
count = length - send_length;
count = count > 0x10000 ? 0x10000 : count;
rt_memcpy(send_buf, msg_parent->send_buf + send_length * cell_size, count * cell_size);
qspi_bus->send_buf = send_buf;
qspi_bus->send_length = count;
send_single = count;
qspi_reg->txftlr = ((SSIC_TX_ABW / 2) << 16) | (SSIC_TX_ABW / 2);
if (tmod == SPI_TMOD_TO)
qspi_reg->imr |= (1 << 0);
}
else if (tmod == SPI_TMOD_TO)
{
/* Wait for SPI transfer to complete (busy-wait) */
while ((qspi_reg->sr & 0x5) != 0x4)
{
/* Busy wait */
}
break;
}
}
/* Handle receive buffer full */
if (event & BIT(SSI_RXF))
{
rt_memcpy(msg_parent->recv_buf + recv_length * cell_size, recv_buf, recv_single * cell_size);
recv_length += recv_single;
if (recv_length >= length)
{
break;
}
count = length - recv_length;
count = count > 0x10000 ? 0x10000 : count;
qspi_bus->recv_buf = recv_buf;
qspi_bus->recv_length = count;
recv_single = count;
qspi_reg->rxftlr = count >= (SSIC_RX_ABW / 2) ? (SSIC_RX_ABW / 2 - 1) : count - 1;
if (tmod == SPI_TMOD_TR)
{
qspi_reg->imr |= (1 << 0) | (1 << 4);
}
else if (tmod == SPI_TMOD_RO)
{
qspi_reg->imr |= (1 << 4);
qspi_reg->ssienr = 0;
qspi_reg->ctrlr1 = count - 1;
qspi_reg->ssienr = 1;
/* Trigger two dummy transfers to restart SPI read in read-only mode.
* This is required by the hardware to ensure correct data reception.
*/
qspi_reg->dr[0] = 0;
qspi_reg->dr[0] = 0;
}
}
}
qspi_reg->ser = 0;
qspi_reg->ssienr = 0;
if (send_buf)
{
rt_free(send_buf);
}
if (recv_buf)
{
rt_free(recv_buf);
}
return length;
}
return 0;
}
static const struct rt_spi_ops k230_qspi_ops =
{
.configure = k230_spi_configure,
.xfer = k230_spi_xfer,
};
static void k230_spi_irq(int vector, void *param)
{
struct k230_spi_dev *qspi_bus = param;
k230_spi_reg_t *qspi_reg = (k230_spi_reg_t *)qspi_bus->base;
vector -= IRQN_SPI0;
vector %= (IRQN_SPI1 - IRQN_SPI0);
/* Handle transmit buffer empty interrupt */
if (vector == SSI_TXE)
{
if (qspi_bus->send_buf == RT_NULL)
{
qspi_reg->imr &= ~1;
}
else if (qspi_bus->cell_size == 1)
{
while ((qspi_bus->send_length) && (qspi_reg->sr & 2))
{
qspi_reg->dr[0] = *((rt_uint8_t *)qspi_bus->send_buf);
qspi_bus->send_buf++;
qspi_bus->send_length--;
}
}
else if (qspi_bus->cell_size == 2)
{
while ((qspi_bus->send_length) && (qspi_reg->sr & 2))
{
qspi_reg->dr[0] = *((rt_uint16_t *)qspi_bus->send_buf);
qspi_bus->send_buf += 2;
qspi_bus->send_length--;
}
}
else if (qspi_bus->cell_size == 4)
{
while ((qspi_bus->send_length) && (qspi_reg->sr & 2))
{
qspi_reg->dr[0] = *((rt_uint32_t *)qspi_bus->send_buf);
qspi_bus->send_buf += 4;
qspi_bus->send_length--;
}
}
else
{
LOG_E("qspi%d datawidth error", qspi_bus->idx);
}
if (qspi_bus->send_length == 0)
{
if (((qspi_reg->ctrlr0 >> 10) & SPI_TMOD_EPROMREAD) == SPI_TMOD_TO)
{
if (qspi_reg->txftlr)
return;
}
qspi_reg->txftlr = 0;
qspi_reg->imr &= ~1;
rt_event_send(&qspi_bus->event, BIT(SSI_TXE));
}
}
/* Handle receive buffer full interrupt */
else if (vector == SSI_RXF)
{
if (qspi_bus->recv_buf == RT_NULL)
{
qspi_reg->imr &= ~0x10;
}
else if (qspi_bus->cell_size == 1)
{
while ((qspi_bus->recv_length) && (qspi_reg->sr & 8))
{
*((rt_uint8_t *)qspi_bus->recv_buf) = qspi_reg->dr[0];
qspi_bus->recv_buf++;
qspi_bus->recv_length--;
}
}
else if (qspi_bus->cell_size == 2)
{
while ((qspi_bus->recv_length) && (qspi_reg->sr & 8))
{
*((rt_uint16_t *)qspi_bus->recv_buf) = qspi_reg->dr[0];
qspi_bus->recv_buf += 2;
qspi_bus->recv_length--;
}
}
else if (qspi_bus->cell_size == 4)
{
while ((qspi_bus->recv_length) && (qspi_reg->sr & 8))
{
*((rt_uint32_t *)qspi_bus->recv_buf) = qspi_reg->dr[0];
qspi_bus->recv_buf += 4;
qspi_bus->recv_length--;
}
}
else
{
LOG_E("qspi%d datawidth error", qspi_bus->idx);
}
if (qspi_bus->recv_length == 0)
{
qspi_reg->imr &= ~0x10;
rt_event_send(&qspi_bus->event, BIT(SSI_RXF));
}
else if (qspi_bus->recv_length <= qspi_reg->rxftlr)
{
qspi_reg->rxftlr = qspi_bus->recv_length - 1;
}
}
/* Handle transfer complete interrupt */
else if (vector == SSI_DONE)
{
/* Clear transfer done interrupt by reading donecr register */
(void)qspi_reg->donecr;
rt_event_send(&qspi_bus->event, BIT(SSI_DONE));
}
/* Handle DMA error interrupt */
else if (vector == SSI_AXIE)
{
/* Clear AXI error interrupt by reading axiecr register */
(void)qspi_reg->axiecr;
rt_event_send(&qspi_bus->event, BIT(SSI_AXIE));
}
}
static struct k230_spi_dev k230_spi_devs[] =
{
#ifdef BSP_USING_SPI0
{
.name = "spi0",
.event_name = "spi0_event",
.pa_base = SPI_OPI_BASE_ADDR,
.size = SPI_OPI_IO_SIZE,
.vector = IRQN_SPI0,
.idx = 0,
.rdse = 0,
.rdsd = 0,
.max_line = 8,
.max_hz = 200000000,
},
#endif
#ifdef BSP_USING_SPI1
{
.name = "spi1",
.event_name = "spi1_event",
.pa_base = SPI_QOPI_BASE_ADDR,
.size = SPI_QOPI_IO_SIZE / 2,
.vector = IRQN_SPI1,
.idx = 1,
.rdse = 0,
.rdsd = 0,
.max_line = 4,
.max_hz = 100000000,
},
#endif
#ifdef BSP_USING_SPI2
{
.name = "spi2",
.event_name = "spi2_event",
.pa_base = SPI_QOPI_BASE_ADDR + SPI_QOPI_IO_SIZE / 2,
.size = SPI_QOPI_IO_SIZE / 2,
.vector = IRQN_SPI2,
.idx = 2,
.rdse = 0,
.rdsd = 0,
.max_line = 4,
.max_hz = 100000000,
},
#endif
};
int rt_hw_qspi_bus_init(void)
{
rt_err_t ret;
int i;
for (i = 0; i < sizeof(k230_spi_devs) / sizeof(k230_spi_devs[0]); i++)
{
k230_spi_devs[i].base = rt_ioremap((void *)k230_spi_devs[i].pa_base, k230_spi_devs[i].size);
ret = rt_qspi_bus_register(&k230_spi_devs[i].dev, k230_spi_devs[i].name, &k230_qspi_ops);
if (ret)
{
LOG_E("%s register fail", k230_spi_devs[i].name);
return ret;
}
rt_event_init(&k230_spi_devs[i].event, k230_spi_devs[i].event_name, RT_IPC_FLAG_PRIO);
rt_hw_interrupt_install(k230_spi_devs[i].vector + SSI_TXE, k230_spi_irq, &k230_spi_devs[i], k230_spi_devs[i].name);
rt_hw_interrupt_umask(k230_spi_devs[i].vector + SSI_TXE);
rt_hw_interrupt_install(k230_spi_devs[i].vector + SSI_RXF, k230_spi_irq, &k230_spi_devs[i], k230_spi_devs[i].name);
rt_hw_interrupt_umask(k230_spi_devs[i].vector + SSI_RXF);
rt_hw_interrupt_install(k230_spi_devs[i].vector + SSI_DONE, k230_spi_irq, &k230_spi_devs[i], k230_spi_devs[i].name);
rt_hw_interrupt_umask(k230_spi_devs[i].vector + SSI_DONE);
rt_hw_interrupt_install(k230_spi_devs[i].vector + SSI_AXIE, k230_spi_irq, &k230_spi_devs[i], k230_spi_devs[i].name);
rt_hw_interrupt_umask(k230_spi_devs[i].vector + SSI_AXIE);
}
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_qspi_bus_init);

View File

@@ -0,0 +1,203 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 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 THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* 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.
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DRV_SPI_H__
#define __DRV_SPI_H__
#include <stdint.h>
#include <stdbool.h>
#define SSIC_HAS_DMA 2
#define SSIC_AXI_BLW 8
#define SSIC_TX_ABW 256
#define SSIC_RX_ABW 256
#define IRQN_SPI0 146
#define IRQN_SPI1 155
#define IRQN_SPI2 164
#ifndef L1_CACHE_BYTES
#define L1_CACHE_BYTES 64
#endif
#define CACHE_ALIGN_TOP(x) (((x) + L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES - 1))
#define CACHE_ALIGN_BOTTOM(x) ((x) & ~(L1_CACHE_BYTES - 1))
#define BIT(n) (1UL << (n))
enum
{
SSI_TXE = 0,
SSI_TXO,
SSI_RXF,
SSI_RXO,
SSI_TXU,
SSI_RXU,
SSI_MST,
SSI_DONE,
SSI_AXIE,
};
/* SPI mode */
enum
{
SPI_FRF_STD_SPI,
SPI_FRF_DUAL_SPI,
SPI_FRF_QUAD_SPI,
SPI_FRF_OCT_SPI,
};
/* SPI transmit mode */
enum
{
SPI_TMOD_TR,
SPI_TMOD_TO,
SPI_TMOD_RO,
SPI_TMOD_EPROMREAD,
};
/* Qspi register */
typedef struct
{
/* SPI Control Register 0 (0x00)*/
volatile uint32_t ctrlr0;
/* SPI Control Register 1 (0x04)*/
volatile uint32_t ctrlr1;
/* SPI Enable Register (0x08)*/
volatile uint32_t ssienr;
/* SPI Microwire Control Register (0x0c)*/
volatile uint32_t mwcr;
/* SPI Slave Enable Register (0x10)*/
volatile uint32_t ser;
/* SPI Baud Rate Select (0x14)*/
volatile uint32_t baudr;
/* SPI Transmit FIFO Threshold Level (0x18)*/
volatile uint32_t txftlr;
/* SPI Receive FIFO Threshold Level (0x1c)*/
volatile uint32_t rxftlr;
/* SPI Transmit FIFO Level Register (0x20)*/
volatile uint32_t txflr;
/* SPI Receive FIFO Level Register (0x24)*/
volatile uint32_t rxflr;
/* SPI Status Register (0x28)*/
volatile uint32_t sr;
/* SPI Interrupt Mask Register (0x2c)*/
volatile uint32_t imr;
/* SPI Interrupt Status Register (0x30)*/
volatile uint32_t isr;
/* SPI Raw Interrupt Status Register (0x34)*/
volatile uint32_t risr;
/* SPI Transmit FIFO Underflow Interrupt Clear Register (0x38)*/
volatile uint32_t txeicr;
/* SPI Receive FIFO Overflow Interrupt Clear Register (0x3c)*/
volatile uint32_t rxoicr;
/* SPI Receive FIFO Underflow Interrupt Clear Register (0x40)*/
volatile uint32_t rxuicr;
/* SPI Multi-Master Interrupt Clear Register (0x44)*/
volatile uint32_t msticr;
/* SPI Interrupt Clear Register (0x48)*/
volatile uint32_t icr;
/* SPI DMA Control Register (0x4c)*/
volatile uint32_t dmacr;
#if SSIC_HAS_DMA == 1
/* SPI DMA Transmit Data Level (0x50)*/
volatile uint32_t dmatdlr;
/* SPI DMA Receive Data Level (0x54)*/
volatile uint32_t dmardlr;
#elif SSIC_HAS_DMA == 2
/* SPI Destination Burst Length (0x50)*/
volatile uint32_t axiawlen;
/* SPI Source Burst Length (0x54)*/
volatile uint32_t axiarlen;
#else
uint32_t resv0[2];
#endif
/* SPI Identification Register (0x58)*/
volatile const uint32_t idr;
/* SPI DWC_ssi component version (0x5c)*/
volatile uint32_t ssic_version_id;
/* SPI Data Register 0-36 (0x60 -- 0xec)*/
volatile uint32_t dr[36];
/* SPI RX Sample Delay Register (0xf0)*/
volatile uint32_t rx_sample_delay;
/* SPI SPI Control Register (0xf4)*/
volatile uint32_t spi_ctrlr0;
/* SPI Transmit Drive Edge Register (0xf8)*/
volatile uint32_t ddr_drive_edge;
/* SPI XIP Mode bits (0xfc)*/
volatile uint32_t xip_mode_bits;
/* SPI XIP INCR transfer opcode (0x100)*/
volatile uint32_t xip_incr_inst;
/* SPI XIP WRAP transfer opcode (0x104)*/
volatile uint32_t xip_wrap_inst;
#if SSIC_CONCURRENT_XIP_EN
/* SPI XIP Control Register (0x108)*/
volatile uint32_t xip_ctrl;
/* SPI XIP Slave Enable Register (0x10c)*/
volatile uint32_t xip_ser;
/* SPI XIP Receive FIFO Overflow Interrupt Clear Register (0x110)*/
volatile uint32_t xrxoicr;
/* SPI XIP time out register for continuous transfers (0x114)*/
volatile uint32_t xip_cnt_time_out;
/* not support dyn ws (0x118)*/
uint32_t resv1[1];
/* SPI Transmit Error Interrupt Clear Register (0x11c)*/
volatile uint32_t spitecr;
#else
uint32_t resv1[6];
#endif
#if SSIC_HAS_DMA == 2
/* SPI Device Register (0x120)*/
volatile uint32_t spidr;
/* SPI Device Address Register (0x124)*/
volatile uint32_t spiar;
/* AXI Address Register 0 (0x128)*/
volatile uint32_t axiar0;
/* AXI Address Register 1 (0x12c)*/
volatile uint32_t axiar1;
/* AXI Master Error Interrupt Clear Register (0x130)*/
volatile uint32_t axiecr;
/* Transfer Done Clear Interrupt Clear Register (0x134)*/
volatile uint32_t donecr;
#endif
/* This register will not be used and is reserved. (0x138 ~ 0x13c)*/
uint32_t resv3[2];
#if SSIC_XIP_WRITE_REG_EN
/* XIP_WRITE_INCR_INST - XIP Write INCR transfer opcode (0x140)*/
volatile uint32_t xip_write_incr_inst;
/* XIP_WRITE_WRAP_INST - XIP Write WRAP transfer opcode (0x144)*/
volatile uint32_t xip_write_wrap_inst;
/* XIP_WRITE_CTRL - XIP Write Control Register (0x148)*/
volatile uint32_t xip_write_ctrl;
#else
uint32_t resv4[3];
#endif
// volatile uint32_t endian;
} __attribute__((packed, aligned(4))) k230_spi_reg_t;
#endif

View File

@@ -33,6 +33,9 @@ if GetDepend('BSP_UTEST_DRIVERS'):
if GetDepend('BSP_USING_I2C'): if GetDepend('BSP_USING_I2C'):
src += ['test_i2c.c'] src += ['test_i2c.c']
if GetDepend('BSP_USING_SPI'):
src += ['test_spi.c']
group = DefineGroup('utestcases', src, depend = ['']) group = DefineGroup('utestcases', src, depend = [''])
Return('group') Return('group')

View File

@@ -48,7 +48,15 @@
* 1. 测试I2C0主机模式 * 1. 测试I2C0主机模式
* 主机模式下主机向从机发送16字节数据不包括写读地址 * 主机模式下主机向从机发送16字节数据不包括写读地址
* 然后再读取回来进行校验共执行两次分别是400kHz和1MHz速率。 * 然后再读取回来进行校验共执行两次分别是400kHz和1MHz速率。
* 使用的从机为AT24C08 EEPROM设备地址为0x50。 * 第一次写数据时带一字节地址总共写16字节数据读取15字节数据
* 第二次写数据时带一字节地址总共写17字节数据读取16字节数据。
* 在两次写数据的过程中如果开启dma功能第一次会调用dma进行写
* 第二次会调用dma进行读。前提是BSP_USING_I2C_DMA宏被定义
* 因为pdma要求地址与数据都要4字节对齐地址的对齐问题会在驱动
* 内部处理),若写/读数据大小非4字节对齐即使启用了dma功能
* 实际也是调用的cpu轮询读写这一点需要应用程序注意并处理
* 注使用的从机为AT24C08 EEPROM设备地址为0x50
* page size 为 16 字节。
*/ */
#define I2C_NAME "i2c0" #define I2C_NAME "i2c0"
@@ -160,6 +168,7 @@ static void _test_i2c0_master(rt_uint8_t *buffer_w, rt_uint8_t *buffer_r, rt_uin
{ {
LOG_I("0x%02X ", buffer_r[i]); LOG_I("0x%02X ", buffer_r[i]);
} }
uassert_buf_equal(buffer_w + 1, buffer_r + 1, size); uassert_buf_equal(buffer_w + 1, buffer_r + 1, size);
} }
@@ -174,13 +183,15 @@ static void test_i2c0_master(void)
buffer_w[0] = 0x00; // memory address buffer_w[0] = 0x00; // memory address
memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1); memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1);
_test_i2c0_master(buffer_w, buffer_r, size, speed); /* if BSP_USING_I2C_DMA is enabled, test i2c write with dma */
_test_i2c0_master(buffer_w, buffer_r, size - 1, speed);
speed = 1000000; // 1MHz speed = 1000000; // 1MHz
memset(buffer_w + 1, 0x55, TEST_BUFFER_SIZE); memset(buffer_w + 1, 0x55, TEST_BUFFER_SIZE);
buffer_w[0] = 0x00; // memory address buffer_w[0] = 0x00; // memory address
memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1); memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1);
/* if BSP_USING_I2C_DMA is enabled, test i2c read with dma */
_test_i2c0_master(buffer_w, buffer_r, size, speed); _test_i2c0_master(buffer_w, buffer_r, size, speed);
} }

View File

@@ -0,0 +1,222 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 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 THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* 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.
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <rtdbg.h>
#include <utest.h>
#include "drv_spi.h"
#include <string.h>
#include "drv_pinctrl.h"
#include "drv_gpio.h"
/*
* 测试 SPI0 在标准SPI模式下的数据发送功能
*
* 功能说明:
* - 查找名为 "spi0" 的SPI总线设备
* - 挂载SPI设备到总线
* - 配置SPI设备参数
* - 模式标准SPI模式0 (RT_SPI_MODE_0)
* - 数据位8位
* - 最大频率1MHz
* - 数据线宽度1标准SPI
* - 准备测试数据(递增序列);
* - 创建SPI消息并发送16字节数据
* - 发送完成接收从机的16字节数据
* - 发送完成后卸载SPI设备。
*
* 硬件说明:
* - 本测试基于 K230 平台;
* - 测试SPI0(OSPI)的标准SPI模式TX和RX功能,使用硬件CS
* - 对应的引脚配置为:
* - CS: GPIO14
* - CLK: GPIO15
* - D0: GPIO16
* - D1: GPIO17
* - 需要连接SPI从设备如SPI调试器等来验证数据传输本测试文件使用一块stm32制作的SPI调试器
* - 如果没有实际从设备可以使用逻辑分析仪或示波器观察SPI波形(但是只能验证TX功能,接收到会是16bit的0xff)
*/
#define SPI0_BUS_NAME "spi0"
#define SPI0_DEV_NAME0 "spi00"
#define TEST_DATA_LENGTH 16
#define SPI0_CS_PIN 14
#define SPI0_CLK_PIN 15
#define SPI0_D0_PIN 16
#define SPI0_D1_PIN 17
#define SPI0_CS_PIN_AF IOMUX_FUNC2
#define SPI0_CLK_PIN_AF IOMUX_FUNC2
#define SPI0_D0_PIN_AF IOMUX_FUNC2
#define SPI0_D1_PIN_AF IOMUX_FUNC2
static void spi_gpio_init(void)
{
LOG_I("SPI demo: initializing SPI0 GPIO...");
k230_pinctrl_set_function(SPI0_CS_PIN, SPI0_CS_PIN_AF);
k230_pinctrl_set_function(SPI0_CLK_PIN, SPI0_CLK_PIN_AF);
k230_pinctrl_set_function(SPI0_D0_PIN, SPI0_D0_PIN_AF);
k230_pinctrl_set_function(SPI0_D1_PIN, SPI0_D1_PIN_AF);
k230_pinctrl_set_oe(SPI0_CS_PIN, 1);
k230_pinctrl_set_oe(SPI0_CLK_PIN, 1);
k230_pinctrl_set_oe(SPI0_D0_PIN, 1);
k230_pinctrl_set_oe(SPI0_D1_PIN, 1);
k230_pinctrl_set_ie(SPI0_CS_PIN, 1);
k230_pinctrl_set_ie(SPI0_CLK_PIN, 1);
k230_pinctrl_set_ie(SPI0_D0_PIN, 1);
k230_pinctrl_set_ie(SPI0_D1_PIN, 1);
}
static void spi_device_demo(void)
{
struct rt_qspi_device *qspi_dev;
LOG_I("Using rt_qspi_device to transmit");
rt_err_t ret;
uint8_t tx_data[TEST_DATA_LENGTH];
uint8_t rx_data[TEST_DATA_LENGTH];
for (int i = 0; i < TEST_DATA_LENGTH; i++)
{
tx_data[i] = i;
}
rt_memset(rx_data, 0, sizeof(rx_data));
/* Find QSPI Bus */
struct rt_spi_bus *spi_bus = (struct rt_spi_bus *)rt_device_find(SPI0_BUS_NAME);
if (!spi_bus)
{
LOG_E("Failed to find SPI bus: %s", SPI0_BUS_NAME);
return;
}
LOG_I("Success to find SPI bus: %s", SPI0_BUS_NAME);
qspi_dev = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
if (!qspi_dev)
{
LOG_E("Failed to allocate SPI device memory");
return;
}
LOG_I("Success to allocate QSPI device memory");
/* Attach SPI Device */
ret = rt_spi_bus_attach_device(&(qspi_dev->parent), SPI0_DEV_NAME0, SPI0_BUS_NAME, RT_NULL);
if (ret != RT_EOK)
{
LOG_E("Failed to attach SPI device: %d", ret);
rt_free(qspi_dev);
return;
}
LOG_I("SPI device attached successfully");
/* SPI Device Config*/
struct rt_qspi_configuration qspi_cfg;
qspi_cfg.parent.mode = RT_SPI_MODE_0 | RT_SPI_MSB;
qspi_cfg.parent.data_width = 8;
qspi_cfg.parent.max_hz = 1000000;
qspi_cfg.parent.reserved = 0;
qspi_cfg.qspi_dl_width = 1;
qspi_cfg.medium_size = 0;
qspi_cfg.ddr_mode = 0;
ret = rt_qspi_configure(qspi_dev, &qspi_cfg);
if (ret != RT_EOK)
{
LOG_E("SPI configuration failed: %d", ret);
rt_free(qspi_dev);
return;
}
LOG_I("SPI configuration: Standard SPI, mode=0, data_width=8, max_hz=%d, data_lines=%d",
qspi_cfg.parent.max_hz, qspi_cfg.qspi_dl_width);
LOG_I("Sending test data (length=%d):", TEST_DATA_LENGTH);
for (int i = 0; i < TEST_DATA_LENGTH; i++)
{
rt_kprintf("%02X ", tx_data[i]);
}
rt_kprintf("\n");
/* Create SPI Message */
struct rt_qspi_message msg;
rt_memset(&msg, 0, sizeof(msg));
/*Using Standard SPI*/
msg.instruction.content = 0;
msg.instruction.qspi_lines = 1;
msg.address.content = 0;
msg.address.size = 0;
msg.address.qspi_lines = 1;
msg.qspi_data_lines = 1;
msg.dummy_cycles = 0;
/* SPI Message Config */
msg.parent.send_buf = tx_data;
msg.parent.recv_buf = rx_data;
msg.parent.length = TEST_DATA_LENGTH;
msg.parent.cs_take = 1;
msg.parent.cs_release = 1;
msg.parent.next = RT_NULL;
/* Transfer Data */
ret = rt_qspi_transfer_message(qspi_dev, &msg);
if (ret != TEST_DATA_LENGTH)
{
LOG_E("SPI transfer failed, returned: %d", ret);
}
uassert_int_equal(ret, TEST_DATA_LENGTH);
LOG_I("SPI TX demo: sent %d bytes successfully", ret);
LOG_I("Received data from slave (length=%d):", TEST_DATA_LENGTH);
for (int i = 0; i < TEST_DATA_LENGTH; i++)
{
rt_kprintf("%02X ", rx_data[i]);
}
rt_kprintf("\n");
/* Detach SPI Device */
ret = rt_spi_bus_detach_device(&(qspi_dev->parent));
uassert_int_equal(ret, RT_EOK);
rt_free(qspi_dev);
}
static void testcase(void)
{
UTEST_UNIT_RUN(spi_gpio_init);
UTEST_UNIT_RUN(spi_device_demo);
}
static rt_err_t utest_tc_init(void)
{
LOG_I("SPI test case initialization");
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
LOG_I("SPI test case cleanup");
return RT_EOK;
}
UTEST_TC_EXPORT(testcase, "bsp.k230.drivers.spi", utest_tc_init, utest_tc_cleanup, 10);

View File

@@ -2,6 +2,5 @@
# If you need to exclude an entire folder, add the folder path in dir_path; # If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path. # If you need to exclude a file, add the path to the file in file_path.
dir_path: # 从 .ignore_format.yml 迁移的规则
- CMSIS /sam*/bsp/
- VangoV85xx_standard_peripheral

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- bsp

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- bsp

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- bsp

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- bsp

View File

@@ -1,7 +1,7 @@
# files format check exclude path, please follow the instructions below to modify; # files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path; # If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path. # If you need to exclude a file, add the path to the file in file_path.
dir_path: # 从 .ignore_format.yml 迁移的规则
- Libraries/N32_Std_Driver /Libraries/

View File

@@ -1,4 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
dir_path:
- Libraries

View File

@@ -1,9 +1,7 @@
# files format check exclude path, please follow the instructions below to modify; # files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path; # If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path. # If you need to exclude a file, add the path to the file in file_path.
file_path: # 从 .ignore_format.yml 迁移的规则
/Libraries/
dir_path:
- Libraries

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- Libraries

View File

@@ -1,6 +1,7 @@
# files format check exclude path, please follow the instructions below to modify; # files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path; # If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path. # If you need to exclude a file, add the path to the file in file_path.
dir_path: # 从 .ignore_format.yml 迁移的规则
- bsp /Libraries/

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- Libraries

View File

@@ -2,6 +2,5 @@
# If you need to exclude an entire folder, add the folder path in dir_path; # If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path. # If you need to exclude a file, add the path to the file in file_path.
dir_path: # 从 .ignore_format.yml 迁移的规则
- CMSIS /Libraries/
- VangoV85xxP_standard_peripheral

View File

@@ -2,5 +2,5 @@
# If you need to exclude an entire folder, add the folder path in dir_path; # If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path. # If you need to exclude a file, add the path to the file in file_path.
dir_path: # 从 .ignore_format.yml 迁移的规则
- bsp /Libraries/

View File

@@ -0,0 +1,7 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
# 从 .ignore_format.yml 迁移的规则
/libraries/N32G45x_Firmware_Library/

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- N32G45x_Firmware_Library

View File

@@ -0,0 +1,7 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
# 从 .ignore_format.yml 迁移的规则
/Libraries/N32_Std_Driver/

View File

@@ -0,0 +1,17 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
# 从 .ignore_format.yml 迁移的规则
/imx/imxrt/imxrt1060-nxp-evk/board/board.c/
/imx/imxrt/imxrt1060-nxp-evk/board/MCUX_Config/
/imx/imxrt/imxrt1060-nxp-evk/xip/
/imx/imxrt/libraries/MIMXRT1060/
/lpc/lpc55sxx/Libraries/LPC55*/
/mcx/mcxa/Libraries/MCXA153/
/mcx/mcxc/Libraries/MCXC444/
/mcx/mcxn/Libraries/MCXN947/

View File

@@ -0,0 +1,10 @@
# .clang-format-ignore File Description:
# ----------------------------------------------------------------------------------------
# 1. Used to specify which files or directories should be skipped by the clang-format tool.
# 2. Follows syntax rules similar to .gitignore.
# 3. Supports wildcard patterns and path matching.
# 4. clang-format will recursively apply the .clang-format-ignore rules.
# NXP imxrt1060-nxp-evk library
/board/MCUX_Config/
/xip/

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
dir_path:
- board/board.c
- board/MCUX_Config
- xip

View File

@@ -1,4 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
dir_path:
- MIMXRT1060

View File

@@ -18,10 +18,6 @@
#include <shell.h> #include <shell.h>
#endif #endif
#ifdef RT_USING_VBUS
#include <vbus.h>
#endif
/* thread phase init */ /* thread phase init */
void rt_init_thread_entry(void *parameter) void rt_init_thread_entry(void *parameter)
{ {
@@ -32,10 +28,6 @@ void rt_init_thread_entry(void *parameter)
finsh_set_device(RT_CONSOLE_DEVICE_NAME); finsh_set_device(RT_CONSOLE_DEVICE_NAME);
#endif #endif
#endif #endif
#ifdef RT_USING_VBUS
rt_vbus_do_init();
#endif
} }
/*the led thread*/ /*the led thread*/
@@ -45,8 +37,6 @@ static struct rt_thread led_thread;
static void led_thread_entry(void *parameter) static void led_thread_entry(void *parameter)
{ {
rt_device_t led_dev; rt_device_t led_dev;
rt_device_t vbus_dev;
rt_err_t err;
rt_led_hw_init(); rt_led_hw_init();
@@ -57,32 +47,14 @@ static void led_thread_entry(void *parameter)
return; return;
} }
vbus_dev = rt_device_find("vecho");
if (vbus_dev == RT_NULL)
{
rt_kprintf("can not find the vbus device\n");
return;
}
err = rt_device_open(vbus_dev, RT_DEVICE_OFLAG_RDWR);
if (err != RT_EOK)
{
rt_kprintf("open vbus failed: %d\n", err);
return;
}
while (1) while (1)
{ {
rt_uint8_t led_value; rt_uint8_t led_value = 1;
int len;
len = rt_device_read(vbus_dev, 0, &led_value, sizeof(led_value));
if (len <= 0)
{
rt_kprintf("vbus read err: %d, %d\n", len, rt_get_errno());
}
led_dev->write(led_dev, 1, &led_value, sizeof(led_value)); led_dev->write(led_dev, 1, &led_value, sizeof(led_value));
rt_thread_delay(500);
led_value = 0;
led_dev->write(led_dev, 1, &led_value, sizeof(led_value));
rt_thread_delay(500);
} }
} }

View File

@@ -50,6 +50,5 @@ extern int __bss_end;
void rt_hw_board_init(void); void rt_hw_board_init(void);
int rt_hw_board_heap_init(void); int rt_hw_board_heap_init(void);
int rt_vbus_do_init(void);
#endif #endif

View File

@@ -1,13 +0,0 @@
#ifndef __VBUS_CONF_H__
#define __VBUS_CONF_H__
/* Number of blocks in VBus. The total size of VBus is
* RT_VMM_RB_BLK_NR * 64byte * 2. */
#define RT_VMM_RB_BLK_NR 20
/* We don't use the IRQ number to trigger IRQ in this BSP. */
#define RT_VBUS_GUEST_VIRQ 0
#define RT_VBUS_HOST_VIRQ 0
#endif /* end of include guard: __VBUS_CONF_H__ */

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-07 Grissiom add comment
*/
#include <rtthread.h>
#ifdef RT_USING_VBUS
#include <rtdevice.h>
#include <vbus.h>
#include <board.h>
struct rt_vbus_ring rt_vbus_rings[2] rt_section("vbus_ring");
int rt_vbus_do_init(void)
{
return rt_vbus_init(&rt_vbus_rings[1], &rt_vbus_rings[0]);
}
INIT_COMPONENT_EXPORT(rt_vbus_do_init);
int rt_vbus_hw_init(void)
{
NVIC_ClearPendingIRQ(M0_M4CORE_IRQn);
NVIC_EnableIRQ(M0_M4CORE_IRQn);
return 0;
}
void M4CORE_IRQHandler(void)
{
LPC_CREG->M4TXEVENT = 0;
rt_vbus_isr(M0_M4CORE_IRQn, RT_NULL);
}
int rt_vbus_hw_eoi(int irqnr, void *param)
{
/* Nothing to do here as we cleared the interrupt in IRQHandler. */
return 0;
}
struct rt_vbus_dev rt_vbus_chn_devx[] = {
{
.req =
{
.prio = 30,
.name = "vecho",
.is_server = 0,
.recv_wm.low = RT_VMM_RB_BLK_NR / 3,
.recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
.post_wm.low = RT_VMM_RB_BLK_NR / 3,
.post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
}
},
{
.req =
{
.name = RT_NULL,
}
},
};
#endif /* RT_USING_VBUS */

View File

@@ -1,40 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-07 Grissiom init commit
*/
#ifndef __VBUS_HW_H__
#define __VBUS_HW_H__
#include <rtthread.h>
#include <board.h>
rt_inline void rt_vbus_tick(unsigned int target_cpu, unsigned int irqnr)
{
__SEV();
}
/* Read memory barrier. */
rt_inline void rt_vbus_smp_rmb(void)
{
__DMB();
}
/* Write memory barrier. */
rt_inline void rt_vbus_smp_wmb(void)
{
__DSB();
}
/* General memory barrier. */
rt_inline void rt_vbus_smp_mb(void)
{
__DSB();
}
#endif /* __VBUS_HW_H__ */

View File

@@ -220,9 +220,6 @@
#define RT_LWIP_MSKADDR3 0 #define RT_LWIP_MSKADDR3 0
// </section> // </section>
#define RT_USING_VBUS
#define _RT_VBUS_RING_SZ 64
#define RT_VBUS_GUEST_VIRQ 0
// </RDTConfigurator> // </RDTConfigurator>

View File

@@ -1,8 +0,0 @@
#ifndef __VBUS_LOCAL_CONF_H__
#define __VBUS_LOCAL_CONF_H__
#define RT_VBUS_USING_FLOW_CONTROL
#define RT_VBUS_USING_TESTS
#endif /* end of include guard: __VBUS_LOCAL_CONF_H__ */

View File

@@ -18,10 +18,6 @@
#include <shell.h> #include <shell.h>
#endif #endif
#ifdef RT_USING_VBUS
#include <vbus.h>
#endif
static const unsigned char _M0_CODE[] rt_section("M0_CODE") = { static const unsigned char _M0_CODE[] rt_section("M0_CODE") = {
// #include "M0_CODE.h" // #include "M0_CODE.h"
}; };
@@ -64,10 +60,6 @@ void rt_init_thread_entry(void *parameter)
#endif #endif
#endif #endif
#ifdef RT_USING_VBUS
rt_vbus_do_init();
#endif
_boot_M0(); _boot_M0();
} }
@@ -79,8 +71,6 @@ static void led_thread_entry(void *parameter)
{ {
rt_uint8_t led_value; rt_uint8_t led_value;
rt_device_t led_dev; rt_device_t led_dev;
rt_device_t vbus_dev;
rt_err_t err;
rt_led_hw_init(); rt_led_hw_init();
@@ -91,34 +81,11 @@ static void led_thread_entry(void *parameter)
return; return;
} }
vbus_dev = rt_device_find("vecho");
if (vbus_dev == RT_NULL)
{
rt_kprintf("can not find the vbus device\n");
return;
}
err = rt_device_open(vbus_dev, RT_DEVICE_OFLAG_RDWR);
if (err != RT_EOK)
{
rt_kprintf("open vbus failed: %d\n", err);
return;
}
led_value = 0; led_value = 0;
while (1) while (1)
{ {
int len;
led_dev->write(led_dev, 0, &led_value, sizeof(led_value)); led_dev->write(led_dev, 0, &led_value, sizeof(led_value));
led_value = !led_value; led_value = !led_value;
len = rt_device_write(vbus_dev, 0, &led_value, sizeof(led_value));
if (len <= 0)
{
rt_kprintf("vbus write err: %d, %d\n", len, rt_get_errno());
}
rt_thread_delay(1000); rt_thread_delay(1000);
} }
} }

View File

@@ -50,6 +50,5 @@ extern int __bss_end;
void rt_hw_board_init(void); void rt_hw_board_init(void);
int rt_hw_board_heap_init(void); int rt_hw_board_heap_init(void);
int rt_vbus_do_init(void);
#endif #endif

View File

@@ -1,13 +0,0 @@
#ifndef __VBUS_CONF_H__
#define __VBUS_CONF_H__
/* Number of blocks in VBus. The total size of VBus is
* RT_VMM_RB_BLK_NR * 64byte * 2. */
#define RT_VMM_RB_BLK_NR 20
/* We don't use the IRQ number to trigger IRQ in this BSP. */
#define RT_VBUS_GUEST_VIRQ 0
#define RT_VBUS_HOST_VIRQ 0
#endif /* end of include guard: __VBUS_CONF_H__ */

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-07 Grissiom add comment
*/
#include <rtthread.h>
#ifdef RT_USING_VBUS
#include <rtdevice.h>
#include <vbus.h>
#include <board.h>
struct rt_vbus_ring rt_vbus_rings[2] rt_section("vbus_ring");
int rt_vbus_do_init(void)
{
return rt_vbus_init(&rt_vbus_rings[0], &rt_vbus_rings[1]);
}
INIT_COMPONENT_EXPORT(rt_vbus_do_init);
int rt_vbus_hw_init(void)
{
NVIC_ClearPendingIRQ(M0CORE_IRQn);
NVIC_EnableIRQ(M0CORE_IRQn);
return 0;
}
void M0CORE_IRQHandler(void)
{
LPC_CREG->M0TXEVENT = 0;
rt_vbus_isr(M0CORE_IRQn, RT_NULL);
}
int rt_vbus_hw_eoi(int irqnr, void *param)
{
/* Nothing to do here as we cleared the interrupt in IRQHandler. */
return 0;
}
struct rt_vbus_dev rt_vbus_chn_devx[] = {
{
.req =
{
.prio = 30,
.name = "vecho",
.is_server = 1,
.recv_wm.low = RT_VMM_RB_BLK_NR / 3,
.recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
.post_wm.low = RT_VMM_RB_BLK_NR / 3,
.post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
}
},
{
.req =
{
.name = RT_NULL,
}
},
};
#endif /* RT_USING_VBUS */

View File

@@ -1,40 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-01-07 Grissiom init commit
*/
#ifndef __VBUS_HW_H__
#define __VBUS_HW_H__
#include <rtthread.h>
#include <board.h>
rt_inline void rt_vbus_tick(unsigned int target_cpu, unsigned int irqnr)
{
__SEV();
}
/* Read memory barrier. */
rt_inline void rt_vbus_smp_rmb(void)
{
__DMB();
}
/* Write memory barrier. */
rt_inline void rt_vbus_smp_wmb(void)
{
__DSB();
}
/* General memory barrier. */
rt_inline void rt_vbus_smp_mb(void)
{
__DSB();
}
#endif /* __VBUS_HW_H__ */

View File

@@ -222,10 +222,6 @@
#define RT_LWIP_MSKADDR3 0 #define RT_LWIP_MSKADDR3 0
// </section> // </section>
#define RT_USING_VBUS
#define RT_VBUS_GUEST_VIRQ 0
#define _RT_VBUS_RING_SZ 64
// </RDTConfigurator> // </RDTConfigurator>
#define RT_CPUS_NR 1 #define RT_CPUS_NR 1
#define RT_BACKTRACE_LEVEL_MAX_NR 32 #define RT_BACKTRACE_LEVEL_MAX_NR 32

View File

@@ -1,8 +0,0 @@
#ifndef __VBUS_LOCAL_CONF_H__
#define __VBUS_LOCAL_CONF_H__
#define RT_VBUS_USING_FLOW_CONTROL
#define RT_VBUS_USING_TESTS
#endif /* end of include guard: __VBUS_LOCAL_CONF_H__ */

View File

@@ -1,8 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
dir_path:
- LPC55S6X
- LPC55S06
- LPC5502
- LPC55S28
- LPC55S36

View File

@@ -0,0 +1,9 @@
# .clang-format-ignore File Description:
# ----------------------------------------------------------------------------------------
# 1. Used to specify which files or directories should be skipped by the clang-format tool.
# 2. Follows syntax rules similar to .gitignore.
# 3. Supports wildcard patterns and path matching.
# 4. clang-format will recursively apply the .clang-format-ignore rules.
# NXP MCXA library
/MCXA153/

View File

@@ -1,4 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
dir_path:
- MCXA153

View File

@@ -1,4 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
dir_path:
- MCXC444

View File

@@ -1,4 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
dir_path:
- MCXN947

View File

@@ -1,4 +1,14 @@
# clang-format ignore file # .clang-format-ignore File Description:
# ----------------------------------------------------------------------------------------
# 1. Used to specify which files or directories should be skipped by the clang-format tool.
# 2. Follows syntax rules similar to .gitignore.
# 3. Supports wildcard patterns and path matching.
# 4. clang-format will recursively apply the .clang-format-ignore rules.
# Renesas Vendor library
<<<<<<< HEAD
/**/ra/ /**/ra/
/**/ra_cfg/ /**/ra_cfg/
/**/ra_gen/ /**/ra_gen/
/libraries/bsp-template/
/**/RTE/

View File

@@ -1,9 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- ra
- ra_gen
- ra_cfg
- RTE

View File

@@ -0,0 +1,9 @@
# .clang-format-ignore File Description:
# ----------------------------------------------------------------------------------------
# 1. Used to specify which files or directories should be skipped by the clang-format tool.
# 2. Follows syntax rules similar to .gitignore.
# 3. Supports wildcard patterns and path matching.
# 4. clang-format will recursively apply the .clang-format-ignore rules.
/common/rk_hal/

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- rk_hal

View File

@@ -0,0 +1,12 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
# 从 .ignore_format.yml 迁移的规则
# 忽略所有 STM32 HAL 库目录
/libraries/STM32*_HAL/
# 忽略所有 STM32 BSP 的 CubeMX 配置目录
/stm32*/board/CubeMX_Config/

View File

@@ -1,23 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- STM32F0xx_HAL
- STM32F1xx_HAL
- STM32F2xx_HAL
- STM32F3xx_HAL
- STM32F4xx_HAL
- STM32F7xx_HAL
- STM32G0xx_HAL
- STM32G4xx_HAL
- STM32H7xx_HAL
- STM32L0xx_HAL
- STM32L1xx_HAL
- STM32L4xx_HAL
- STM32L5xx_HAL
- STM32MPxx_HAL
- STM32U5xx_HAL
- STM32H5xx_HAL
- STM32WBxx_HAL
- STM32WLxx_HAL

View File

@@ -145,6 +145,17 @@ extern "C" {
#endif /* UART5_DMA_RX_CONFIG */ #endif /* UART5_DMA_RX_CONFIG */
#endif /* BSP_UART5_RX_USING_DMA */ #endif /* BSP_UART5_RX_USING_DMA */
#if defined(BSP_USING_LPUART1)
#ifndef LPUART1_CONFIG
#define LPUART1_CONFIG \
{ \
.name = "hlpuart1", \
.Instance = LPUART1, \
.irq_type = LPUART1_IRQn, \
}
#endif /* LPUART1_CONFIG */
#endif /* BSP_USING_LPUART1 */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -472,11 +472,23 @@ static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
argval = (rt_uint32_t) arg; argval = (rt_uint32_t) arg;
if (argval == 0) if (argval == 0)
{ {
HAL_CAN_Stop(&drv_can->CanHandle); if (HAL_CAN_DeInit(&drv_can->CanHandle) != HAL_OK)
{
LOG_E("CAN deinitialization failed");
return -RT_ERROR;
}
} }
else else
{ {
HAL_CAN_Start(&drv_can->CanHandle); rt_err_t result = _can_config(&drv_can->device, &drv_can->device.config);
if (result != RT_EOK)
{
return result;
}
if (HAL_CAN_Start(&drv_can->CanHandle) != HAL_OK)
{
return -RT_ERROR;
}
} }
break; break;
@@ -500,7 +512,7 @@ static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
* *
* @return `RT_EOK` on success, or an error code on failure. * @return `RT_EOK` on success, or an error code on failure.
*/ */
static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num) static rt_ssize_t _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
{ {
CAN_HandleTypeDef *hcan; CAN_HandleTypeDef *hcan;
hcan = &((struct stm32_can *) can->parent.user_data)->CanHandle; hcan = &((struct stm32_can *) can->parent.user_data)->CanHandle;
@@ -515,32 +527,32 @@ static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t
(state == HAL_CAN_STATE_LISTENING)) (state == HAL_CAN_STATE_LISTENING))
{ {
/*check select mailbox is empty */ /*check select mailbox is empty */
uint32_t mailbox_mask;
uint32_t tme_flag;
switch (1 << box_num) switch (1 << box_num)
{ {
case CAN_TX_MAILBOX0: case CAN_TX_MAILBOX0:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0) != SET) mailbox_mask = CAN_TX_MAILBOX0;
{ tme_flag = CAN_TSR_TME0;
/* Return function status */
return -RT_ERROR;
}
break; break;
case CAN_TX_MAILBOX1: case CAN_TX_MAILBOX1:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1) != SET) mailbox_mask = CAN_TX_MAILBOX1;
{ tme_flag = CAN_TSR_TME1;
/* Return function status */
return -RT_ERROR;
}
break; break;
case CAN_TX_MAILBOX2: case CAN_TX_MAILBOX2:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME2) != SET) mailbox_mask = CAN_TX_MAILBOX2;
{ tme_flag = CAN_TSR_TME2;
/* Return function status */
return -RT_ERROR;
}
break; break;
default: default:
RT_ASSERT(0); RT_ASSERT(0);
break; return -RT_ERROR;
}
if (HAL_IS_BIT_SET(hcan->Instance->TSR, tme_flag) != SET)
{
RT_UNUSED(mailbox_mask);
return -RT_ERROR;
} }
if (RT_CAN_STDID == pmsg->ide) if (RT_CAN_STDID == pmsg->ide)
@@ -649,7 +661,7 @@ static rt_ssize_t _can_sendmsg_nonblocking(struct rt_can_device *can, const void
return RT_EOK; return RT_EOK;
} }
static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo) static rt_ssize_t _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
{ {
HAL_StatusTypeDef status; HAL_StatusTypeDef status;
CAN_HandleTypeDef *hcan; CAN_HandleTypeDef *hcan;

View File

@@ -23,6 +23,57 @@ extern "C" {
#define __STM32_PORT(port) GPIO##port##_BASE #define __STM32_PORT(port) GPIO##port##_BASE
/**
* @brief Calculates the RT-Thread global pin number from an STM32-specific port and pin.
*
* @details
* This macro provides a vendor-specific way to map a human-readable GPIO port
* (e.g., 'A', 'B') and pin number (0-15) to a single integer value that RT-Thread's
* pin device driver uses to identify a pin globally.
*
* The calculation is based on the memory address offset of the target GPIO port's
* base register relative to GPIOA. It assumes a linear memory map for GPIO ports.
*
* It includes special compile-time handling for different STM32 series, such as the
* STM32MP1, which have a different GPIO memory layout (e.g., 4KB stride between
* port registers) and may include special ports like GPIOZ.
*
* @param[in] PORTx The GPIO port letter (e.g., A, B, C, D). Pass the letter without
* quotes (e.g., A, not 'A').
* @param[in] PIN The pin number within the port (an integer from 0 to 15).
*
* @return
* An `rt_base_t` integer representing the unique pin index for use with RT-Thread
* pin device driver functions (e.g., rt_pin_mode(), rt_pin_write()).
*
* @note
* - **STM32 & RT-Thread Specific:** This macro is highly dependent on the STM32 HAL
* and RT-Thread's pin numbering convention. It relies on underlying HAL macros like
* `__STM32_PORT()` and base address definitions like `GPIOA_BASE`.
* - **Not Portable:** Do not use this macro in code intended to be portable across
* different microcontroller vendors.
* - **Compile-Time Evaluation:** The macro is evaluated entirely at compile time. The
* correct implementation for the target STM32 series is selected via preprocessor
* directives (e.g., `SOC_SERIES_STM32MP1`).
* - **Argument Evaluation:** As this is a preprocessor macro, its arguments are
* substituted directly. Avoid passing expressions with side effects (e.g., `i++`)
* as arguments, as they may be evaluated multiple times.
*
* @see rt_pin_mode()
* @see rt_pin_write()
* @see rt_pin_read()
*
* @code
* // Usage Example 1: Configure pin PD11 as a push-pull output.
* rt_pin_mode(GET_PIN(D, 11), PIN_MODE_OUTPUT);
*
* // Usage Example 2: Write a high logic level to pin PA5.
* rt_pin_write(GET_PIN(A, 5), PIN_HIGH);
*
* // Usage Example 3: Read the logic level from pin PC13.
* int level = rt_pin_read(GET_PIN(C, 13));
* @endcode
*/
#if defined(SOC_SERIES_STM32MP1) #if defined(SOC_SERIES_STM32MP1)
#define GET_PIN(PORTx,PIN) (GPIO##PORTx == GPIOZ) ? (176 + PIN) : ((rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x1000UL) )) + PIN)) #define GET_PIN(PORTx,PIN) (GPIO##PORTx == GPIOZ) ? (176 + PIN) : ((rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x1000UL) )) + PIN))
#else #else

View File

@@ -1,7 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config
- linker_scripts

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

View File

@@ -1,6 +0,0 @@
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- CubeMX_Config

File diff suppressed because it is too large Load Diff

42
bsp/stm32/stm32f407-micu/.gitignore vendored Normal file
View File

@@ -0,0 +1,42 @@
*.pyc
*.map
*.dblite
*.elf
*.bin
*.hex
*.axf
*.exe
*.pdb
*.idb
*.ilk
*.old
build
Debug
documentation/html
packages/
*~
*.o
*.obj
*.out
*.bak
*.dep
*.lib
*.i
*.d
.DS_Stor*
.config 3
.config 4
.config 5
Midea-X1
*.uimg
GPATH
GRTAGS
GTAGS
.vscode
JLinkLog.txt
JLinkSettings.ini
DebugConfig/
RTE/
settings/
*.uvguix*
cconfig.h

View File

@@ -0,0 +1,15 @@
mainmenu "RT-Thread Configuration"
BSP_DIR := .
RTT_DIR := ../../..
PKGS_DIR := packages
source "$(RTT_DIR)/Kconfig"
osource "$PKGS_DIR/Kconfig"
rsource "../libraries/Kconfig"
if !RT_USING_NANO
rsource "board/Kconfig"
endif

Some files were not shown because too many files have changed in this diff Show More