* @internal * @brief Handles blocking transmission in "private mode". * * This is a specialized version of `_can_int_tx` where the target hardware mailbox * for each message is specified by the user in the `priv` field of the `rt_can_msg` * structure, rather than being acquired dynamically from a pool. * * @param[in] can A pointer to the CAN device. * @param[in] data A pointer to the so
| 255 | * @return The number of bytes successfully sent. |
| 256 | */ |
| 257 | rt_inline int _can_int_tx_priv(struct rt_can_device *can, const struct rt_can_msg *data, int msgs) |
| 258 | { |
| 259 | int size; |
| 260 | rt_base_t level; |
| 261 | rt_uint32_t no, result; |
| 262 | struct rt_can_tx_fifo *tx_fifo; |
| 263 | |
| 264 | RT_ASSERT(can != RT_NULL); |
| 265 | |
| 266 | size = msgs; |
| 267 | tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; |
| 268 | RT_ASSERT(tx_fifo != RT_NULL); |
| 269 | |
| 270 | while (msgs) |
| 271 | { |
| 272 | no = data->priv; |
| 273 | if (no >= can->config.sndboxnumber) |
| 274 | { |
| 275 | break; |
| 276 | } |
| 277 | |
| 278 | level = rt_hw_local_irq_disable(); |
| 279 | if ((tx_fifo->buffer[no].result != RT_CAN_SND_RESULT_OK)) |
| 280 | { |
| 281 | rt_hw_local_irq_enable(level); |
| 282 | |
| 283 | rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_WAITING_FOREVER); |
| 284 | continue; |
| 285 | } |
| 286 | tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_WAIT; |
| 287 | rt_hw_local_irq_enable(level); |
| 288 | |
| 289 | if (can->ops->sendmsg(can, data, no) != RT_EOK) |
| 290 | { |
| 291 | continue; |
| 292 | } |
| 293 | can->status.sndchange |= 1<<no; |
| 294 | if (rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_CANSND_MSG_TIMEOUT) != RT_EOK) |
| 295 | { |
| 296 | can->status.sndchange &= ~ (1<<no); |
| 297 | continue; |
| 298 | } |
| 299 | |
| 300 | result = tx_fifo->buffer[no].result; |
| 301 | if (result == RT_CAN_SND_RESULT_OK) |
| 302 | { |
| 303 | level = rt_hw_local_irq_disable(); |
| 304 | can->status.sndpkg++; |
| 305 | rt_hw_local_irq_enable(level); |
| 306 | data ++; |
| 307 | msgs -= sizeof(struct rt_can_msg); |
| 308 | if (!msgs) break; |
| 309 | } |
| 310 | else |
| 311 | { |
| 312 | level = rt_hw_local_irq_disable(); |
| 313 | can->status.dropedsndpkg++; |
| 314 | rt_hw_local_irq_enable(level); |
no test coverage detected