Skip to content

Conversation

@Start-xl-wq
Copy link

@Start-xl-wq Start-xl-wq commented Jan 16, 2026

拉取/合并请求描述:(PR description)

Fix the bug where the cmd6 command is sent but the status of the card is not queried, which can cause failure in switching to the high-speed mode in DDR mode.

为什么提交这份PR (why to submit this PR)

Solve the issue of normal code execution in the eMMC DDR mode.

你的解决方案是什么 (what is your solution)

Add command 13 polling in mmc_switch.

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用formatting 等源码格式化工具确保格式符合RT-Thread代码规范 This PR complies with RT-Thread code specification
  • 如果是新增bsp, 已经添加ci检查到.github/ALL_BSP_COMPILE.json 详细请参考链接BSP自查

…the card is not queried, which can cause failure in switching to the high-speed mode in DDR mode.
@github-actions
Copy link

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  • 将目标分支设置为 \ Set the target branch to:fixbuf_emmc_switch_api_bug
  • 设置PR number为 \ Set the PR number to:11139
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将自动推送至你的分支。
    The formatted code will be automatically pushed to your branch.

完成后,提交将自动更新至 fixbuf_emmc_switch_api_bug 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the fixbuf_emmc_switch_api_bug branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


unknown seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions
Copy link

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: @Maihuanyi

Changed Files (Click to expand)
  • components/drivers/sdio/dev_mmc.c

📊 Current Review Status (Last Updated: 2026-01-16 15:35 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@Start-xl-wq
Copy link
Author

For more details, please refer to: https://club.rt-thread.org/ask/question/26ae04a2e1a47f0d.html

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an eMMC bug where CMD6 (SWITCH command) is sent to modify the EXT_CSD register, but the card status is not subsequently polled to verify the operation completed successfully. This can cause failures when switching to high-speed DDR mode. The fix adds two new helper functions (mmc_send_status and mmc_poll_for_busy) that implement CMD13 status polling with timeout handling, and integrates this polling into the mmc_switch function.

Changes:

  • Added mmc_send_status() function to send CMD13 and retrieve card status
  • Added mmc_poll_for_busy() function to poll card status until ready or timeout
  • Modified mmc_switch() to call mmc_poll_for_busy() after sending CMD6

Comment on lines +317 to +321
if (out)
{
LOG_E("wait card busy timeout");
return -RT_ETIMEOUT;
}
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Bug/错误]: Timeout check logic is incorrect / 超时检查逻辑错误

English: The timeout check is performed AFTER sending the status command. This means:

  1. If the card is already ready (status & R1_READY_FOR_DATA is true), the timeout check is skipped entirely due to the while loop condition at line 330
  2. The timeout is only checked after each status query, which means the loop could run one extra iteration beyond the timeout

The timeout check should be done BEFORE checking status or at the beginning of the loop to ensure accurate timeout behavior.

中文:超时检查在发送状态命令之后执行。这意味着:

  1. 如果卡已经就绪(status & R1_READY_FOR_DATA 为真),由于第 330 行的 while 循环条件,超时检查会被完全跳过
  2. 超时仅在每次状态查询后检查,这意味着循环可能会在超时后多运行一次迭代

超时检查应该在检查状态之前或在循环开始时执行,以确保准确的超时行为。

Copilot uses AI. Check for mistakes.
start = rt_tick_get();
do
{
rt_bool_t out = (int)(rt_tick_get() - start) > timeout;
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Naming/命名]: Variable name 'out' is unclear / 变量名 'out' 不清晰

English: The variable name out at line 308 is ambiguous. It's not clear whether it means "output", "timeout occurred", or something else.

A clearer name would be timeout_expired, is_timeout, or timed_out to explicitly indicate that it represents the timeout condition.

中文:第 308 行的变量名 out 含义模糊。不清楚它是表示 "output"、"超时发生" 还是其他含义。

更清晰的名称应该是 timeout_expiredis_timeouttimed_out,以明确表示它代表超时条件。

Copilot uses AI. Check for mistakes.
return err;

