RT-Thread / RT-Thread/rt-thread

can组件驱动中_can_int_tx 调用底层发送msg时 如果有暂时无法恢复的总线错误会卡死

Open
#4,848 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
12.2k
Forks
5.4k
Avg merge
4d 12h
Merged PRs (30d)
40

Description

can组件驱动中_can_int_tx 调用底层发送msg时 如果有暂时无法恢复的总线错误会卡死

rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *data, int msgs)
{
int size;
struct rt_can_tx_fifo *tx_fifo;

RT_ASSERT(can != RT_NULL);

size = msgs;
tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;
RT_ASSERT(tx_fifo != RT_NULL);

while (msgs)
{
    rt_base_t level;
    rt_uint32_t no;
    rt_uint32_t result;
    struct rt_can_sndbxinx_list *tx_tosnd = RT_NULL;

    rt_sem_take(&(tx_fifo->sem), RT_WAITING_FOREVER);
    level = rt_hw_interrupt_disable();
    tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list);
    RT_ASSERT(tx_tosnd != RT_NULL);
    rt_list_remove(&tx_tosnd->list);
    rt_hw_interrupt_enable(level);

    no = ((rt_uint32_t)tx_tosnd - (rt_uint32_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list);
    tx_tosnd->result = RT_CAN_SND_RESULT_WAIT;
    **if (can->ops->sendmsg(can, data, no) != RT_EOK)**
    {
        /* send failed. */
        level = rt_hw_interrupt_disable();
        rt_list_insert_after(&tx_fifo->freelist, &tx_tosnd->list);
        rt_hw_interrupt_enable(level);
        rt_sem_release(&(tx_fifo->sem));
        **continue;**
    }

    can->status.sndchange = 1;
    rt_completion_wait(&(tx_tosnd->completion), RT_WAITING_FOREVER);

    level = rt_hw_interrupt_disable();
    result = tx_tosnd->result;
    if (!rt_list_isempty(&tx_tosnd->list))
    {
        rt_list_remove(&tx_tosnd->list);
    }
    rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list);
    rt_hw_interrupt_enable(level);
    rt_sem_release(&(tx_fifo->sem));

    if (result == RT_CAN_SND_RESULT_OK)
    {
        level = rt_hw_interrupt_disable();
        can->status.sndpkg++;
        rt_hw_interrupt_enable(level);

        data ++;
        msgs -= sizeof(struct rt_can_msg);
        if (!msgs) break;
    }
    else
    {
        level = rt_hw_interrupt_disable();
        can->status.dropedsndpkg++;
        rt_hw_interrupt_enable(level);
        break;
    }
}

return (size - msgs);

}

当总线存在临时物理断开时 调用底层can->ops->sendmsg(can, data, no) 会一直失败 然后再下面分支的continue一直循环

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the _can_int_tx function and inspect the can->ops->sendmsg failure branch shown in the issue, along with the CAN driver implementations that return its result. Reproduce the case with a temporarily disconnected CAN bus and trace the retry path; done should mean a persistent send failure no longer leaves transmission stuck in an endless loop.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
embedded-iot, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.