Compare commits

...

52 Commits

Author SHA1 Message Date
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
PandaFeng
6d4e2aa2fe [bsp/stm32h7]: Add STM32H7 fdcan driver. #10767 2025-10-29 22:59:33 +08:00
Ze-Hou
9e3127982d bsp: k230: add i2c driver
Requirement: The BSP for the k230 platform in the RT-Thread repository
        does not yet have an I2C driver.

        Solution: Provide I2C driver for the k230 platform in the RT-Thread
        repository.
        1. support i2c master mode

Signed-off-by: Ze-Hou <yingkezhou@qq.com>
2025-10-29 13:33:11 +08:00
WangShun
e4f014eb96 [bsp/xuantie] 添加E901BSP #10836 2025-10-29 13:31:38 +08:00
482 changed files with 43089 additions and 6190 deletions

View File

@@ -160,6 +160,7 @@
"stm32/stm32f407-atk-explorer",
"stm32/stm32f407-robomaster-c",
"stm32/stm32f407-st-discovery",
"stm32/stm32f407-micu",
"stm32/stm32f410-st-nucleo",
"stm32/stm32f411-st-nucleo",
"stm32/stm32f411-atk-nano",
@@ -195,6 +196,7 @@
"stm32/stm32h563-st-nucleo",
"stm32/stm32h503-st-nucleo",
"stm32/stm32h723-st-nucleo",
"stm32/stm32h723-lxb-disco",
"stm32/stm32h730-esphosted-evb",
"stm32/stm32h743-armfly-v7",
"stm32/stm32h743-atk-apollo",
@@ -482,6 +484,7 @@
"RTT_BSP": "xuantie",
"RTT_TOOL_CHAIN": "sourcery-Xuantie-900-gcc-elf-newlib",
"SUB_RTT_BSP": [
"xuantie/smartl/e901",
"xuantie/smartl/e902",
"xuantie/smartl/e906",
"xuantie/smartl/e907",

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
# events but only for the RT-Thread organization master branch
on:
# Runs at 16:00 UTC (BeiJing 00:00) every day
schedule:
- cron: '0 16 * * *'
push:
branches:
- master
@@ -46,6 +43,12 @@ on:
types:
- online-pkgs-static-building-trigger-event
workflow_dispatch:
inputs:
trigger_type:
description: '触发类型'
required: false
default: 'manual'
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -177,10 +180,10 @@ jobs:
- name: Install Xuantie-900-gcc-elf-newlib Tools
if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-Xuantie-900-gcc-elf-newlib' && success() }}
run: |
wget -q https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1744884010580/Xuantie-900-gcc-elf-newlib-x86_64-V3.0.2-20250410.tar.gz
sudo tar -zxvf Xuantie-900-gcc-elf-newlib-x86_64-V3.0.2-20250410.tar.gz -C /opt
/opt/Xuantie-900-gcc-elf-newlib-x86_64-V3.0.2/bin/riscv64-unknown-elf-gcc --version
echo "RTT_EXEC_PATH=/opt/Xuantie-900-gcc-elf-newlib-x86_64-V3.0.2/bin" >> $GITHUB_ENV
wget -q https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1751370399722/Xuantie-900-gcc-elf-newlib-x86_64-V3.2.0-20250627.tar.gz
sudo tar -zxvf Xuantie-900-gcc-elf-newlib-x86_64-V3.2.0-20250627.tar.gz -C /opt
/opt/Xuantie-900-gcc-elf-newlib-x86_64-V3.2.0/bin/riscv64-unknown-elf-gcc --version
echo "RTT_EXEC_PATH=/opt/Xuantie-900-gcc-elf-newlib-x86_64-V3.2.0/bin" >> $GITHUB_ENV
- name: Install Xuantie-900-gcc-linux-musl Tools
if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-Xuantie-900-gcc-linux-musl' && success() }}
@@ -288,4 +291,17 @@ jobs:
uses: actions/upload-artifact@main
with:
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

@@ -29,4 +29,17 @@ jobs:
shell: bash
run: |
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

@@ -54,4 +54,17 @@ jobs:
sudo make install FILESDIR=/usr/local/share/Cppcheck
cppcheck --version
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/**
- '**/README.md'
- '**/README_zh.md'
workflow_dispatch:
inputs:
trigger_type:
description: '触发类型'
required: false
default: 'manual'
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -297,4 +304,16 @@ jobs:
echo "=========================================================================================="
break
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

@@ -1,3 +1,184 @@
# RT-Thread v5.2.2 Released
Change Log Since v5.2.1 Release.
## Kernel
* Fix scheduling exception caused by interrupt preemption in rt_schedule.[(#10715)](https://github.com/RT-Thread/rt-thread/pull/10715)
* Fix the legacy issue related to the length of the object name version.[(#10537)](https://github.com/RT-Thread/rt-thread/pull/10537)
* Fixed buffer overflow vulnerability in object.[(#10523)](https://github.com/RT-Thread/rt-thread/pull/10523)
* Add up scheduler critical switch flag.[(#10581)](https://github.com/RT-Thread/rt-thread/pull/10581)
* Update the default value of RT_NAME_MAX to 12.[(#10839)](https://github.com/RT-Thread/rt-thread/pull/10839)
* Feat the rt_scheduler lock nest uses atomic operations.[(#10621)](https://github.com/RT-Thread/rt-thread/pull/10621)
## Components
* **Drivers**
* **Serial:**
* serial_v1
* Fix correct data loss logic when RX ring buffer is full.
* serial_v2
* Fix the bug of RX flush under DMA.
* Add serial V2 buffer configuration via Kconfig.
* Feat optimize serial v2. [(#10603)](https://github.com/RT-Thread/rt-thread/pull/10603)
* Feat modify the default configuration of the RT_SERIAL_CONFIG_DEFAULT structure to support parameters in the absence of DMA configuration.
* **RTC:**
* Add the alarm using local time for calculation.
* **CAN:**
* Fixed the issue where the thread calling CAN int TX was suspended when CAN at the bottom layer failed to work.
* Feat: Implement non-blocking send mechanism and enhance CAN driver functionality.
* **SPI:**
* Add SPI device detach function.[(#10733)](https://github.com/RT-Thread/rt-thread/pull/10733)
* Update and fix up the SPI.
* **ADC:**
* Fixed cppcheck error.
* Remove build warnings.
* **ktime:**
* Remove unused rt_ktime_hrtimer_getcnt for hrtimer.
* **wlan:**
* Update SECURITY_UNKNOWN value.
* **LWP**
* Fix potential signal handler infinite loop for riscv.
* Feat: Restore TP register in arch_thread_signal_enter to fix user-mode memory access.
* **Libc**
* Add comments for some pthread functions.
* pthreads: Fix pthread_cond_timedwait lacks timeout wakeup.
* ensure compatibility with newlib <3.4.0 by handling removed __sdidinit. [(#10791)](https://github.com/RT-Thread/rt-thread/pull/10791)
* **DFS**
* **DFS v2**:
* Fix bugs for function _get_parent_path(). [(#10539)](https://github.com/RT-Thread/rt-thread/pull/10539)
* **Net**
* **SAL/Socket:**
* Fixed CI compilation failure in sal/src/sal_socket.c.
* Fix memory leak when sal_socket failed.
* improve the error return of sal.
* **Netdev:**
* Fixed compilation errors when enabling IPv6 and IPv4 dual-stack support.
* Fixed netdev_unregister missing correct return value. [(#10693)](https://github.com/RT-Thread/rt-thread/pull/10693)
* Expose netdev_set_dns and netdev_set_if. [(#10128)](https://github.com/RT-Thread/rt-thread/pull/10128)
* **AT:**
* at_client add deInit port. [(#10598)](https://github.com/RT-Thread/rt-thread/pull/10598)
* **Finsh:**
* Fixed clear out the useless copy operations. [(#10699)](https://github.com/RT-Thread/rt-thread/pull/10699)
* Feat add support for the Home, Insert, Delete and End keys, and improve input mode processing.[(#10595)](https://github.com/RT-Thread/rt-thread/pull/10595)
* Feat: Add new features (delete by word, switch cursor, etc.).
* **USB:**
* Update (cherryusb): update to v1.5.1.
* Fixed several issues related to cherryusb.[(#10844)](https://github.com/RT-Thread/rt-thread/pull/10844)
* **Ulog:**
* Fix:filter should not be associated with ULOG_USING_COLOR and ULOG_USING_SYSLOG configurations.
* **IPC:**
* Pass rt_tick_t for RT_TIMER_CTRL_SET_TIME and RT_TIMER_CTRL_GET_TIME.[(#10717)](https://github.com/RT-Thread/rt-thread/pull/10717)
## DM
* NVME: fix up the QUEUE alloc error no check.
* Thermal: Fix up the C99, 6.8.1 Labeled statements p4; Fix up the PWM-FAN remove handle data ptr.
* PCI: Add SoC PCI Kconfig import; Multiple PCI-related fixes; Fix and optimize interrupt-related issues.
* WDT: Support related to Intel 6300ESB/Synopsys Watchdog, etc.
## Libcpu
* **AArch64:**
* Fix up MMU and linker warning.
* Fix rt_aspace_init error when KERNEL_VADDR_START >= 0x80000000.
* Add the configuration of libcpu/aarch64 KERNEL ASPACE START.
* Update Hypercall API.
* Remove unused rt_hw_set_gtimer_frq.
* **Cortex-M33:**
* Fix the M33 assembly syntax errors and fix the compilation error of BSP.
* Added HardFault_Handler to save floating point registers.
* **Cortex-M4:**
* Fixed compilation error.
* Added HardFault_Handler to save floating point registers.
* **Cortex-M3:**
* The parameter passed to the unified rt_exception_hook is exception_stack. [(#10619)](https://github.com/RT-Thread/rt-thread/pull/10619)
* **RISC-V:**
* Fix type mismatch of `_query`.
* Fix the support for RV32E. RV32E does not support the s2 register. Modify it to the s1 register.
* Use volatile RW for claim and complete.
* Add spaces to fix `Wliteral-suffix`.
* Add comment for the round down of symb_pc.
* Remove `rt_hw_cpu_id` in `cpuport.h` to fix error.
## Tools
* Add support for package.json, refactor BuildPackage function to handle new format.
* Add documents for tools script; Add NG for tools. [(#10572)](https://github.com/RT-Thread/rt-thread/pull/10572)
* Add workspace generation for RT-Thread root directory.
* Add vsc_workspace target in scons.
* Add DTC (Devicetree Compiler) tools.
* Add clang-format formatting script for CI.
* Optimize the file opening method.
* Clang format ignore migration.
* Improve[clang-format]: optimize the formatting logic for RT-Thread coding standard.
## Action
* Fixed CI: ARDUINO_ADAFRUIT_SENSORLAB compilation failure issue.
* Fixed CI compilation failure in sal/src/sal_socket.c.[(#10854)](https://github.com/RT-Thread/rt-thread/pull/10854)
* Merge same tag with different paths, remove Path display from CI comment.
* Add Copilot review title keywords.
* Add concurrency control to GitHub Actions. [(#10761)](https://github.com/RT-Thread/rt-thread/pull/10761)
* integrate utest run ci. [(#10748)](https://github.com/RT-Thread/rt-thread/pull/10748)
* Improve the comment instructions for the PR format bot.[(#10747)](https://github.com/RT-Thread/rt-thread/pull/10747)
## Documents
* **Doxygen:**
* Fix some document issues.
* Update naming rule for utest-case.
* Update doc for env to latest.
* Update some document content.
* Group name all in lowercase. [(#10530)](https://github.com/RT-Thread/rt-thread/pull/10530)
* Grouping and page optimization related to device driver.
* use layout to control the HTML display.
* Add doxygen comments for scheduler. [(#10366)](https://github.com/RT-Thread/rt-thread/pull/10366) and lwp
* update doxygen version to v1.9.8 .
## Utest
* Add netdev/lwip/filesystem/memory pool/SAL/system performance API test case.
* Support autocomplete of utest cases for `utest_run`. [(#10701)](https://github.com/RT-Thread/rt-thread/pull/10701)
* Feat:reorganize utest menu.
* Feat:rename files and update naming according to new rule.
* Feat:reorganize utest framework structure (initial version).
* Feat:unify config name. [(#10808)](https://github.com/RT-Thread/rt-thread/pull/10808)
* Feat:integrate test cases into utest framework. [(#10665)](https://github.com/RT-Thread/rt-thread/pull/10665)
* Move driver-related test cases under `drivers`.
* Move and enhance C++ test cases.
## BSP
* Some driver issues have been resolved and some driver support has been added.
* **Added/Updated BSPs:**
* **xuantie**
* E901
* **Renesas:**
* ek-ra6e2
* ek-ra4e2
* ek-ra2a1
* ek-ra2e2
* ek-ra4m1
* **GD32:**
* gd32h759i-eval
* gd32470i-eval
* gd32e230-lckfb
* **NXP:**
* MCX E247
* FRDM-MCXE247
* FRDM-MCXA346
* **HPMicro:**
* hpm6p00evk
* hpm5e00evk
* **Phytium**
* **Raspberry RP2350**
# RT-Thread v5.2.1 Released
Change Log Since v5.2.0 Release

View File

@@ -147,6 +147,10 @@ tag: bsp_stm32f429-atk-apollo
path: bsp/stm32/stm32f429-atk-apollo
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
path: bsp/stm32/stm32h723-st-nucleo
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)
void rt_hw_board_init(void);
int rt_vbus_do_init(void);
#endif

View File

@@ -34,55 +34,63 @@ menu "On-chip Peripheral Drivers"
config BSP_UART0_RX_USING_DMA
bool "Enable UART0 RX DMA"
depends on BSP_USING_UART0
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART0 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART0_TX_USING_DMA
bool "Enable UART0 TX DMA"
depends on BSP_USING_UART0
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART0 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART0 RX buffer size"
range 64 65535
depends on BSP_USING_UART0 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART0_TX_BUFSIZE
int "Set UART0 TX buffer size"
range 0 65535
depends on BSP_USING_UART0 && RT_USING_SERIAL_V2
default 0
default 128
config BSP_USING_UART1
bool "Enable UART1"
default n
default y
config BSP_UART1_RX_USING_DMA
bool "Enable UART1 RX DMA"
depends on BSP_USING_UART1
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART1_TX_USING_DMA
bool "Enable UART1 TX DMA"
depends on BSP_USING_UART1
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART1 RX buffer size"
range 64 65535
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART1_TX_BUFSIZE
int "Set UART1 TX buffer size"
range 0 65535
depends on BSP_USING_UART1 && RT_USING_SERIAL_V2
default 0
default 128
config BSP_USING_UART2
bool "Enable UART2"
@@ -90,27 +98,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART2_RX_USING_DMA
bool "Enable UART2 RX DMA"
depends on BSP_USING_UART2
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART2_TX_USING_DMA
bool "Enable UART2 TX DMA"
depends on BSP_USING_UART2
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART2 RX buffer size"
range 64 65535
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART2_TX_BUFSIZE
int "Set UART2 TX buffer size"
range 0 65535
depends on BSP_USING_UART2 && RT_USING_SERIAL_V2
default 0
default 128
config BSP_USING_UART3
bool "Enable UART3"
@@ -118,27 +130,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART3_RX_USING_DMA
bool "Enable UART3 RX DMA"
depends on BSP_USING_UART3
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART3_TX_USING_DMA
bool "Enable UART3 TX DMA"
depends on BSP_USING_UART3
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART3 RX buffer size"
range 64 65535
depends on BSP_USING_UART3 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART3_TX_BUFSIZE
int "Set UART3 TX buffer size"
range 0 65535
depends on BSP_USING_UART3 && RT_USING_SERIAL_V2
default 0
default 128
config BSP_USING_UART4
bool "Enable UART4"
@@ -146,27 +162,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART4_RX_USING_DMA
bool "Enable UART4 RX DMA"
depends on BSP_USING_UART4
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART4 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART4_TX_USING_DMA
bool "Enable UART4 TX DMA"
depends on BSP_USING_UART4
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART4 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART4 RX buffer size"
range 64 65535
depends on BSP_USING_UART4 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART4_TX_BUFSIZE
int "Set UART4 TX buffer size"
range 0 65535
depends on BSP_USING_UART4 && RT_USING_SERIAL_V2
default 0
default 128
config BSP_USING_UART5
bool "Enable UART5"
@@ -174,27 +194,31 @@ menu "On-chip Peripheral Drivers"
config BSP_UART5_RX_USING_DMA
bool "Enable UART5 RX DMA"
depends on BSP_USING_UART5
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART5 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART5_TX_USING_DMA
bool "Enable UART5 TX DMA"
depends on BSP_USING_UART5
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART5 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART5 RX buffer size"
range 64 65535
depends on BSP_USING_UART5 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART5_TX_BUFSIZE
int "Set UART5 TX buffer size"
range 0 65535
depends on BSP_USING_UART5 && RT_USING_SERIAL_V2
default 0
default 128
config BSP_USING_UART6
bool "Enable UART6"
@@ -202,55 +226,63 @@ menu "On-chip Peripheral Drivers"
config BSP_UART6_RX_USING_DMA
bool "Enable UART6 RX DMA"
depends on BSP_USING_UART6
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART6 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART6_TX_USING_DMA
bool "Enable UART6 TX DMA"
depends on BSP_USING_UART6
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART6 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART6 RX buffer size"
range 64 65535
depends on BSP_USING_UART6 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART6_TX_BUFSIZE
int "Set UART6 TX buffer size"
range 0 65535
depends on BSP_USING_UART6 && RT_USING_SERIAL_V2
default 0
default 128
config BSP_USING_UART7
config BSP_USING_UART7
bool "Enable UART7"
default n
config BSP_UART7_RX_USING_DMA
bool "Enable UART7 RX DMA"
depends on BSP_USING_UART7
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART7 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
default n
config BSP_UART7_TX_USING_DMA
bool "Enable UART7 TX DMA"
depends on BSP_USING_UART7
select RT_SERIAL_USING_DMA
depends on BSP_USING_UART7 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA
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
int "Set UART7 RX buffer size"
range 64 65535
depends on BSP_USING_UART7 && RT_USING_SERIAL_V2
default 64
default 128
config BSP_UART7_TX_BUFSIZE
int "Set UART7 TX buffer size"
range 0 65535
depends on BSP_USING_UART7 && RT_USING_SERIAL_V2
default 0
default 128
endif
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);
uart = rt_container_of(serial, struct gd32_uart, serial);
recv_len = 0;
level = rt_hw_interrupt_disable();
#if defined SOC_SERIES_GD32E23x
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)
{
struct rt_serial_rx_fifo *rx_fifo;
rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
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_uint8_t chr = usart_data_receive(uart->periph);
rt_hw_serial_control_isr(serial, RT_HW_SERIAL_CTRL_PUTC, (void *)&chr);
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)
{
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);
}
@@ -320,7 +312,6 @@ static void usart_isr (struct rt_serial_device *serial)
usart_interrupt_disable(uart->periph, USART_INT_TBE);
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)
{
@@ -334,10 +325,9 @@ static void usart_isr (struct rt_serial_device *serial)
#ifdef RT_SERIAL_USING_DMA
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);
usart_interrupt_flag_clear(uart->periph, USART_INT_FLAG_IDLE);
}
#endif
@@ -595,8 +585,8 @@ void UART7_IRQHandler (void)
}
#endif /* BSP_USING_UART7 */
#if define SOC_SERIES_GD32E23x
#if define BSP_UART0_RX_USING_DMA || define BSP_UART0_TX_USING_DMA
#if defined SOC_SERIES_GD32E23x
#if defined BSP_UART0_RX_USING_DMA || defined BSP_UART0_TX_USING_DMA
void DMA_Channel1_2_IRQHandler(void)
{
/* 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_FTFIE);
/* enable circular mode */
dma_circulation_enable(uart->dma.rx.channel);
/* enable dma channel */
dma_channel_enable(uart->dma.rx.channel);
@@ -953,7 +946,11 @@ static void _uart_dma_receive (struct gd32_uart *uart, rt_uint8_t *buffer, rt_ui
usart_interrupt_enable(uart->periph, USART_INT_IDLE);
/* 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);
#endif
#endif
}
@@ -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;
/* 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);
#endif
/* enable dma 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)
{
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 */
_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 rx_gpio_clk;
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;
#endif
uint16_t tx_pin;
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;
#endif
uint16_t rx_pin;

View File

@@ -0,0 +1,54 @@
scons.args: &scons
scons_arg:
- '--strict'
devices.spi:
<<: *scons
kconfig:
- CONFIG_RT_USING_SPI=y
- CONFIG_BSP_USING_SPI=y
- CONFIG_BSP_USING_SPI0=y
devices.i2c:
<<: *scons
kconfig:
- CONFIG_RT_USING_I2C=y
- CONFIG_BSP_USING_I2C=y
- CONFIG_BSP_USING_I2C0=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

@@ -227,6 +227,7 @@ CONFIG_FINSH_THREAD_STACK_SIZE=8192
CONFIG_FINSH_USING_HISTORY=y
CONFIG_FINSH_HISTORY_LINES=5
# CONFIG_FINSH_USING_WORD_OPERATION is not set
# CONFIG_FINSH_USING_FUNC_EXT is not set
CONFIG_FINSH_USING_SYMTAB=y
CONFIG_FINSH_CMD_SIZE=80
CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
@@ -425,6 +426,7 @@ CONFIG_RT_USING_POSIX_TIMER=y
#
CONFIG_RT_USING_SAL=y
CONFIG_SAL_INTERNET_CHECK=y
CONFIG_SOCKET_TABLE_STEP_LEN=4
#
# Docking with protocol stacks
@@ -532,8 +534,6 @@ CONFIG_RT_USING_ADT_REF=y
# CONFIG_RT_USING_RT_LINK is not set
# end of Utilities
# CONFIG_RT_USING_VBUS is not set
#
# Memory management
#
@@ -941,6 +941,7 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_R_RHEALSTONE is not set
# CONFIG_PKG_USING_HEARTBEAT is not set
# CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set
# CONFIG_PKG_USING_CHERRYECAT is not set
# end of system packages
#
@@ -1098,6 +1099,12 @@ CONFIG_RT_USING_VDSO=y
# CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set
# end of GD32 Drivers
#
# HPMicro SDK
#
# CONFIG_PKG_USING_HPM_SDK is not set
# end of HPMicro SDK
# end of HAL & SDK Drivers
#
@@ -1617,6 +1624,8 @@ CONFIG_PKG_ZLIB_VER="latest"
#
# Drivers Configuration
#
# CONFIG_BSP_USING_SPI is not set
# CONFIG_BSP_USING_I2C is not set
# CONFIG_BSP_USING_RTC is not set
# CONFIG_BSP_USING_ADC is not set
# CONFIG_BSP_USING_TS is not set

View File

@@ -1,5 +1,59 @@
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
bool "Enable I2C"
select RT_USING_I2C
default n
if BSP_USING_I2C
config BSP_USING_I2C0
bool "Enable I2C0"
default n
config BSP_USING_I2C1
bool "Enable I2C1"
default n
config BSP_USING_I2C2
bool "Enable I2C2"
default n
config BSP_USING_I2C3
bool "Enable I2C3"
default n
config BSP_USING_I2C4
bool "Enable I2C4"
default n
endif
config BSP_USING_RTC
bool "Enable RTC"
select RT_USING_RTC

View File

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

View File

@@ -0,0 +1,528 @@
/* 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 <rthw.h>
#include <rtdevice.h>
#include <riscv_io.h>
#include <ioremap.h>
#include "board.h"
#include "drv_i2c.h"
#include "sysctl_clk.h"
#undef DBG_TAG
#undef DBG_LVL
#define DBG_TAG "drv_i2c"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
struct _i2c_speed_cfg
{
rt_uint16_t hcnt;
rt_uint16_t lcnt;
rt_uint16_t spklen;
};
struct k230_i2c_dev
{
struct rt_i2c_bus_device dev;
const char *name;
rt_ubase_t base;
size_t size;
int vector;
rt_uint32_t clock;
struct rt_i2c_msg *msg;
struct _i2c_speed_cfg speed_cfg;
};
static rt_size_t k230_i2c_get_timer(rt_size_t base)
{
return rt_tick_get() - base ;
}
static void k230_i2c_enable(struct k230_i2c_dev *dev, rt_bool_t enable)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint32_t en_value = enable ? 1 : 0;
int timeout = 100;
do
{
i2c->enable.enable = en_value;
if(i2c->enable_status.en == en_value)
{
return;
}
/*
* Wait 10 times the signaling period of the highest I2C
* transfer supported by the driver (for 400KHz this is
* 25us) as described in the DesignWare I2C databook.
*/
rt_hw_us_delay(25);
}while(timeout--);
LOG_E("timeout in %s i2c\n", enable ? "enable" : "disable");
}
static void k230_i2c_set_bus_timeout(struct k230_i2c_dev *dev, rt_uint32_t timeout)
{
float tick = 0;
tick = RT_TICK_PER_SECOND / 1000.0f; /* ms to tick */
dev->dev.timeout = (rt_uint32_t)(timeout * tick);
}
static int k230_i2c_set_bus_speed(struct k230_i2c_dev *dev, rt_uint32_t speed)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint32_t i2c_spd, period, spklen, ft;
/*
* Calculate clock counts for I2C speed
* hcnt + lcnt + spklen + 7 + 1 + fall_time * clk = clk / speed
* fall_time = 10ns
* spklen = 0~50ns
*/
spklen = dev->clock * 10 / 1e9;
ft = dev->clock * 10 / 1e9;
period = dev->clock / speed;
period = period - spklen - 7 - 1 - ft;
dev->speed_cfg.lcnt = period / 2;
dev->speed_cfg.hcnt = period - dev->speed_cfg.lcnt;
dev->speed_cfg.spklen = spklen;
if(speed <= I2C_STANDARD_SPEED_UP)
{
i2c_spd = I2C_SPEED_MODE_STANDARD;
}
else if(speed <= I2C_FAST_SPEED_UP)
{
i2c_spd = I2C_SPEED_MODE_FAST;
}
else if(speed <= I2C_MAX_SPEED_UP)
{
i2c_spd = I2C_SPEED_MODE_MAX;
}
else
{
return -RT_EINVAL;
}
/* to set speed cltr must be disabled */
k230_i2c_enable(dev, RT_FALSE);
switch(i2c_spd)
{
case I2C_SPEED_MODE_STANDARD:
i2c->ss_ufm_scl_hcnt.cnt = dev->speed_cfg.hcnt;
i2c->ss_ufm_scl_lcnt.cnt = dev->speed_cfg.lcnt;
i2c->fs_ufm_spklen.spklen = dev->speed_cfg.spklen;
break;
case I2C_SPEED_MODE_FAST:
i2c->fs_scl_hcnt_ufm_tbuf_cnt.cnt = dev->speed_cfg.hcnt;
i2c->fs_scl_lcnt.cnt = dev->speed_cfg.lcnt;
i2c->fs_ufm_spklen.spklen = dev->speed_cfg.spklen;
break;
case I2C_SPEED_MODE_MAX:
i2c->hs_scl_hcnt.cnt = dev->speed_cfg.hcnt;
i2c->hs_scl_lcnt.cnt = dev->speed_cfg.lcnt;
i2c->hs_spklen.spklen = dev->speed_cfg.spklen;
break;
default: break;
}
i2c->con.speed = i2c_spd;
/* Enable back i2c now speed set */
k230_i2c_enable(dev, RT_TRUE);
return RT_EOK;
}
static void k230_i2c_set_addr(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint16_t i2c_addr = dev->msg->addr;
/* Disable i2c */
k230_i2c_enable(dev, RT_FALSE);
if(dev->msg->flags & RT_I2C_ADDR_10BIT || dev->dev.flags & RT_I2C_ADDR_10BIT)
{
i2c->tar.master_10bit_addr = 1;
i2c_addr &= 0x3FF;
}
else
{
i2c->tar.master_10bit_addr = 0;
i2c_addr &= 0x7F;
}
i2c->tar.tar = i2c_addr;
/* Enable i2c */
k230_i2c_enable(dev, RT_TRUE);
}
static void k230_i2c_flush_rxfifo(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
while(i2c->status.rfne)
{
readl(&i2c->data_cmd);
}
}
static int k230_i2c_wait_for_bus_busy(struct k230_i2c_dev *dev)
{
rt_size_t start_time = k230_i2c_get_timer(0);
volatile i2c_t *i2c = (i2c_t *)dev->base;
while((i2c->status.mst_activity) || !(i2c->status.tfe))
{
/* Evaluate timeout */
if(k230_i2c_get_timer(start_time) > (rt_size_t)dev->dev.timeout * I2C_TX_FIFO_SIZE)
{
return -RT_ETIMEOUT;
}
}
return RT_EOK;
}
static int k230_i2c_xfer_init(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint8_t addr = 0;
if(k230_i2c_wait_for_bus_busy(dev) != RT_EOK)
{
return -RT_EBUSY;
}
k230_i2c_set_addr(dev);
return RT_EOK;
}
static int k230_i2c_xfer_finish(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_uint32_t start_stop_det = k230_i2c_get_timer(0);
while (1)
{
if(i2c->raw_intr_stat.stop_det)
{
readl(&i2c->clr_stop_det);
break;
}
else if (k230_i2c_get_timer(start_stop_det) > dev->dev.timeout)
{
break;
}
}
if (k230_i2c_wait_for_bus_busy(dev) != RT_EOK)
{
return -RT_EBUSY;
}
k230_i2c_flush_rxfifo(dev);
return RT_EOK;
}
static int _k230_i2c_read(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_size_t start_time_rx = 0;
rt_uint32_t recv_len = dev->msg->len;
rt_uint32_t tran_len = dev->msg->len;
rt_uint8_t *buffer = dev->msg->buf;
rt_uint32_t cmd = 0;
/* 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)
{
return -RT_EBUSY;
}
}
start_time_rx = k230_i2c_get_timer(0);
while(recv_len || tran_len)
{
if (tran_len)
{
while(i2c->status.tfnf == 0);
/* Write stop when the last byte */
cmd = tran_len == 1 ? cmd | I2C_DATA_CMD_STOP : cmd;
/* Write to data cmd register to trigger i2c */
writel(cmd | I2C_DATA_CMD_READ, &i2c->data_cmd);
cmd = 0;
tran_len--;
}
if(i2c->status.rfne)
{
*buffer++ = i2c->data_cmd.dat;
recv_len--;
start_time_rx = k230_i2c_get_timer(0);
}
else if(k230_i2c_get_timer(start_time_rx) > dev->dev.timeout)
{
return -RT_ETIMEOUT;
}
}
return k230_i2c_xfer_finish(dev);
}
static int _k230_i2c_write(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
rt_size_t start_time_tx = 0;
rt_uint32_t tran_len = dev->msg->len;
rt_uint8_t *buffer = dev->msg->buf;
rt_uint32_t cmd = 0;
rt_uint32_t cut = 0;
if (k230_i2c_xfer_init(dev) != RT_EOK)
{
return -RT_EBUSY;
}
start_time_tx = k230_i2c_get_timer(0);
while(tran_len)
{
if(i2c->status.tfnf)
{
/* If there is no stop flag, the stop condition will not be sent at the last byte. */
if(tran_len == 1 && !(dev->msg->flags & RT_I2C_NO_STOP))
{
cmd |= I2C_DATA_CMD_STOP;
}
else
{
cmd &= ~I2C_DATA_CMD_STOP;
}
cmd |= *buffer++;
writel(cmd, &i2c->data_cmd);
cmd = 0;
tran_len--;
start_time_tx = k230_i2c_get_timer(0);
}
else if(k230_i2c_get_timer(start_time_tx) > dev->dev.timeout)
{
return -RT_ETIMEOUT;
}
}
if (dev->msg->flags & RT_I2C_NO_STOP)
{
return RT_EOK;
}
if (k230_i2c_wait_for_bus_busy(dev) != RT_EOK)
{
return -RT_EBUSY;
}
return RT_EOK;
}
static rt_ssize_t k230_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
{
struct k230_i2c_dev *i2c_dev = rt_container_of(bus, struct k230_i2c_dev, dev);
volatile i2c_t *i2c = (i2c_t *)i2c_dev->base;
int ret;
rt_ssize_t send_mesgs = num;
for (; num > 0; num--, msgs++)
{
i2c_dev->msg = msgs;
if(msgs->flags & RT_I2C_RD)
{
ret = _k230_i2c_read(i2c_dev);
}
else
{
ret = _k230_i2c_write(i2c_dev);
}
if (ret != RT_EOK)
{
return -RT_EIO;
}
}
return send_mesgs;
}
static rt_err_t k230_i2c_control(struct rt_i2c_bus_device *bus, int cmd, void *args)
{
struct k230_i2c_dev *i2c_dev = rt_container_of(bus, struct k230_i2c_dev, dev);
rt_uint32_t arg = *(rt_uint32_t *)args;
rt_err_t ret;
RT_ASSERT(bus != RT_NULL);
switch (cmd)
{
/* set 10-bit addr mode */
case RT_I2C_DEV_CTRL_10BIT:
if(arg & RT_I2C_ADDR_10BIT)
{
i2c_dev->dev.flags |= RT_I2C_ADDR_10BIT;
}
else
{
i2c_dev->dev.flags &= ~RT_I2C_ADDR_10BIT;
}
break;
case RT_I2C_DEV_CTRL_TIMEOUT:
k230_i2c_set_bus_timeout(i2c_dev, arg);
break;
case RT_I2C_DEV_CTRL_CLK:
ret = k230_i2c_set_bus_speed(i2c_dev, arg);
if (ret != RT_EOK)
{
return -RT_EIO;
}
break;
default: break;
}
return RT_EOK;
}
static void k230_i2c_master_init(struct k230_i2c_dev *dev)
{
volatile i2c_t *i2c = (i2c_t *)dev->base;
/* Disable i2c */
k230_i2c_enable(dev, RT_FALSE);
i2c->con.slave_disable = 1;
i2c->con.restart_en = 1;
i2c->con.master_mode = 1;
i2c->tx_tl.tl = I2C_TX_TL;
i2c->rx_tl.tl = I2C_RX_TL;
i2c->intr_mask.m_stop_det = 1;
/* Enable i2c */
k230_i2c_enable(dev, RT_TRUE);
}
static const struct rt_i2c_bus_device_ops k230_i2c_ops =
{
.master_xfer = k230_i2c_xfer,
.i2c_bus_control = k230_i2c_control,
};
static struct k230_i2c_dev k230_i2c_devs[] =
{
#ifdef BSP_USING_I2C0
{
.name = "i2c0",
.base = I2C0_BASE_ADDR,
.size = I2C0_IO_SIZE,
.vector = K230_IRQ_I2C0,
},
#endif
#ifdef BSP_USING_I2C1
{
.name = "i2c1",
.base = I2C1_BASE_ADDR,
.size = I2C1_IO_SIZE,
.vector = K230_IRQ_I2C1,
},
#endif
#ifdef BSP_USING_I2C2
{
.name = "i2c2",
.base = I2C2_BASE_ADDR,
.size = I2C2_IO_SIZE,
.vector = K230_IRQ_I2C2,
},
#endif
#ifdef BSP_USING_I2C3
{
.name = "i2c3",
.base = I2C3_BASE_ADDR,
.size = I2C3_IO_SIZE,
.vector = K230_IRQ_I2C3,
},
#endif
#ifdef BSP_USING_I2C4
{
.name = "i2c4",
.base = I2C4_BASE_ADDR,
.size = I2C4_IO_SIZE,
.vector = K230_IRQ_I2C4,
},
#endif
};
int rt_hw_i2c_init(void)
{
int 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].dev.ops = &k230_i2c_ops;
k230_i2c_devs[i].clock = sysctl_clk_get_leaf_freq(SYSCTL_CLK_I2C0_CORE + i);
k230_i2c_master_init(&k230_i2c_devs[i]);
k230_i2c_set_bus_timeout(&k230_i2c_devs[i], I2C_DEFAULT_TIMEOUT);
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);
LOG_I("i2c%d master mode, i2c%d clock=%dHz\n", i, i, k230_i2c_devs[i].clock);
}
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_i2c_init);

View File

@@ -0,0 +1,704 @@
/* 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_I2C_H__
#define __DRV_I2C_H__
#include <stdint.h>
#define BIT(x) (1<<(x))
/* Speed Selection */
#define I2C_SPEED_MODE_STANDARD 1
#define I2C_SPEED_MODE_FAST 2
#define I2C_SPEED_MODE_MAX 3
#define I2C_MAX_SPEED_UP 3400000
#define I2C_FAST_SPEED_UP 1000000
#define I2C_STANDARD_SPEED_UP 100000
#define I2C_DEFAULT_SPEED 400000
#define I2C_DEFAULT_TIMEOUT 8 /* 8ms */
/* i2c data cmd definition */
#define I2C_DATA_CMD_READ BIT(8)
#define I2C_DATA_CMD_STOP BIT(9)
#define I2C_DATA_CMD_RESTART BIT(10)
#define I2C_DATA_CMD_FIRST_DATA_BYTE BIT(11)
/* i2c fifo size */
#define I2C_TX_FIFO_SIZE 32 /* 32 * 32bit */
#define I2C_RX_FIFO_SIZE 32 /* 64 * 8bit */
/* fifo threshold register definitions */
#define I2C_TL0 0x00
#define I2C_TL1 0x01
#define I2C_TL2 0x02
#define I2C_TL3 0x03
#define I2C_TL4 0x04
#define I2C_TL5 0x05
#define I2C_TL6 0x06
#define I2C_TL7 0x07
#define I2C_RX_TL I2C_TL0
#define I2C_TX_TL I2C_TL0
/* i2c control register(offset address 0x00) */
typedef struct _i2c_ic_con
{
uint32_t master_mode : 1;
uint32_t speed : 2;
uint32_t slave_10bit_addr : 1;
uint32_t master_10bit_addr : 1;
uint32_t restart_en : 1;
uint32_t slave_disable : 1;
uint32_t stop_det_ifaddressed : 1;
uint32_t tx_empty_ctrl : 1;
uint32_t rx_fifo_full_hld_ctrl : 1;
uint32_t stop_det_if_master_active : 1;
uint32_t bus_clear_feature_ctrl : 1;
uint32_t rsvd_1 : 4; /* reserved */
uint32_t optional_sar_ctrl : 1;
uint32_t smbus_slave_quick_en : 1;
uint32_t smbus_arp_en : 1;
uint32_t smbus_persisent_slv_addr_en : 1;
uint32_t rsvd_2 : 12; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_con_t;
/* i2c target address register(offset address 0x04) */
typedef struct _i2c_ic_tar
{
uint32_t tar : 10;
uint32_t gc_or_start : 1;
uint32_t special : 1;
uint32_t master_10bit_addr : 1;
uint32_t device_id : 1;
uint32_t rsvd_1 : 2; /* reserved */
uint32_t smbus_quick_cmd : 1;
uint32_t rsvd_2 : 15; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_tar_t;
/* i2c slave address register(offset address 0x08) */
typedef struct _i2c_ic_sar
{
uint32_t sar : 10;
uint32_t rsvd : 22; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_sar_t;
/* i2c high speed master mode code address register(offset address 0x0c) */
typedef struct _i2c_ic_hs_maddr
{
uint32_t mar : 3;
uint32_t rsvd : 29; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_hs_maddr_t;
/* i2c rx/tx data buffer and command register(offset address 0x10) */
typedef struct _i2c_ic_data_cmd
{
uint32_t dat : 8;
uint32_t cmd : 1;
uint32_t stop : 1;
uint32_t restart : 1;
uint32_t first_data_byte : 1;
uint32_t rsvd : 20; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_data_cmd_t;
/* i2c standard/ultra-fast speed clock scl high count register(offset address 0x14) */
typedef struct _i2c_ic_ss_ufm_scl_hcnt
{
uint32_t cnt : 16;
uint32_t rsvd : 16; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_ss_ufm_scl_hcnt_t;
/* i2c standard/ultra-fast speed clock scl low count register(offset address 0x18) */
typedef struct _i2c_ic_ss_ufm_scl_lcnt
{
uint32_t cnt : 16;
uint32_t rsvd : 16; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_ss_ufm_scl_lcnt_t;
/* i2c fast mode speed clock scl low count/ultra-fast mode speed tbuf idle count register(offset address 0x1c) */
typedef struct _i2c_ic_fs_scl_hcnt_ufm_tbuf_cnt
{
uint32_t cnt : 16;
uint32_t rsvd : 16; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_fs_scl_hcnt_ufm_tbuf_cnt_t;
/* i2c fast mode clock scl low count register(offset address 0x20) */
typedef struct _i2c_ic_fs_scl_lcnt
{
uint32_t cnt : 16;
uint32_t rsvd : 16; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_fs_scl_lcnt_t;
/* i2c high speed mode clock scl high count register(offset address 0x24) */
typedef struct _i2c_ic_hs_scl_hcnt
{
uint32_t cnt : 16;
uint32_t rsvd : 16; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_hs_scl_hcnt_t;
/* i2c high speed mode clock scl low count register(offset address 0x28) */
typedef struct _i2c_ic_hs_scl_lcnt
{
uint32_t cnt : 16;
uint32_t rsvd : 16; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_hs_scl_lcnt_t;
/* i2c interrupt status register(offset address 0x2c) */
typedef struct _i2c_ic_intr_stat
{
uint32_t r_rx_under : 1;
uint32_t r_rx_over : 1;
uint32_t r_rx_full : 1;
uint32_t r_tx_over : 1;
uint32_t r_tx_empty : 1;
uint32_t r_rd_req : 1;
uint32_t r_tx_abrt : 1;
uint32_t r_rx_done : 1;
uint32_t r_activity : 1;
uint32_t r_stop_det : 1;
uint32_t r_start_det : 1;
uint32_t r_gen_call : 1;
uint32_t r_restart_det : 1;
uint32_t r_master_on_hold : 1;
uint32_t r_slc_stuck_at_low : 1;
uint32_t rsvd : 17; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_intr_stat_t;
/* i2c interrupt mask register(offset address 0x30) */
typedef struct _i2c_ic_intr_mask
{
uint32_t m_rx_under : 1;
uint32_t m_rx_over : 1;
uint32_t m_rx_full : 1;
uint32_t m_tx_over : 1;
uint32_t m_tx_empty : 1;
uint32_t m_rd_req : 1;
uint32_t m_tx_abrt : 1;
uint32_t m_rx_done : 1;
uint32_t m_activity : 1;
uint32_t m_stop_det : 1;
uint32_t m_start_det : 1;
uint32_t m_gen_call : 1;
uint32_t m_restart_det : 1;
uint32_t m_master_on_hold : 1;
uint32_t m_slc_stuck_at_low : 1;
uint32_t rsvd : 17; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_intr_mask_t;
/* i2c raw interrupt status register(offset address 0x34) */
typedef struct _i2c_ic_raw_intr_stat
{
uint32_t rx_under : 1;
uint32_t rx_over : 1;
uint32_t rx_full : 1;
uint32_t tx_over : 1;
uint32_t tx_empty : 1;
uint32_t rd_req : 1;
uint32_t tx_abrt : 1;
uint32_t rx_done : 1;
uint32_t activity : 1;
uint32_t stop_det : 1;
uint32_t start_det : 1;
uint32_t gen_call : 1;
uint32_t restart_det : 1;
uint32_t master_on_hold : 1;
uint32_t scl_stuck_at_low : 1;
uint32_t rsvd : 17; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_raw_intr_stat_t;
/* i2c receive FIFO threshold register(offset address 0x38) */
typedef struct _i2c_ic_rx_tl
{
uint32_t tl : 8;
uint32_t rsvd : 24; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_rx_tl_t;
/* i2c transmit FIFO threshold register(offset address 0x3c) */
typedef struct _i2c_ic_tx_tl
{
uint32_t tl : 8;
uint32_t rsvd : 24; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_tx_tl_t;
/* i2c clear combined and individual interrupt register(offset address 0x40) */
typedef struct _i2c_ic_clr_intr
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_intr_t;
/* i2c clear rx under interrupt register(offset address 0x44) */
typedef struct _i2c_ic_clr_rx_under
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_rx_under_t;
/* i2c clear rx over interrupt register(offset address 0x48) */
typedef struct _i2c_ic_clr_rx_over
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_rx_over_t;
/* i2c clear tx over interrupt register(offset address 0x4c) */
typedef struct _i2c_ic_clr_tx_over
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_tx_over_t;
/* i2c clear rd req interrupt register(offset address 0x50) */
typedef struct _i2c_ic_clr_rd_req
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_rd_req_t;
/* i2c clear tx abrt interrupt register(offset address 0x54) */
typedef struct _i2c_ic_clr_tx_abrt
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_tx_abrt_t;
/* i2c clear rx done interrupt register(offset address 0x58) */
typedef struct _i2c_ic_clr_rx_done
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_rx_done_t;
/* i2c clear activity interrupt register(offset address 0x5c) */
typedef struct _i2c_ic_clr_activity
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_activity_t;
/* i2c clear stop det interrupt register(offset address 0x60) */
typedef struct _i2c_clr_stop_det
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_stop_det_t;
/* i2c clear start det interrupt register(offset address 0x64) */
typedef struct _i2c_ic_clr_start_det
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_start_det_t;
/* i2c clear gen call interrupt register(offset address 0x68) */
typedef struct _i2c_ic_clr_gen_call
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_gen_call_t;
/* i2c enable register(offset address 0x6c) */
typedef struct _i2c_ic_enable
{
uint32_t enable : 1;
uint32_t abort : 1;
uint32_t tx_cmd_block : 1;
uint32_t sda_stuck_recovery_enable : 1;
uint32_t rsvd_1 : 12; /* reserved */
uint32_t smbus_clk_reset : 1;
uint32_t smbus_suspned_en : 1;
uint32_t smbus_alert_en : 1;
uint32_t rsvd_2 : 13; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_enable_t;
/* i2c status register(offset address 0x70) */
typedef struct _i2c_ic_status
{
uint32_t activity : 1;
uint32_t tfnf : 1;
uint32_t tfe : 1;
uint32_t rfne : 1;
uint32_t rff : 1;
uint32_t mst_activity : 1;
uint32_t slv_activity : 1;
uint32_t mst_hold_tx_fifo_empty : 1;
uint32_t mst_hold_rx_fifo_full : 1;
uint32_t slv_hold_tx_fifo_empty : 1;
uint32_t slv_hold_rx_fifo_full : 1;
uint32_t sda_stuck_not_recovered : 1;
uint32_t rsvd_1 : 4; /* reserved */
uint32_t smbus_quick_cmd_bit : 1;
uint32_t smbus_slave_addr_valid : 1;
uint32_t smbus_slave_addr_resolved : 1;
uint32_t smbus_suspend_status : 1;
uint32_t smbus_alert : 1;
uint32_t rsvd_2 : 11; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_status_t;
/* i2c transmit fifo level register(offset address 0x74) */
typedef struct _i2c_ic_txflr
{
uint32_t txflr : 5;
uint32_t rsvd : 27; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_txflr_t;
/* i2c receive fifo level register(offset address 0x78) */
typedef struct _i2c_ic_rxflr
{
uint32_t rxflr : 5;
uint32_t rsvd : 27; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_rxflr_t;
/* i2c sda hold time length register(offset address 0x7c) */
typedef struct _i2c_ic_sda_hold
{
uint32_t tx_hold : 16;
uint32_t rx_hold : 8;
uint32_t rsvd : 8; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_sda_hold_t;
/* i2c transmit abort source register(offset address 0x80) */
typedef struct _i2c_ic_tx_abrt_source
{
uint32_t abrt_7b_addr_noack : 1;
uint32_t abrt_10addr1_noack : 1;
uint32_t abrt_10addr2_noack : 1;
uint32_t abrt_txdata_noack : 1;
uint32_t abrt_gcall_noack : 1;
uint32_t abrt_gcall_read : 1;
uint32_t abrt_hs_ackdet : 1;
uint32_t abrt_sbyte_ackdet : 1;
uint32_t abrt_hs_norstrt : 1;
uint32_t abrt_sbyte_norstrt : 1;
uint32_t abrt_10b_rd_norstrt : 1;
uint32_t abrt_master_dis : 1;
uint32_t abrt_lost : 1;
uint32_t abrt_slvflush_txfifo : 1;
uint32_t abrt_slv_arblost : 1;
uint32_t abrt_slvrd_intx : 1;
uint32_t abrt_user_abrt : 1;
uint32_t abrt_sda_stuck_at_low : 1;
uint32_t abrt_device_noack : 1;
uint32_t abrt_device_slvaddr_noack : 1;
uint32_t abrt_device_write : 1;
uint32_t rsvd : 2; /* reserved */
uint32_t tx_flush_cnt : 9;
} __attribute__((packed, aligned(4))) i2c_ic_tx_abrt_source_t;
/* i2c generate slave data nack register(offset address 0x84) */
typedef struct _i2c_ic_slv_data_nack_only
{
uint32_t nack : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_slv_data_nack_only_t;
/* i2c dma control register(offset address 0x88) */
typedef struct _i2c_ic_dma_cr
{
uint32_t rdmae : 1;
uint32_t tdmae : 1;
uint32_t rsvd : 30; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_dma_cr_t;
/* i2c dma transmit data level register(offset address 0x8c) */
typedef struct _i2c_ic_dma_tdlr
{
uint32_t dmatdl : 5;
uint32_t rsvd : 27; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_dma_tdlr_t;
/* i2c dma receive data level register(offset address 0x90) */
typedef struct _i2c_ic_dma_rdlr
{
uint32_t dmardl : 5;
uint32_t rsvd : 27; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_dma_rdlr_t;
/* i2c sda setup register(offset address 0x94) */
typedef struct _i2c_ic_sda_setup
{
uint32_t setup : 8;
uint32_t rsvd : 24; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_sda_setup_t;
/* i2c ack general call register(offset address 0x98) */
typedef struct _i2c_ic_ack_general_call
{
uint32_t ask : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_ack_general_call_t;
/* i2c enable status register(offset address 0x9c) */
typedef struct _i2c_ic_enable_status
{
uint32_t en : 1;
uint32_t slv_disabled_while_busy : 1;
uint32_t slv_rx_data_lost : 1;
uint32_t rsvd : 29; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_enable_status_t;
/* i2c ss, fs, or fm+/ufm spike suppression limit register(offset address 0xa0) */
typedef struct _i2c_ic_fs_ufm_spklen
{
uint32_t spklen : 8;
uint32_t rsvd : 24; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_fs_ufm_spklen_t;
/* i2c hs spike suppression limit register(offset address 0xa4) */
typedef struct _i2c_ic_hs_spklen
{
uint32_t spklen : 8;
uint32_t rsvd : 24; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_hs_spklen_t;
/* i2c clear restart det interrupt register(offset address 0xa8) */
typedef struct _i2c_ic_clr_restart_det
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_restart_det_t;
/* i2c scl stuck at low timeout register(offset address 0xac) */
typedef struct _i2c_ic_scl_stuck_at_low_timeout
{
uint32_t timeout : 32;
} __attribute__((packed, aligned(4))) i2c_ic_scl_stuck_at_low_timeout_t;
/* i2c sda stuck at low timeout register(offset address 0xb0) */
typedef struct _i2c_ic_sda_stuck_at_low_timeout
{
uint32_t timeout : 32;
} __attribute__((packed, aligned(4))) i2c_ic_sda_stuck_at_low_timeout_t;
/* i2c clear scl stuck at low detect interrupt register(offset address 0xb4) */
typedef struct _i2c_ic_clr_slc_stuck_det
{
uint32_t clr : 1;
uint32_t rsvd : 31; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_slc_stuck_det_t;
/* i2c device id register(offset address 0xb8) */
typedef struct _i2c_ic_device_id
{
uint32_t device_id : 24;
uint32_t rsvd : 8; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_device_id_t;
/* i2c smbus slave clock extend timeout register(offset address 0xbc) */
typedef struct _i2c_ic_smbus_clk_low_sext
{
uint32_t timeout : 32;
} __attribute__((packed, aligned(4))) i2c_ic_smbus_clk_low_sext_t;
/* i2c smbus master clock extend timeout register(offset address 0xc0) */
typedef struct _i2c_ic_smbus_clk_low_mext
{
uint32_t timeout : 32;
} __attribute__((packed, aligned(4))) i2c_ic_smbus_clk_low_mext_t;
/* i2c smbus master thigh max bus-idle count register(offset address 0xc4) */
typedef struct _i2c_ic_smbus_thigh_max_idle_count
{
uint32_t cnt : 16;
uint32_t rsvd : 16; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_smbus_thigh_max_idle_count_t;
/* i2c smbus interrupt status register(offset address 0xc8) */
typedef struct _i2c_ic_smbus_intr_stat
{
uint32_t r_slv_clock_extnd_timeout : 1;
uint32_t r_mst_clock_extnd_timeout : 1;
uint32_t r_quick_cmd_det : 1;
uint32_t r_host_notify_mst_det : 1;
uint32_t r_arp_prepare_cmd_det : 1;
uint32_t r_arp_rst_cmd_det : 1;
uint32_t r_arp_get_udid_cmd_det : 1;
uint32_t r_arp_assgn_addr_cmd_det : 1;
uint32_t r_slv_rx_pec_nack : 1;
uint32_t r_smbus_suspend_det : 1;
uint32_t r_smbus_alert_det : 1;
uint32_t rsvd : 21; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_smbus_intr_stat_t;
/* i2c smbus interrupt mask register(offset address 0xcc) */
typedef struct _i2c_ic_smbus_intr_mask
{
uint32_t m_slv_clock_extnd_timeout : 1;
uint32_t m_mst_clock_extnd_timeout : 1;
uint32_t m_quick_cmd_det : 1;
uint32_t m_host_notify_mst_det : 1;
uint32_t m_arp_prepare_cmd_det : 1;
uint32_t m_arp_rst_cmd_det : 1;
uint32_t m_arp_get_udid_cmd_det : 1;
uint32_t m_arp_assgn_addr_cmd_det : 1;
uint32_t m_slv_rx_pec_nack : 1;
uint32_t m_smbus_suspend_det : 1;
uint32_t m_smbus_alert_det : 1;
uint32_t rsvd : 21; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_smbus_intr_mask_t;
/* i2c smbus raw interrupt status register(offset address 0xd0) */
typedef struct _i2c_ic_smbus_raw_intr_stat
{
uint32_t slv_clock_extnd_timeout : 1;
uint32_t mst_clock_extnd_timeout : 1;
uint32_t quick_cmd_det : 1;
uint32_t host_notify_mst_det : 1;
uint32_t arp_prepare_cmd_det : 1;
uint32_t arp_rst_cmd_det : 1;
uint32_t arp_get_udid_cmd_det : 1;
uint32_t arp_assgn_addr_cmd_det : 1;
uint32_t slv_rx_pec_nack : 1;
uint32_t smbus_suspend_det : 1;
uint32_t smbus_alert_det : 1;
uint32_t rsvd : 21; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_smbus_raw_intr_stat_t;
/* i2c smbus clear interrupt register(offset address 0xd4) */
typedef struct _i2c_ic_clr_smbus_intr
{
uint32_t slv_clock_extnd_timeout : 1;
uint32_t mst_clock_extnd_timeout : 1;
uint32_t quick_cmd_det : 1;
uint32_t host_notify_mst_det : 1;
uint32_t arp_prepare_cmd_det : 1;
uint32_t arp_rst_cmd_det : 1;
uint32_t arp_get_udid_cmd_det : 1;
uint32_t arp_assgn_addr_cmd_det : 1;
uint32_t slv_rx_pec_nack : 1;
uint32_t smbus_suspend_det : 1;
uint32_t smbus_alert_det : 1;
uint32_t rsvd : 21; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_clr_smbus_intr_t;
/* i2c optional slave address register(offset address 0xd8) */
typedef struct _i2c_ic_optional_sar
{
uint32_t sar : 7;
uint32_t rsvd : 25; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_optional_sar_t;
/* i2c smbus udid lsb register(offset address 0xdc) */
typedef struct _i2c_ic_smbus_udid_lsb
{
uint32_t udid_lsb : 32;
} __attribute__((packed, aligned(4))) i2c_ic_smbus_udid_lsb_t;
/* i2c component parameter 1 register(offset address 0xf4) */
typedef struct _i2c_ic_comp_param_1
{
uint32_t apb_data_width : 2;
uint32_t max_speed_mode : 2;
uint32_t hc_count_values : 1;
uint32_t intr_io : 1;
uint32_t has_dma : 1;
uint32_t add_encoded_params : 1;
uint32_t rx_buffer_depth : 8;
uint32_t tx_buffer_depth : 8;
uint32_t rsvd : 8; /* reserved */
} __attribute__((packed, aligned(4))) i2c_ic_comp_param_1_t;
/* i2c component version register(offset address 0xf8) */
typedef struct _i2c_ic_comp_version
{
uint32_t version : 32;
} __attribute__((packed, aligned(4))) i2c_ic_comp_version_t;
/* i2c component type register(offset address 0xfc) */
typedef struct _i2c_ic_comp_type
{
uint32_t type : 32;
} __attribute__((packed, aligned(4))) i2c_ic_comp_type_t;
/* i2c register */
typedef struct _i2c
{
i2c_ic_con_t con; /* 0x00 */
i2c_ic_tar_t tar; /* 0x04 */
i2c_ic_sar_t sar; /* 0x08 */
i2c_ic_hs_maddr_t hs_maddr; /* 0x0c */
i2c_ic_data_cmd_t data_cmd; /* 0x10 */
i2c_ic_ss_ufm_scl_hcnt_t ss_ufm_scl_hcnt; /* 0x14 */
i2c_ic_ss_ufm_scl_lcnt_t ss_ufm_scl_lcnt; /* 0x18 */
i2c_ic_fs_scl_hcnt_ufm_tbuf_cnt_t fs_scl_hcnt_ufm_tbuf_cnt; /* 0x1c */
i2c_ic_fs_scl_lcnt_t fs_scl_lcnt; /* 0x20 */
i2c_ic_hs_scl_hcnt_t hs_scl_hcnt; /* 0x24 */
i2c_ic_hs_scl_lcnt_t hs_scl_lcnt; /* 0x28 */
i2c_ic_intr_stat_t intr_stat; /* 0x2c */
i2c_ic_intr_mask_t intr_mask; /* 0x30 */
i2c_ic_raw_intr_stat_t raw_intr_stat; /* 0x34 */
i2c_ic_rx_tl_t rx_tl; /* 0x38 */
i2c_ic_tx_tl_t tx_tl; /* 0x3c */
i2c_ic_clr_intr_t clr_intr; /* 0x40 */
i2c_ic_clr_rx_under_t clr_rx_under; /* 0x44 */
i2c_ic_clr_rx_over_t clr_rx_over; /* 0x48 */
i2c_ic_clr_tx_over_t clr_tx_over; /* 0x4c */
i2c_ic_clr_rd_req_t clr_rd_req; /* 0x50 */
i2c_ic_clr_tx_abrt_t clr_tx_abrt; /* 0x54 */
i2c_ic_clr_rx_done_t clr_rx_done; /* 0x58 */
i2c_ic_clr_activity_t clr_activity; /* 0x5c */
i2c_ic_clr_stop_det_t clr_stop_det; /* 0x60 */
i2c_ic_clr_start_det_t clr_start_det; /* 0x64 */
i2c_ic_clr_gen_call_t clr_gen_call; /* 0x68 */
i2c_ic_enable_t enable; /* 0x6c */
i2c_ic_status_t status; /* 0x70 */
i2c_ic_txflr_t txflr; /* 0x74 */
i2c_ic_rxflr_t rxflr; /* 0x78 */
i2c_ic_sda_hold_t sda_hold; /* 0x7c */
i2c_ic_tx_abrt_source_t tx_abrt_source; /* 0x80 */
i2c_ic_slv_data_nack_only_t slv_data_nack_only; /* 0x84 */
i2c_ic_dma_cr_t dma_cr; /* 0x88 */
i2c_ic_dma_tdlr_t dma_tdlr; /* 0x8c */
i2c_ic_dma_rdlr_t dma_rdlr; /* 0x90 */
i2c_ic_sda_setup_t sda_setup; /* 0x94 */
i2c_ic_ack_general_call_t ack_general_call; /* 0x98 */
i2c_ic_enable_status_t enable_status; /* 0x9c */
i2c_ic_fs_ufm_spklen_t fs_ufm_spklen; /* 0xa0 */
i2c_ic_hs_spklen_t hs_spklen; /* 0xa4 */
i2c_ic_clr_restart_det_t clr_restart_det; /* 0xa8 */
i2c_ic_scl_stuck_at_low_timeout_t scl_stuck_at_low_timeout; /* 0xac */
i2c_ic_sda_stuck_at_low_timeout_t sda_stuck_at_low_timeout; /* 0xb0 */
i2c_ic_clr_slc_stuck_det_t clr_slc_stuck_det; /* 0xb4 */
i2c_ic_device_id_t device_id; /* 0xb8 */
i2c_ic_smbus_clk_low_sext_t smbus_clk_low_sext; /* 0xbc */
i2c_ic_smbus_clk_low_mext_t smbus_clk_low_mext; /* 0xc0 */
i2c_ic_smbus_thigh_max_idle_count_t smbus_thigh_max_idle_count; /* 0xc4 */
i2c_ic_smbus_intr_stat_t smbus_intr_stat; /* 0xc8 */
i2c_ic_smbus_intr_mask_t smbus_intr_mask; /* 0xcc */
i2c_ic_smbus_raw_intr_stat_t smbus_raw_intr_stat; /* 0xd0 */
i2c_ic_clr_smbus_intr_t clr_smbus_intr; /* 0xd4 */
i2c_ic_optional_sar_t optional_sar; /* 0xd8 */
i2c_ic_smbus_udid_lsb_t smbus_udid_lsb; /* 0xdc */
uint32_t rsvd_1[5]; /* 0xe0-0xf0 reserved */
i2c_ic_comp_param_1_t comp_param_1; /* 0xf4 */
i2c_ic_comp_version_t comp_version; /* 0xf8 */
i2c_ic_comp_type_t comp_type; /* 0xfc */
} __attribute__((packed, aligned(4))) i2c_t;
#endif /* __DRV_I2C_H__ */

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

@@ -29,7 +29,13 @@ if GetDepend('BSP_UTEST_DRIVERS'):
if GetDepend('BSP_USING_RTC'):
src += ['test_rtc.c']
if GetDepend('BSP_USING_I2C'):
src += ['test_i2c.c']
if GetDepend('BSP_USING_SPI'):
src += ['test_spi.c']
group = DefineGroup('utestcases', src, depend = [''])
Return('group')

View File

@@ -0,0 +1,204 @@
/* 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 <utest.h>
#include <string.h>
#include "drv_i2c.h"
#include "drv_pinctrl.h"
#include "drv_gpio.h"
/*
* 测试K230 I2C的主从机通信在这里采用I2C0作为测试对象
*
* 硬件平台:
* 测试的硬件平台为庐山派开发板使用的I2C0引脚是GPIO048(SCL)
* 和GPIO049(SDA)。
*
* 测试说明:
* 1. 测试I2C0主机模式
* 主机模式下主机向从机发送16字节数据不包括写读地址
* 然后再读取回来进行校验共执行两次分别是400kHz和1MHz速率。
* 注使用的从机为AT24C08 EEPROM设备地址为0x50。
*/
#define I2C_NAME "i2c0"
#define TARGET_ADDR 0x50
#define TEST_BUFFER_SIZE 16
#define I2C_SCL_PIN 48
#define I2C_SDA_PIN 49
#define I2C_SCL_PIN_AF IOMUX_FUNC4
#define I2C_SDA_PIN_AF IOMUX_FUNC4
static void test_i2c0_deinit_pin(void)
{
k230_pinctrl_set_function(I2C_SCL_PIN, IOMUX_FUNC1);
k230_pinctrl_set_function(I2C_SDA_PIN, IOMUX_FUNC1);
k230_pinctrl_set_oe(I2C_SCL_PIN, 0);
k230_pinctrl_set_oe(I2C_SDA_PIN, 0);
k230_pinctrl_set_ie(I2C_SCL_PIN, 1);
k230_pinctrl_set_ie(I2C_SDA_PIN, 1);
kd_pin_mode(I2C_SCL_PIN, GPIO_DM_INPUT);
kd_pin_mode(I2C_SDA_PIN, GPIO_DM_INPUT);
}
static void test_i2c0_init_pin(void)
{
k230_pinctrl_set_function(I2C_SCL_PIN, I2C_SCL_PIN_AF); // I2C0_SCL
k230_pinctrl_set_function(I2C_SDA_PIN, I2C_SDA_PIN_AF); // I2C0_SDA
k230_pinctrl_set_oe(I2C_SCL_PIN, 1);
k230_pinctrl_set_oe(I2C_SDA_PIN, 1);
k230_pinctrl_set_ie(I2C_SCL_PIN, 1);
k230_pinctrl_set_ie(I2C_SDA_PIN, 1);
}
static int test_i2c_check_pin(void)
{
test_i2c0_deinit_pin();
if(kd_pin_read(I2C_SCL_PIN) != 1 || kd_pin_read(I2C_SDA_PIN) != 1)
{
LOG_W("i2c bus is not idle, try to recover it.");
k230_pinctrl_set_oe(I2C_SCL_PIN, 1);
kd_pin_mode(I2C_SCL_PIN, GPIO_DM_OUTPUT);
for(rt_uint8_t i = 0; i < 9; i++)
{
kd_pin_write(I2C_SCL_PIN, 0);
rt_hw_us_delay(2);
kd_pin_write(I2C_SCL_PIN, 1);
rt_hw_us_delay(2);
}
k230_pinctrl_set_oe(I2C_SCL_PIN, 0);
kd_pin_mode(I2C_SCL_PIN, GPIO_DM_INPUT);
}
if(kd_pin_read(I2C_SCL_PIN) != 1 || kd_pin_read(I2C_SDA_PIN) != 1)
{
LOG_E("i2c bus recover failed");
return -RT_ERROR;
}
LOG_I("i2c bus(pin: %u, %u) is idle, init i2c bus pin", I2C_SCL_PIN, I2C_SDA_PIN);
test_i2c0_init_pin();
return RT_EOK;
}
static void _test_i2c0_master(rt_uint8_t *buffer_w, rt_uint8_t *buffer_r, rt_uint32_t size, rt_uint32_t speed)
{
rt_err_t ret = RT_EOK;
struct rt_i2c_bus_device *dev;
struct rt_i2c_msg msgs[2];
dev = rt_i2c_bus_device_find(I2C_NAME);
uassert_not_null(dev);
rt_i2c_control(dev, RT_I2C_DEV_CTRL_CLK, (void *)&speed);
msgs[0].addr = TARGET_ADDR;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = buffer_w;
msgs[0].len = size + 1;
if(rt_i2c_transfer(dev, msgs, 1) != 1)
{
LOG_E("i2c transfer failed");
uassert_true(0);
}
rt_thread_mdelay(10);
msgs[0].addr = TARGET_ADDR;
msgs[0].flags = RT_I2C_WR | RT_I2C_NO_STOP;
msgs[0].buf = &buffer_r[0];
msgs[0].len = 1;
msgs[1].addr = TARGET_ADDR;
msgs[1].flags = RT_I2C_RD | RT_I2C_NO_START;
msgs[1].buf = &buffer_r[1];
msgs[1].len = size;
if(rt_i2c_transfer(dev, msgs, 2) != 2)
{
LOG_E("i2c transfer failed");
uassert_true(0);
}
LOG_I("Read data:\n");
for(rt_uint8_t i = 1; i < size + 1; i++)
{
LOG_I("0x%02X ", buffer_r[i]);
}
uassert_buf_equal(buffer_w + 1, buffer_r + 1, size);
}
static void test_i2c0_master(void)
{
rt_uint8_t buffer_w[TEST_BUFFER_SIZE + 1];
rt_uint8_t buffer_r[TEST_BUFFER_SIZE + 1];
rt_uint32_t size = TEST_BUFFER_SIZE;
rt_uint32_t speed = 400000; // 400kHz
memset(buffer_w + 1, 0xAA, TEST_BUFFER_SIZE);
buffer_w[0] = 0x00; // memory address
memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1);
_test_i2c0_master(buffer_w, buffer_r, size, speed);
speed = 1000000; // 1MHz
memset(buffer_w + 1, 0x55, TEST_BUFFER_SIZE);
buffer_w[0] = 0x00; // memory address
memset(buffer_r, 0x00, TEST_BUFFER_SIZE + 1);
_test_i2c0_master(buffer_w, buffer_r, size, speed);
}
static void testcase(void)
{
LOG_I("This is a i2c test case.\n");
UTEST_UNIT_RUN(test_i2c0_master);
}
static rt_err_t utest_tc_init(void)
{
return test_i2c_check_pin();
}
static rt_err_t utest_tc_cleanup(void)
{
LOG_I("i2c bus pin deinit.\n");
test_i2c0_deinit_pin();
return RT_EOK;
}
UTEST_TC_EXPORT(testcase, "bsp.k230.drivers.i2c", utest_tc_init, utest_tc_cleanup, 100);

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

@@ -276,6 +276,7 @@
#define RT_USING_SAL
#define SAL_INTERNET_CHECK
#define SOCKET_TABLE_STEP_LEN 4
/* Docking with protocol stacks */
@@ -502,6 +503,10 @@
/* GD32 Drivers */
/* end of GD32 Drivers */
/* HPMicro SDK */
/* end of HPMicro SDK */
/* end of HAL & SDK Drivers */
/* sensors drivers */

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 a file, add the path to the file in file_path.
dir_path:
- CMSIS
- VangoV85xx_standard_peripheral
# 从 .ignore_format.yml 迁移的规则
/sam*/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,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;
# 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/N32_Std_Driver
# 从 .ignore_format.yml 迁移的规则
/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;
# 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.
file_path:
dir_path:
- Libraries
# 从 .ignore_format.yml 迁移的规则
/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;
# 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
# 从 .ignore_format.yml 迁移的规则
/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 a file, add the path to the file in file_path.
dir_path:
- CMSIS
- VangoV85xxP_standard_peripheral
# 从 .ignore_format.yml 迁移的规则
/Libraries/

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 a file, add the path to the file in file_path.
dir_path:
- bsp
# 从 .ignore_format.yml 迁移的规则
/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>
#endif
#ifdef RT_USING_VBUS
#include <vbus.h>
#endif
/* thread phase init */
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);
#endif
#endif
#ifdef RT_USING_VBUS
rt_vbus_do_init();
#endif
}
/*the led thread*/
@@ -45,8 +37,6 @@ static struct rt_thread led_thread;
static void led_thread_entry(void *parameter)
{
rt_device_t led_dev;
rt_device_t vbus_dev;
rt_err_t err;
rt_led_hw_init();
@@ -57,32 +47,14 @@ static void led_thread_entry(void *parameter)
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)
{
rt_uint8_t led_value;
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());
}
rt_uint8_t led_value = 1;
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);
int rt_hw_board_heap_init(void);
int rt_vbus_do_init(void);
#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
// </section>
#define RT_USING_VBUS
#define _RT_VBUS_RING_SZ 64
#define RT_VBUS_GUEST_VIRQ 0
// </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>
#endif
#ifdef RT_USING_VBUS
#include <vbus.h>
#endif
static const unsigned char _M0_CODE[] rt_section("M0_CODE") = {
// #include "M0_CODE.h"
};
@@ -64,10 +60,6 @@ void rt_init_thread_entry(void *parameter)
#endif
#endif
#ifdef RT_USING_VBUS
rt_vbus_do_init();
#endif
_boot_M0();
}
@@ -79,8 +71,6 @@ static void led_thread_entry(void *parameter)
{
rt_uint8_t led_value;
rt_device_t led_dev;
rt_device_t vbus_dev;
rt_err_t err;
rt_led_hw_init();
@@ -91,34 +81,11 @@ static void led_thread_entry(void *parameter)
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;
while (1)
{
int len;
led_dev->write(led_dev, 0, &led_value, sizeof(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);
}
}

View File

@@ -50,6 +50,5 @@ extern int __bss_end;
void rt_hw_board_init(void);
int rt_hw_board_heap_init(void);
int rt_vbus_do_init(void);
#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
// </section>
#define RT_USING_VBUS
#define RT_VBUS_GUEST_VIRQ 0
#define _RT_VBUS_RING_SZ 64
// </RDTConfigurator>
#define RT_CPUS_NR 1
#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_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

@@ -50,7 +50,10 @@ if GetDepend(['RT_USING_DAC']):
src += ['drv_dac.c']
if GetDepend(['RT_USING_CAN']):
src += ['drv_can.c']
if GetDepend(['SOC_SERIES_STM32H7']):
src += ['drv_fdcan.c']
else:
src += ['drv_can.c']
if GetDepend(['RT_USING_PM']):
src += ['drv_pm.c']

View File

@@ -145,6 +145,17 @@ extern "C" {
#endif /* UART5_DMA_RX_CONFIG */
#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
}
#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;
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
{
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;
@@ -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.
*/
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;
hcan = &((struct stm32_can *) can->parent.user_data)->CanHandle;
@@ -515,32 +527,31 @@ static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t
(state == HAL_CAN_STATE_LISTENING))
{
/*check select mailbox is empty */
uint32_t mailbox_mask;
uint32_t tme_flag;
switch (1 << box_num)
{
case CAN_TX_MAILBOX0:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0) != SET)
{
/* Return function status */
return -RT_ERROR;
}
mailbox_mask = CAN_TX_MAILBOX0;
tme_flag = CAN_TSR_TME0;
break;
case CAN_TX_MAILBOX1:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1) != SET)
{
/* Return function status */
return -RT_ERROR;
}
mailbox_mask = CAN_TX_MAILBOX1;
tme_flag = CAN_TSR_TME1;
break;
case CAN_TX_MAILBOX2:
if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME2) != SET)
{
/* Return function status */
return -RT_ERROR;
}
mailbox_mask = CAN_TX_MAILBOX2;
tme_flag = CAN_TSR_TME2;
break;
default:
RT_ASSERT(0);
break;
return -RT_ERROR;
}
if (HAL_IS_BIT_SET(hcan->Instance->TSR, tme_flag) != SET)
{
return -RT_ERROR;
}
if (RT_CAN_STDID == pmsg->ide)
@@ -649,7 +660,7 @@ static rt_ssize_t _can_sendmsg_nonblocking(struct rt_can_device *can, const void
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;
CAN_HandleTypeDef *hcan;

View File

@@ -0,0 +1,703 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-02-24 heyuan the first version
* 2020-08-17 malongwei Fix something
* 2025-10-27 pandafeng Fix some bugs
*/
#include "drv_fdcan.h"
#if defined(RT_USING_CAN) && defined(RT_CAN_USING_CANFD)
#if defined(BSP_USING_FDCAN1) || defined(BSP_USING_FDCAN2)
//#define DRV_DEBUG
#define LOG_TAG "drv_fdcan"
#include <drv_log.h>
#ifdef BSP_USING_FDCAN1
static stm32_fdcan_t st_DrvCan1=
{
.name = "fdcan1",
.fdcanHandle.Instance = FDCAN1,
};
#endif
#ifdef BSP_USING_FDCAN2
static stm32_fdcan_t st_DrvCan2=
{
.name = "fdcan2",
.fdcanHandle.Instance = FDCAN2,
};
#endif
/* 40MHz CAN clock */
static const stm32_fdcan_timing_t st_FDCAN_ArbTiming[] =
{
{CAN1MBaud, {1, 29, 10, 8, 0}}, /* 1Mbps */
{CAN800kBaud, {1, 37, 12, 8, 0}}, /* 800kbps */
{CAN500kBaud, {1, 59, 20, 8, 0}}, /* 500kbps */
{CAN250kBaud, {2, 63, 16, 8, 0}}, /* 250kbps */
{CAN125kBaud, {5, 55, 8, 8, 0}}, /* 125kbps */
{CAN100kBaud, {8, 41, 8, 8, 0}}, /* 100kbps */
{CAN50kBaud, {16, 41, 8, 8, 0}}, /* 50kbps */
{CAN20kBaud, {40,41,8,8,0}}, /* 20kbps */
{CAN10kBaud, {100,31,8,8,0}} /* 10kbps */
};
/* 40MHz CAN clock */
static const stm32_fdcan_timing_t st_FDCAN_DataTiming[] =
{
{CAN1MBaud * 8, {1, 3, 1, 1, 0}}, /* 8Mbps */
{CAN500kBaud *8, {1, 7, 2, 1, 0}}, /* 4Mbps */
{CAN250kBaud * 8, {4, 3, 1, 1, 0}}, /* 2Mbps */
{CAN125kBaud *8, {1, 31, 8, 1, 0}}, /* 1Mkbps */
{CAN100kBaud*8, {2, 19, 5, 1, 0}}, /* 800kbps */
{CAN50kBaud *8, {5, 15, 4, 1, 0}}, /* 400kbps */
};
/**
* @brief Convert CAN-FD frame length to DLC (Data Length Code)
*
* CAN-FD DLC mapping (length → DLC):
* Length 0~8 -> DLC 0~8
* Length 9~12 -> DLC 9
* Length 13~16 -> DLC 10
* Length 17~20 -> DLC 11
* Length 21~24 -> DLC 12
* Length 25~32 -> DLC 13
* Length 33~48 -> DLC 14
* Length 49~64 -> DLC 15
*
* @param len Frame length in bytes (0~64)
* @return DLC code (0~15)
*/
uint8_t length_to_dlc(uint8_t len) {
return (len <= 8) ? len :
(len <= 12) ? 9 :
(len <= 16) ? 10 :
(len <= 20) ? 11 :
(len <= 24) ? 12 :
(len <= 32) ? 13 :
(len <= 48) ? 14 : 15;
}
/**
* @brief 获取 FDCAN 仲裁段波特率配置索引
*/
static uint32_t _inline_get_ArbBaudIndex(uint32_t baud_rate)
{
uint32_t len = sizeof(st_FDCAN_ArbTiming) / sizeof(st_FDCAN_ArbTiming[0]);
for (uint32_t i = 0; i < len; i++)
{
if (st_FDCAN_ArbTiming[i].u32Baudrate == baud_rate)
return i;
}
return -1;
}
/**
* @brief Get the index of the FDCAN data segment bitrate configuration.
*
* @param baud_rate The desired data phase baud rate (in bps).
* @retval uint32_t Index of the matching data segment configuration.
* Returns -1 if no matching configuration is found.
*/
static uint32_t _inline_get_DataBaudIndex(uint32_t baud_rate)
{
uint32_t len = sizeof(st_FDCAN_DataTiming) / sizeof(st_FDCAN_DataTiming[0]);
for (uint32_t i = 0; i < len; i++)
{
if (st_FDCAN_DataTiming[i].u32Baudrate == baud_rate)
return i;
}
return -1;
}
static rt_err_t _inline_can_config(struct rt_can_device *can, struct can_configure *cfg)
{
stm32_fdcan_t *pdrv_can;
rt_uint32_t tmp_u32Index;
RT_ASSERT(can);
RT_ASSERT(cfg);
pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
RT_ASSERT(pdrv_can);
pdrv_can->fdcanHandle.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
pdrv_can->fdcanHandle.Init.AutoRetransmission = ENABLE;
pdrv_can->fdcanHandle.Init.TransmitPause = DISABLE;
pdrv_can->fdcanHandle.Init.ProtocolException = ENABLE;
switch (cfg->mode)
{
case RT_CAN_MODE_NORMAL:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
break;
case RT_CAN_MODE_LISTEN:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_BUS_MONITORING;
break;
case RT_CAN_MODE_LOOPBACK:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_INTERNAL_LOOPBACK;
break;
default:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
break;
}
uint32_t arb_idx = _inline_get_ArbBaudIndex(cfg->baud_rate);
if (arb_idx == (uint32_t)-1)
{
LOG_E("not support %d baudrate", cfg->baud_rate);
return -RT_ERROR;
}
/* FDCAN arbitration segment */
pdrv_can->fdcanHandle.Init.NominalPrescaler = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.prescaler;
pdrv_can->fdcanHandle.Init.NominalSyncJumpWidth = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.num_sjw;
pdrv_can->fdcanHandle.Init.NominalTimeSeg1 = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.num_seg1;
pdrv_can->fdcanHandle.Init.NominalTimeSeg2 = st_FDCAN_ArbTiming[arb_idx].cam_bit_timing.num_seg2;
#ifdef RT_CAN_USING_CANFD
if(cfg->enable_canfd) {
uint32_t data_idx = _inline_get_DataBaudIndex(cfg->baud_rate_fd);
if (data_idx == (uint32_t)-1)
{
LOG_E("not support %d baudrate", cfg->baud_rate_fd);
return -RT_ERROR;
}
/* 数据段 */
pdrv_can->fdcanHandle.Init.DataPrescaler = st_FDCAN_DataTiming[data_idx].cam_bit_timing.prescaler;
pdrv_can->fdcanHandle.Init.DataSyncJumpWidth = st_FDCAN_DataTiming[data_idx].cam_bit_timing.num_sjw;
pdrv_can->fdcanHandle.Init.DataTimeSeg1 = st_FDCAN_DataTiming[data_idx].cam_bit_timing.num_seg1;
pdrv_can->fdcanHandle.Init.DataTimeSeg2 = st_FDCAN_DataTiming[data_idx].cam_bit_timing.num_seg2;
}
#endif
/* Configure Message RAM */
if(pdrv_can->fdcanHandle.Instance == FDCAN1)
{
pdrv_can->fdcanHandle.Init.MessageRAMOffset = 0;
}
else
{
pdrv_can->fdcanHandle.Init.MessageRAMOffset = 1280;
}
pdrv_can->fdcanHandle.Init.StdFiltersNbr = 2;
pdrv_can->fdcanHandle.Init.ExtFiltersNbr = 2;
pdrv_can->fdcanHandle.Init.RxFifo0ElmtsNbr = 1;
pdrv_can->fdcanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;
pdrv_can->fdcanHandle.Init.RxFifo1ElmtsNbr = 0;
pdrv_can->fdcanHandle.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64;
pdrv_can->fdcanHandle.Init.RxBuffersNbr = 0;
pdrv_can->fdcanHandle.Init.RxBufferSize = FDCAN_DATA_BYTES_64;
pdrv_can->fdcanHandle.Init.TxEventsNbr = 0;
pdrv_can->fdcanHandle.Init.TxBuffersNbr = 3;
pdrv_can->fdcanHandle.Init.TxFifoQueueElmtsNbr = 0;
pdrv_can->fdcanHandle.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
pdrv_can->fdcanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_64;
if (HAL_FDCAN_Init(&pdrv_can->fdcanHandle) != HAL_OK)
{
return -RT_ERROR;
}
/* default filter config */
HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle , &pdrv_can->FilterConfig);
/*init fdcan tx header*/
pdrv_can->TxHeader.Identifier = 0x000000;
pdrv_can->TxHeader.IdType = FDCAN_EXTENDED_ID;
pdrv_can->TxHeader.TxFrameType = FDCAN_DATA_FRAME;
pdrv_can->TxHeader.DataLength = FDCAN_DLC_BYTES_8;
pdrv_can->TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
pdrv_can->TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
pdrv_can->TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
pdrv_can->TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
pdrv_can->TxHeader.MessageMarker = 0;
/* can start */
HAL_FDCAN_Start(&pdrv_can->fdcanHandle);
return RT_EOK;
}
static rt_err_t _inline_can_filter_config(stm32_fdcan_t *pdrv_can,struct rt_can_filter_config *puser_can_filter_config)
{
int tmp_i32IndexCount;
RT_ASSERT(pdrv_can);
RT_ASSERT(puser_can_filter_config);
/* get default filter */
for (tmp_i32IndexCount = 0; tmp_i32IndexCount < puser_can_filter_config->count; tmp_i32IndexCount++)
{
pdrv_can->FilterConfig.FilterIndex = puser_can_filter_config->items[tmp_i32IndexCount].hdr_bank;
pdrv_can->FilterConfig.FilterID1 = puser_can_filter_config->items[tmp_i32IndexCount].id;
pdrv_can->FilterConfig.FilterID2 = puser_can_filter_config->items[tmp_i32IndexCount].mask;
if(puser_can_filter_config->items[tmp_i32IndexCount].ide == RT_CAN_EXTID)
{
pdrv_can->FilterConfig.IdType = FDCAN_EXTENDED_ID;
}
else
{
pdrv_can->FilterConfig.IdType = FDCAN_STANDARD_ID;
}
pdrv_can->FilterConfig.FilterType = FDCAN_FILTER_MASK;
pdrv_can->FilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
if(HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle , &pdrv_can->FilterConfig) != HAL_OK)
{
return -RT_ERROR;
}
}
return RT_EOK;
}
static rt_err_t _inline_can_control(struct rt_can_device *can, int cmd, void *arg)
{
rt_uint32_t argval;
stm32_fdcan_t *pdrv_can;
struct rt_can_filter_config *filter_cfg;
RT_ASSERT(can != RT_NULL);
pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
RT_ASSERT(pdrv_can != RT_NULL);
switch (cmd) {
case RT_DEVICE_CTRL_CLR_INT:
argval = (rt_uint32_t) arg;
if (argval == RT_DEVICE_FLAG_INT_RX) {
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE);
} else if (argval == RT_DEVICE_FLAG_INT_TX) {
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_FIFO_EMPTY);
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE);
} else if (argval == RT_DEVICE_CAN_INT_ERR) {
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_WARNING);
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_PASSIVE);
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_LOGGING_OVERFLOW);
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_BUS_OFF);
HAL_FDCAN_DeactivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ARB_PROTOCOL_ERROR);
}
break;
case RT_DEVICE_CTRL_SET_INT:
argval = (rt_uint32_t) arg;
if (argval == RT_DEVICE_FLAG_INT_RX) {
HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
FDCAN_INTERRUPT_LINE0);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
if (FDCAN1 == pdrv_can->fdcanHandle.Instance) {
HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
} else {
HAL_NVIC_SetPriority(FDCAN2_IT0_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(FDCAN2_IT0_IRQn);
}
} else if (argval == RT_DEVICE_FLAG_INT_TX) {
HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_INTERRUPT_LINE1);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER0);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER1);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER2);
if (FDCAN1 == pdrv_can->fdcanHandle.Instance) {
HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0, 2);
HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
} else {
HAL_NVIC_SetPriority(FDCAN2_IT1_IRQn, 0, 2);
HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
}
} else if (argval == RT_DEVICE_CAN_INT_ERR) {
HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_BUS_OFF, FDCAN_INTERRUPT_LINE1);
HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_WARNING, FDCAN_INTERRUPT_LINE1);
HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_PASSIVE, FDCAN_INTERRUPT_LINE1);
HAL_FDCAN_ConfigInterruptLines(&pdrv_can->fdcanHandle, FDCAN_IT_ARB_PROTOCOL_ERROR,
FDCAN_INTERRUPT_LINE1);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_BUS_OFF, 0);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_WARNING, 0);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ERROR_PASSIVE, 0);
HAL_FDCAN_ActivateNotification(&pdrv_can->fdcanHandle, FDCAN_IT_ARB_PROTOCOL_ERROR, 0);
if (FDCAN1 == pdrv_can->fdcanHandle.Instance) {
HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0, 2);
HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
} else {
HAL_NVIC_SetPriority(FDCAN2_IT1_IRQn, 0, 2);
HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
}
}
break;
case RT_CAN_CMD_SET_FILTER:
if (RT_NULL == arg) {
/* default filter config */
HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle, &pdrv_can->FilterConfig);
} else {
filter_cfg = (struct rt_can_filter_config *) arg;
_inline_can_filter_config(pdrv_can, filter_cfg);
}
break;
case RT_CAN_CMD_SET_MODE:
argval = (rt_uint32_t) arg;
if (argval != RT_CAN_MODE_NORMAL &&
argval != RT_CAN_MODE_LISTEN &&
argval != RT_CAN_MODE_LOOPBACK &&
argval != RT_CAN_MODE_LOOPBACKANLISTEN) {
return -RT_ERROR;
}
if (argval != pdrv_can->device.config.mode) {
pdrv_can->device.config.mode = argval;
return _inline_can_config(&pdrv_can->device, &pdrv_can->device.config);
}
break;
case RT_CAN_CMD_SET_BAUD:
argval = (rt_uint32_t) arg;
uint32_t arb_idx = _inline_get_ArbBaudIndex(argval);
if (arb_idx == (uint32_t) -1) {
return -RT_ERROR;
}
if (argval != pdrv_can->device.config.baud_rate) {
pdrv_can->device.config.baud_rate = argval;
return _inline_can_config(&pdrv_can->device, &pdrv_can->device.config);
}
break;
case RT_CAN_CMD_SET_PRIV:
argval = (rt_uint32_t) arg;
if (argval != RT_CAN_MODE_PRIV &&
argval != RT_CAN_MODE_NOPRIV) {
return -RT_ERROR;
}
if (argval != pdrv_can->device.config.privmode) {
pdrv_can->device.config.privmode = argval;
return RT_EOK;
}
break;
case RT_CAN_CMD_GET_STATUS: {
rt_uint32_t tmp_u32Errcount;
rt_uint32_t tmp_u32status;
tmp_u32Errcount = pdrv_can->fdcanHandle.Instance->ECR;
tmp_u32status = pdrv_can->fdcanHandle.Instance->PSR;
pdrv_can->device.status.rcverrcnt = (tmp_u32Errcount >> 8) & 0x000000ff;
pdrv_can->device.status.snderrcnt = (tmp_u32Errcount) & 0x000000ff;
pdrv_can->device.status.lasterrtype = tmp_u32status & 0x000000007;
rt_memcpy(arg, &pdrv_can->device.status, sizeof(pdrv_can->device.status));
}
break;
case RT_CAN_CMD_SET_BAUD_FD: {
argval = (rt_uint32_t) arg;
uint32_t data_idx = _inline_get_DataBaudIndex(argval);
if (data_idx == (uint32_t) -1) {
return -RT_ERROR;
}
if (argval != pdrv_can->device.config.baud_rate_fd) {
pdrv_can->device.config.baud_rate_fd = argval;
return _inline_can_config(&pdrv_can->device, &pdrv_can->device.config);
}
}
}
return RT_EOK;
}
static int _inline_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
{
stm32_fdcan_t *pdrv_can;
struct rt_can_msg *pmsg;
uint32_t tmp_u32DataLen;
RT_ASSERT(can);
RT_ASSERT(buf);
pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
RT_ASSERT(pdrv_can);
pmsg = (struct rt_can_msg *) buf;
/* Check the parameters */
tmp_u32DataLen = length_to_dlc( pmsg->len);
if(pmsg->ide == RT_CAN_EXTID)
{
pdrv_can->TxHeader.IdType = FDCAN_EXTENDED_ID;
}
else
{
pdrv_can->TxHeader.IdType = FDCAN_STANDARD_ID;
}
if (RT_CAN_DTR == pmsg->rtr)
{
pdrv_can->TxHeader.TxFrameType = FDCAN_DATA_FRAME;
}
else
{
pdrv_can->TxHeader.TxFrameType = FDCAN_REMOTE_FRAME;
}
pdrv_can->TxHeader.Identifier = pmsg->id;
pdrv_can->TxHeader.DataLength = tmp_u32DataLen;
if (pmsg->fd_frame == 1)
{
pdrv_can->TxHeader.FDFormat = FDCAN_FD_CAN;
}
else {
pdrv_can->TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
}
if(HAL_FDCAN_AddMessageToTxBuffer(&pdrv_can->fdcanHandle, &pdrv_can->TxHeader, pmsg->data, FDCAN_TX_BUFFER0 + box_num) != HAL_OK)
{
return -RT_ERROR;
}
else
{
/* Request transmission */
HAL_FDCAN_EnableTxBufferRequest(&pdrv_can->fdcanHandle,FDCAN_TX_BUFFER0+box_num);
return RT_EOK;
}
}
static int _inline_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
{
struct rt_can_msg *pmsg;
stm32_fdcan_t *pdrv_can;
RT_ASSERT(can);
RT_ASSERT(buf);
pdrv_can = (stm32_fdcan_t *)can->parent.user_data;
pmsg = (struct rt_can_msg *) buf;
if(HAL_FDCAN_GetRxMessage(&pdrv_can->fdcanHandle,FDCAN_RX_FIFO0+fifo, &pdrv_can->RxHeader, pmsg->data) != HAL_OK)
{
return 0;
}
else
{
if(pdrv_can->RxHeader.IdType == FDCAN_EXTENDED_ID)
{
pmsg->ide = RT_CAN_EXTID;
}
else
{
pmsg->ide = RT_CAN_STDID;
}
if(pdrv_can->RxHeader.RxFrameType == FDCAN_DATA_FRAME)
{
pmsg->rtr = RT_CAN_DTR;
}
else
{
pmsg->rtr = RT_CAN_RTR;
}
pmsg->id = pdrv_can->RxHeader.Identifier;
pmsg->len = pdrv_can->RxHeader.DataLength;
pmsg->hdr_index = pdrv_can->RxHeader.FilterIndex;
#ifdef RT_CAN_USING_CANFD
pmsg->fd_frame = (pdrv_can->RxHeader.FDFormat >> 16) && 0x20;
pmsg->brs = (pdrv_can->RxHeader.BitRateSwitch >> 16) && 0x10;
#endif
return sizeof(struct rt_can_msg);
}
}
static const struct rt_can_ops _can_ops =
{
_inline_can_config,
_inline_can_control,
_inline_can_sendmsg,
_inline_can_recvmsg,
};
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
{
if(hfdcan->Instance == FDCAN1)
{
#ifdef BSP_USING_FDCAN1
//CAN1
/* Retreive Rx messages from RX FIFO0 */
rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_RX_IND | 0 << 8);
#endif
}
else
{
#ifdef BSP_USING_FDCAN2
//CAN2
/* Retreive Rx messages from RX FIFO0 */
rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_RX_IND | 0 << 8);
#endif
}
}
}
void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
{
if(hfdcan->Instance == FDCAN1)
{
#ifdef BSP_USING_FDCAN1
//can1
rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_DONE | ((BufferIndexes-1) << 8));
#endif
}
else
{
#ifdef BSP_USING_FDCAN2
//can2
rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_DONE | ((BufferIndexes-1) << 8));
#endif
}
}
void HAL_FDCAN_TxFifoEmptyCallback(FDCAN_HandleTypeDef *hfdcan)
{
if(hfdcan->Instance == FDCAN1)
{
#ifdef BSP_USING_FDCAN1
rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_DONE);
#endif
}
else
{
#ifdef BSP_USING_FDCAN2
rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_DONE);
#endif
}
}
void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan)
{
rt_uint32_t tmp_u32Errcount;
rt_uint32_t tmp_u32status;
uint32_t ret = HAL_FDCAN_GetError(hfdcan);
if(hfdcan->Instance == FDCAN1)
{
#ifdef BSP_USING_FDCAN1
if((ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&
(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk))
{
//hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;
hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;
st_DrvCan1.device.status.errcode = 0xff;
}
else
{
tmp_u32Errcount = st_DrvCan1.fdcanHandle.Instance->ECR;
tmp_u32status = st_DrvCan1.fdcanHandle.Instance->PSR;
st_DrvCan1.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;
st_DrvCan1.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;
st_DrvCan1.device.status.lasterrtype = tmp_u32status&0x000000007;
rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_FAIL);
}
#endif /*BSP_USING_FDCAN1*/
}
else
{
#ifdef BSP_USING_FDCAN2
if( (ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&
(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk))
{
//hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;
hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;
st_DrvCan2.device.status.errcode = 0xff;
}
else
{
//can2
tmp_u32Errcount = st_DrvCan2.fdcanHandle.Instance->ECR;
tmp_u32status = st_DrvCan2.fdcanHandle.Instance->PSR;
st_DrvCan2.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;
st_DrvCan2.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;
st_DrvCan2.device.status.lasterrtype = tmp_u32status&0x000000007;
rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_FAIL);
}
#endif /*BSP_USING_FDCAN2*/
}
}
#ifdef BSP_USING_FDCAN1
void FDCAN1_IT0_IRQHandler(void) /* FDCAN1 interrupt line 0 */
{
rt_interrupt_enter();
HAL_FDCAN_IRQHandler(&st_DrvCan1.fdcanHandle);
rt_interrupt_leave();
}
void FDCAN1_IT1_IRQHandler(void) /* FDCAN1 interrupt line 1 */
{
rt_interrupt_enter();
HAL_FDCAN_IRQHandler(&st_DrvCan1.fdcanHandle);
rt_interrupt_leave();
}
#endif /*BSP_USING_FDCAN1*/
#ifdef BSP_USING_FDCAN2
void FDCAN2_IT0_IRQHandler(void) /* FDCAN2 interrupt line 0 */
{
rt_interrupt_enter();
HAL_FDCAN_IRQHandler(&st_DrvCan2.fdcanHandle);
rt_interrupt_leave();
}
void FDCAN2_IT1_IRQHandler(void) /* FDCAN2 interrupt line 1 */
{
rt_interrupt_enter();
HAL_FDCAN_IRQHandler(&st_DrvCan2.fdcanHandle);
rt_interrupt_leave();
}
#endif/*BSP_USING_FDCAN2*/
static int rt_hw_can_init(void)
{
struct can_configure config;
config.baud_rate = CAN1MBaud;
config.msgboxsz = 48;
config.sndboxnumber = 1;
config.mode = RT_CAN_MODE_NORMAL;
config.privmode = RT_CAN_MODE_NOPRIV;
config.ticks = 50;
#ifdef RT_CAN_USING_HDR
config.maxhdr = 14;
#endif
#ifdef RT_CAN_USING_CANFD
config.baud_rate_fd = CAN1MBaud * 8;
config.enable_canfd = 1;
#endif
/* config default filter */
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0;
sFilterConfig.FilterID2 = 0x7FF;
#ifdef BSP_USING_FDCAN1
st_DrvCan1.FilterConfig = sFilterConfig;
st_DrvCan1.device.config = config;
/* register FDCAN1 device */
rt_hw_can_register(&st_DrvCan1.device, st_DrvCan1.name, &_can_ops, &st_DrvCan1);
#endif /* BSP_USING_FDCAN1 */
#ifdef BSP_USING_FDCAN2
st_DrvCan2.FilterConfig = sFilterConfig;
st_DrvCan2.device.config = config;
/* register FDCAN2 device */
rt_hw_can_register(&st_DrvCan2.device, st_DrvCan2.name, &_can_ops, &st_DrvCan2);
#endif /* BSP_USING_FDCAN2 */
return 0;
}
INIT_BOARD_EXPORT(rt_hw_can_init);
#endif /* BSP_USING_FDCAN1 || BSP_USING_FDCAN2 */
#endif /* RT_USING_CAN */

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-02-24 heyuan the first version
* 2020-08-17 malongwei Fix something
*/
#ifndef __DRV_FDCAN_H__
#define __DRV_FDCAN_H__
#include <board.h>
#include <rtdevice.h>
#if defined(RT_USING_CAN) && defined(RT_CAN_USING_CANFD)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
const char *name;
FDCAN_HandleTypeDef fdcanHandle;
FDCAN_RxHeaderTypeDef RxHeader;
FDCAN_TxHeaderTypeDef TxHeader;
uint8_t u8RxDataBuffer[8];
uint8_t u8TxDataBuffer[8];
FDCAN_FilterTypeDef FilterConfig; /*FDCAN filter*/
struct rt_can_device device; /* inherit from can device */
} stm32_fdcan_t;
typedef struct {
uint32_t u32Baudrate;
struct rt_can_bit_timing cam_bit_timing;
}stm32_fdcan_timing_t;
#ifdef __cplusplus
}
#endif
#endif /* RT_USING_CAN */
#endif /* __DRV_FDCAN_H__ */

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

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