/*
* Poll the status of the cmd13 card with a timeout of 500ms and a polling interval of 1ms.
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Spelling/拼写]: Typo in comment / 注释中的拼写错误

English: The comment says "Poll the status of the cmd13 card" but should say "Poll the card status using CMD13" or "Poll the card status with CMD13". The phrase "cmd13 card" is grammatically incorrect - CMD13 is the command, not a type of card.

中文:注释说 "Poll the status of the cmd13 card",但应该是 "Poll the card status using CMD13" 或 "Poll the card status with CMD13"。短语 "cmd13 card" 语法不正确 - CMD13 是命令,不是卡的类型。

Suggested change
* Poll the status of the cmd13 card with a timeout of 500ms and a polling interval of 1ms.
* Poll the card status using CMD13 with a timeout of 500ms and a polling interval of 1ms.

Copilot uses AI. Check for mistakes.
Comment on lines +310 to +330
err = mmc_send_status(card, &status, retries);
if (err)
{
LOG_E("error %d requesting status", err);
return err;
}

if (out)
{
LOG_E("wait card busy timeout");
return -RT_ETIMEOUT;
}

rt_thread_mdelay(1);
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
* indication and the card state.
*/
}
while (!(status & R1_READY_FOR_DATA));
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Bug/错误]: Missing error status check in card status response / 卡状态响应中缺少错误状态检查

English: The function mmc_poll_for_busy() only checks for R1_READY_FOR_DATA bit but doesn't check for error bits in the card status response. According to the MMCSD specification, the R1 response contains various error status bits (defined in dev_mmcsd_core.h, such as R1_ERROR, R1_CC_ERROR, R1_CARD_ECC_FAILED, etc.) that should be checked.

If the card reports an error status, the function should detect and return an error instead of continuing to poll. Consider adding a check like:

  • Check R1_STATUS(status) macro to detect error conditions
  • Return appropriate error if card reports an error state

中文:函数 mmc_poll_for_busy() 只检查 R1_READY_FOR_DATA 位,但不检查卡状态响应中的错误位。根据 MMCSD 规范,R1 响应包含各种错误状态位(在 dev_mmcsd_core.h 中定义,如 R1_ERROR、R1_CC_ERROR、R1_CARD_ECC_FAILED 等)应该被检查。

如果卡报告错误状态,函数应该检测并返回错误,而不是继续轮询。考虑添加检查,例如:

  • 检查 R1_STATUS(status) 宏以检测错误条件
  • 如果卡报告错误状态则返回相应的错误

Copilot uses AI. Check for mistakes.
/*
* Poll Busy.
*/
static int mmc_poll_for_busy(struct rt_mmcsd_card *card, unsigned int timeout_ms, int retries)
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Best Practices/最佳实践]: Inconsistent parameter type usage / 参数类型使用不一致

English: The function mmc_poll_for_busy() uses unsigned int timeout_ms for the timeout parameter, while mmc_send_status() uses unsigned retries. This inconsistency in using unsigned int vs unsigned reduces code readability.

For consistency with RT-Thread coding style, consider using explicit types like rt_uint32_t for timeout_ms, or use unsigned int consistently throughout the function parameters.

中文:函数 mmc_poll_for_busy() 对超时参数使用 unsigned int timeout_ms,而 mmc_send_status() 使用 unsigned retries。这种在 unsigned intunsigned 之间的不一致降低了代码可读性。

为了与 RT-Thread 编码风格保持一致,考虑对 timeout_ms 使用显式类型如 rt_uint32_t,或在整个函数参数中一致使用 unsigned int

Suggested change
static int mmc_poll_for_busy(struct rt_mmcsd_card *card, unsigned int timeout_ms, int retries)
static int mmc_poll_for_busy(struct rt_mmcsd_card *card, unsigned timeout_ms, int retries)

Copilot uses AI. Check for mistakes.
static int mmc_send_status(struct rt_mmcsd_card *card, rt_uint32_t *status, unsigned retries)
{
int err;
struct rt_mmcsd_cmd cmd;
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Best Practices/最佳实践]: Inconsistent structure initialization pattern / 结构体初始化模式不一致

English: In mmc_send_status(), the rt_mmcsd_cmd cmd structure is declared without initialization, and then individual fields are set. However, in mmc_switch() at line 349, the structure is initialized with { 0 }.

For consistency and to avoid potential uninitialized field issues, consider using the same initialization pattern. The safer approach is to initialize with { 0 } as done in mmc_switch().

中文:在 mmc_send_status() 中,rt_mmcsd_cmd cmd 结构体声明时没有初始化,然后设置各个字段。然而,在第 349 行的 mmc_switch() 中,结构体用 { 0 } 初始化。

为了保持一致性并避免潜在的未初始化字段问题,考虑使用相同的初始化模式。更安全的方法是像 mmc_switch() 中那样使用 { 0 } 初始化。

