CAN驱动
CAN驱动框架
CAN初始化
-rt_hw_can_register
注册CAN设备,并初始化互斥量
-rt_timer_init
初始化CAN定时器,注册定时器回调函数 cantimeout
初始化&&配置
- RT_CAN_CMD_SET_PRIV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| if (can->config.privmode)
{
for (i = 0; i < can->config.sndboxnumber; i++)
{
level = rt_hw_interrupt_disable();
if(rt_list_isempty(&tx_fifo->buffer[i].list))
{
rt_sem_release(&(tx_fifo->sem));
}
else
{
rt_list_remove(&tx_fifo->buffer[i].list);
}
rt_hw_interrupt_enable(level);
}
}
else
{
for (i = 0; i < can->config.sndboxnumber; i++)
{
level = rt_hw_interrupt_disable();
if (tx_fifo->buffer[i].result == RT_CAN_SND_RESULT_OK)
{
rt_list_insert_before(&tx_fifo->freelist, &tx_fifo->buffer[i].list);
}
rt_hw_interrupt_enable(level);
}
}
}
|
- RT_CAN_CMD_SET_FILTER
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
if (pfilter->actived)
{
while (count)
{
if (pitem->hdr_bank >= can->config.maxhdr || pitem->hdr_bank < 0)
{
count--;
pitem++;
continue;
}
level = rt_hw_interrupt_disable();
if (!can->hdr[pitem->hdr_bank].connected)
{
rt_hw_interrupt_enable(level);
rt_memcpy(&can->hdr[pitem->hdr_bank].filter, pitem,
sizeof(struct rt_can_filter_item));
level = rt_hw_interrupt_disable();
can->hdr[pitem->hdr_bank].connected = 1;
can->hdr[pitem->hdr_bank].msgs = 0;
rt_list_init(&can->hdr[pitem->hdr_bank].list);
}
rt_hw_interrupt_enable(level);
count--;
pitem++;
}
}
else
{
while (count)
{
if (pitem->hdr_bank >= can->config.maxhdr || pitem->hdr_bank < 0)
{
count--;
pitem++;
continue;
}
level = rt_hw_interrupt_disable();
if (can->hdr[pitem->hdr_bank].connected)
{
can->hdr[pitem->hdr_bank].connected = 0;
can->hdr[pitem->hdr_bank].msgs = 0;
if (!rt_list_isempty(&can->hdr[pitem->hdr_bank].list))
{
rt_list_remove(can->hdr[pitem->hdr_bank].list.next);
}
rt_hw_interrupt_enable(level);
rt_memset(&can->hdr[pitem->hdr_bank].filter, 0,
sizeof(struct rt_can_filter_item));
}
else
{
rt_hw_interrupt_enable(level);
}
count--;
pitem++;
}
}
|
open
- RX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| struct rt_can_rx_fifo
{
struct rt_can_msg_list *buffer;
rt_uint32_t freenumbers;
struct rt_list_node freelist;
struct rt_list_node uselist;
};
|
- 将每个rt_fifo消息插入free链表中;
- 初始化每个rt_fifo消息的硬件过滤链表
- 配置RX中断
- TX
1 2 3 4 5 6 7 8 9 10 11 12 13
| struct rt_can_tx_fifo
{
struct rt_can_sndbxinx_list *buffer;
struct rt_semaphore sem;
struct rt_list_node freelist;
};
|
- 将每个rt_fifo消息插入free链表中;并初始化完成量
- 初始化信号量
- 硬件过滤表初始化
- 开启can定时器
close
- 关闭CAN定时器
- free hdr分配
write
- _can_int_tx
- 互斥量加锁
- 从free链表中取出一个rt_fifo消息并从链表中移除;确保这个消息是安全的发送
- 执行发送操作
- 发送失败,则重新插入free链表
- 发送成功,再次检测是否被插入发送链表,如果是则移除;然后重新插入free链表
- 互斥量解锁
- 计算发送包数和失败包数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| while (msgs)
{
rt_base_t level;
rt_uint32_t no;
rt_uint32_t result;
struct rt_can_sndbxinx_list *tx_tosnd = RT_NULL;
rt_mutex_take(&(tx_fifo->mutex), 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_ubase_t)tx_tosnd - (rt_ubase_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list);
tx_tosnd->result = RT_CAN_SND_RESULT_WAIT;
rt_completion_init(&tx_tosnd->completion);
if (can->ops->sendmsg(can, data, no) != RT_EOK)
{
level = rt_hw_interrupt_disable();
rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list);
rt_hw_interrupt_enable(level);
rt_mutex_release(&(tx_fifo->mutex));
goto err_ret;
}
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_mutex_release(&(tx_fifo->mutex));
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
{
err_ret:
level = rt_hw_interrupt_disable();
can->status.dropedsndpkg++;
rt_hw_interrupt_enable(level);
break;
}
}
|
- _can_int_tx_priv
read
- 判断硬件过滤表不为空
- 判断硬件过滤表为空
- userlist链表不为空,则取出消息,移除消息出消息链表
- 没数据则退出
- 判断listmsg有取到消息,拷贝消息到用户空间
4.msgs–;msgs为0,则退出
- 接收中断
-RT_CAN_EVENT_RXOF_IND
- 错误接收数据++
-RT_CAN_EVENT_RX_IND
- 接收数据++
- 从freelist链表中取出一个消息放入,并移除链表,移除hdr链表
- 否则从uselist链表中取出一个消息放入,并移除链表,移除hdr链表
- 拷贝消息到用户空间,插入到uselist链表
- hdr 有对应的index,这插入hdr链表
- 执行对应的hdr回调或者用户回调
STM32 CAN 硬件