Suggested change
struct rt_mmcsd_cmd cmd;
struct rt_mmcsd_cmd cmd = (struct rt_mmcsd_cmd){ 0 };

Copilot uses AI. Check for mistakes.
Comment on lines +323 to +330
rt_thread_mdelay(1);
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
* indication and the card state.
*/
}
while (!(status & R1_READY_FOR_DATA));
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Performance/性能]: Potential unnecessary delay after card is ready / 卡已就绪后可能有不必要的延迟

English: The code calls rt_thread_mdelay(1) at line 323 before checking if the card is ready at line 330. This means even when the card is already ready (status indicates R1_READY_FOR_DATA), the function will still delay for 1ms unnecessarily before exiting the loop.

Consider checking the status condition before the delay to avoid the unnecessary wait when the card is already ready.

中文:代码在第 323 行调用 rt_thread_mdelay(1),然后在第 330 行检查卡是否就绪。这意味着即使卡已经就绪(状态指示 R1_READY_FOR_DATA),函数在退出循环之前仍然会不必要地延迟 1ms。

考虑在延迟之前检查状态条件,以避免在卡已经就绪时不必要的等待。

Copilot uses AI. Check for mistakes.
Comment on lines +300 to +308
int timeout = rt_tick_from_millisecond(timeout_ms);
int err = 0;
rt_uint32_t status;
rt_tick_t start;

start = rt_tick_get();
do
{
rt_bool_t out = (int)(rt_tick_get() - start) > timeout;
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Bug/错误]: Type mismatch and incorrect timeout calculation / 类型不匹配和错误的超时计算

English: There are two issues with the timeout calculation:

  1. rt_tick_from_millisecond() returns rt_tick_t (typically unsigned), but it's assigned to int timeout, which could cause issues if the value exceeds INT_MAX
  2. The comparison (int)(rt_tick_get() - start) > timeout uses signed integer comparison for tick differences, which could produce incorrect results due to potential overflow in the subtraction or type conversion

For proper tick-based timeout checking in RT-Thread, consider using the pattern: (rt_tick_get() - start) >= timeout with consistent unsigned types, or check if rt_tick_get() >= (start + timeout) to avoid overflow issues.

中文:超时计算存在两个问题:

  1. rt_tick_from_millisecond() 返回 rt_tick_t(通常是无符号类型),但它被赋值给 int timeout,如果值超过 INT_MAX 可能会导致问题
  2. 比较 (int)(rt_tick_get() - start) > timeout 使用有符号整数比较来处理 tick 差值,由于减法或类型转换中的潜在溢出,可能会产生不正确的结果

为了在 RT-Thread 中进行正确的基于 tick 的超时检查,考虑使用模式:(rt_tick_get() - start) >= timeout 并使用一致的无符号类型,或检查 rt_tick_get() >= (start + timeout) 以避免溢出问题。

Copilot uses AI. Check for mistakes.
* indication and the card state.
*/
}
while (!(status & R1_READY_FOR_DATA));
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Documentation/文档]: Comment mentions checking card state but implementation doesn't / 注释提到检查卡状态但实现未检查

English: The comment at lines 324-328 states "Some cards mishandle the status bits, so make sure to check both the busy indication and the card state." However, the implementation at line 330 only checks R1_READY_FOR_DATA (the busy indication) but does not check the card state using R1_CURRENT_STATE(status).

According to the comment's intent, the code should also verify that the card is in the correct state (e.g., transfer state). Consider adding a check for the card state if this is indeed necessary for proper operation, or update the comment to accurately reflect what the code does.

中文:第 324-328 行的注释说明 "Some cards mishandle the status bits, so make sure to check both the busy indication and the card state."(某些卡会错误处理状态位,因此要确保同时检查忙指示和卡状态)。然而,第 330 行的实现只检查了 R1_READY_FOR_DATA(忙指示),但没有使用 R1_CURRENT_STATE(status) 检查卡状态。

根据注释的意图,代码还应该验证卡处于正确的状态(例如传输状态)。如果这对于正确操作确实是必要的,请考虑添加卡状态检查,或者更新注释以准确反映代码的实际行为。

Suggested change
while (!(status & R1_READY_FOR_DATA));
while (!(status & R1_READY_FOR_DATA) ||
(R1_CURRENT_STATE(status) == R1_STATE_PRG));

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants