1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2015-05-14 [email protected] first version 9 * 2015-07-06 Bernard code cleanup and remove RT_CAN_USING_LED; 10 */ 11 12 #include <rthw.h> 13 #include <rtthread.h> 14 #include <rtdevice.h> 15 16 #define CAN_LOCK(can) rt_mutex_take(&(can->lock), RT_WAITING_FOREVER) 17 #define CAN_UNLOCK(can) rt_mutex_release(&(can->lock)) 18 19 static rt_err_t rt_can_init(struct rt_device *dev) 20 { 21 rt_err_t result = RT_EOK; 22 struct rt_can_device *can; 23 24 RT_ASSERT(dev != RT_NULL); 25 can = (struct rt_can_device *)dev; 26 27 /* initialize rx/tx */ 28 can->can_rx = RT_NULL; 29 can->can_tx = RT_NULL; 30 31 /* apply configuration */ 32 if (can->ops->configure) 33 result = can->ops->configure(can, &can->config); 34 35 return result; 36 } 37 38 /* 39 * can interrupt routines 40 */ 41 rt_inline int _can_int_rx(struct rt_can_device *can, struct rt_can_msg *data, int msgs) 42 { 43 int size; 44 struct rt_can_rx_fifo *rx_fifo; 45 RT_ASSERT(can != RT_NULL); 46 size = msgs; 47 48 rx_fifo = (struct rt_can_rx_fifo *) can->can_rx; 49 RT_ASSERT(rx_fifo != RT_NULL); 50 51 /* read from software FIFO */ 52 while (msgs) 53 { 54 rt_base_t level; 55 #ifdef RT_CAN_USING_HDR 56 rt_int32_t hdr; 57 #endif /*RT_CAN_USING_HDR*/ 58 struct rt_can_msg_list *listmsg = RT_NULL; 59 60 /* disable interrupt */ 61 level = rt_hw_interrupt_disable(); 62 #ifdef RT_CAN_USING_HDR 63 hdr = data->hdr; 64 65 if (hdr >= 0 && can->hdr && hdr < can->config.maxhdr && !rt_list_isempty(&can->hdr[hdr].list)) 66 { 67 listmsg = rt_list_entry(can->hdr[hdr].list.next, struct rt_can_msg_list, hdrlist); 68 rt_list_remove(&listmsg->list); 69 rt_list_remove(&listmsg->hdrlist); 70 if (can->hdr[hdr].msgs) 71 { 72 can->hdr[hdr].msgs--; 73 } 74 listmsg->owner = RT_NULL; 75 } 76 else if (hdr == -1) 77 #endif /*RT_CAN_USING_HDR*/ 78 { 79 if (!rt_list_isempty(&rx_fifo->uselist)) 80 { 81 listmsg = rt_list_entry(rx_fifo->uselist.next, struct rt_can_msg_list, list); 82 rt_list_remove(&listmsg->list); 83 #ifdef RT_CAN_USING_HDR 84 rt_list_remove(&listmsg->hdrlist); 85 if (listmsg->owner != RT_NULL && listmsg->owner->msgs) 86 { 87 listmsg->owner->msgs--; 88 } 89 listmsg->owner = RT_NULL; 90 #endif /*RT_CAN_USING_HDR*/ 91 } 92 else 93 { 94 /* no data, enable interrupt and break out */ 95 rt_hw_interrupt_enable(level); 96 break; 97 } 98 } 99 100 /* enable interrupt */ 101 rt_hw_interrupt_enable(level); 102 if (listmsg != RT_NULL) 103 { 104 rt_memcpy(data, &listmsg->data, sizeof(struct rt_can_msg)); 105 106 level = rt_hw_interrupt_disable(); 107 rt_list_insert_before(&rx_fifo->freelist, &listmsg->list); 108 rx_fifo->freenumbers++; 109 RT_ASSERT(rx_fifo->freenumbers <= can->config.msgboxsz); 110 rt_hw_interrupt_enable(level); 111 112 listmsg = RT_NULL; 113 } 114 else 115 { 116 break; 117 } 118 data ++; 119 msgs -= sizeof(struct rt_can_msg); 120 } 121 122 return (size - msgs); 123 } 124 125 rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *data, int msgs) 126 { 127 int size; 128 struct rt_can_tx_fifo *tx_fifo; 129 130 RT_ASSERT(can != RT_NULL); 131 132 size = msgs; 133 tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; 134 RT_ASSERT(tx_fifo != RT_NULL); 135 136 while (msgs) 137 { 138 rt_base_t level; 139 rt_uint32_t no; 140 rt_uint32_t result; 141 struct rt_can_sndbxinx_list *tx_tosnd = RT_NULL; 142 143 rt_sem_take(&(tx_fifo->sem), RT_WAITING_FOREVER); 144 level = rt_hw_interrupt_disable(); 145 tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list); 146 RT_ASSERT(tx_tosnd != RT_NULL); 147 rt_list_remove(&tx_tosnd->list); 148 rt_hw_interrupt_enable(level); 149 150 no = ((rt_uint32_t)tx_tosnd - (rt_uint32_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list); 151 tx_tosnd->result = RT_CAN_SND_RESULT_WAIT; 152 if (can->ops->sendmsg(can, data, no) != RT_EOK) 153 { 154 /* send failed. */ 155 level = rt_hw_interrupt_disable(); 156 rt_list_insert_after(&tx_fifo->freelist, &tx_tosnd->list); 157 rt_hw_interrupt_enable(level); 158 rt_sem_release(&(tx_fifo->sem)); 159 continue; 160 } 161 162 can->status.sndchange = 1; 163 rt_completion_wait(&(tx_tosnd->completion), RT_WAITING_FOREVER); 164 165 level = rt_hw_interrupt_disable(); 166 result = tx_tosnd->result; 167 if (!rt_list_isempty(&tx_tosnd->list)) 168 { 169 rt_list_remove(&tx_tosnd->list); 170 } 171 rt_list_insert_before(&tx_fifo->freelist, &tx_tosnd->list); 172 rt_hw_interrupt_enable(level); 173 rt_sem_release(&(tx_fifo->sem)); 174 175 if (result == RT_CAN_SND_RESULT_OK) 176 { 177 level = rt_hw_interrupt_disable(); 178 can->status.sndpkg++; 179 rt_hw_interrupt_enable(level); 180 181 data ++; 182 msgs -= sizeof(struct rt_can_msg); 183 if (!msgs) break; 184 } 185 else 186 { 187 level = rt_hw_interrupt_disable(); 188 can->status.dropedsndpkg++; 189 rt_hw_interrupt_enable(level); 190 break; 191 } 192 } 193 194 return (size - msgs); 195 } 196 197 rt_inline int _can_int_tx_priv(struct rt_can_device *can, const struct rt_can_msg *data, int msgs) 198 { 199 int size; 200 rt_base_t level; 201 rt_uint32_t no, result; 202 struct rt_can_tx_fifo *tx_fifo; 203 204 RT_ASSERT(can != RT_NULL); 205 206 size = msgs; 207 tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; 208 RT_ASSERT(tx_fifo != RT_NULL); 209 210 while (msgs) 211 { 212 no = data->priv; 213 if (no >= can->config.sndboxnumber) 214 { 215 break; 216 } 217 218 level = rt_hw_interrupt_disable(); 219 if ((tx_fifo->buffer[no].result != RT_CAN_SND_RESULT_OK)) 220 { 221 rt_hw_interrupt_enable(level); 222 223 rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_WAITING_FOREVER); 224 continue; 225 } 226 tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_WAIT; 227 rt_hw_interrupt_enable(level); 228 229 if (can->ops->sendmsg(can, data, no) != RT_EOK) 230 { 231 continue; 232 } 233 can->status.sndchange = 1; 234 rt_completion_wait(&(tx_fifo->buffer[no].completion), RT_WAITING_FOREVER); 235 236 result = tx_fifo->buffer[no].result; 237 if (result == RT_CAN_SND_RESULT_OK) 238 { 239 level = rt_hw_interrupt_disable(); 240 can->status.sndpkg++; 241 rt_hw_interrupt_enable(level); 242 data ++; 243 msgs -= sizeof(struct rt_can_msg); 244 if (!msgs) break; 245 } 246 else 247 { 248 level = rt_hw_interrupt_disable(); 249 can->status.dropedsndpkg++; 250 rt_hw_interrupt_enable(level); 251 break; 252 } 253 } 254 255 return (size - msgs); 256 } 257 258 static rt_err_t rt_can_open(struct rt_device *dev, rt_uint16_t oflag) 259 { 260 struct rt_can_device *can; 261 char tmpname[16]; 262 RT_ASSERT(dev != RT_NULL); 263 can = (struct rt_can_device *)dev; 264 265 CAN_LOCK(can); 266 267 /* get open flags */ 268 dev->open_flag = oflag & 0xff; 269 if (can->can_rx == RT_NULL) 270 { 271 if (oflag & RT_DEVICE_FLAG_INT_RX) 272 { 273 int i = 0; 274 struct rt_can_rx_fifo *rx_fifo; 275 276 rx_fifo = (struct rt_can_rx_fifo *) rt_malloc(sizeof(struct rt_can_rx_fifo) + 277 can->config.msgboxsz * sizeof(struct rt_can_msg_list)); 278 RT_ASSERT(rx_fifo != RT_NULL); 279 280 rx_fifo->buffer = (struct rt_can_msg_list *)(rx_fifo + 1); 281 rt_memset(rx_fifo->buffer, 0, can->config.msgboxsz * sizeof(struct rt_can_msg_list)); 282 rt_list_init(&rx_fifo->freelist); 283 rt_list_init(&rx_fifo->uselist); 284 rx_fifo->freenumbers = can->config.msgboxsz; 285 for (i = 0; i < can->config.msgboxsz; i++) 286 { 287 rt_list_insert_before(&rx_fifo->freelist, &rx_fifo->buffer[i].list); 288 #ifdef RT_CAN_USING_HDR 289 rt_list_init(&rx_fifo->buffer[i].hdrlist); 290 rx_fifo->buffer[i].owner = RT_NULL; 291 #endif 292 } 293 can->can_rx = rx_fifo; 294 295 dev->open_flag |= RT_DEVICE_FLAG_INT_RX; 296 /* configure low level device */ 297 can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); 298 } 299 } 300 301 if (can->can_tx == RT_NULL) 302 { 303 if (oflag & RT_DEVICE_FLAG_INT_TX) 304 { 305 int i = 0; 306 struct rt_can_tx_fifo *tx_fifo; 307 308 tx_fifo = (struct rt_can_tx_fifo *) rt_malloc(sizeof(struct rt_can_tx_fifo) + 309 can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); 310 RT_ASSERT(tx_fifo != RT_NULL); 311 312 tx_fifo->buffer = (struct rt_can_sndbxinx_list *)(tx_fifo + 1); 313 rt_memset(tx_fifo->buffer, 0, 314 can->config.sndboxnumber * sizeof(struct rt_can_sndbxinx_list)); 315 rt_list_init(&tx_fifo->freelist); 316 for (i = 0; i < can->config.sndboxnumber; i++) 317 { 318 rt_list_insert_before(&tx_fifo->freelist, &tx_fifo->buffer[i].list); 319 rt_completion_init(&(tx_fifo->buffer[i].completion)); 320 tx_fifo->buffer[i].result = RT_CAN_SND_RESULT_OK; 321 } 322 323 rt_sprintf(tmpname, "%stl", dev->parent.name); 324 rt_sem_init(&(tx_fifo->sem), tmpname, can->config.sndboxnumber, RT_IPC_FLAG_FIFO); 325 can->can_tx = tx_fifo; 326 327 dev->open_flag |= RT_DEVICE_FLAG_INT_TX; 328 /* configure low level device */ 329 can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX); 330 } 331 } 332 333 can->ops->control(can, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_CAN_INT_ERR); 334 335 #ifdef RT_CAN_USING_HDR 336 if (can->hdr == RT_NULL) 337 { 338 int i = 0; 339 struct rt_can_hdr *phdr; 340 341 phdr = (struct rt_can_hdr *) rt_malloc(can->config.maxhdr * sizeof(struct rt_can_hdr)); 342 RT_ASSERT(phdr != RT_NULL); 343 rt_memset(phdr, 0, can->config.maxhdr * sizeof(struct rt_can_hdr)); 344 for (i = 0; i < can->config.maxhdr; i++) 345 { 346 rt_list_init(&phdr[i].list); 347 } 348 349 can->hdr = phdr; 350 } 351 #endif 352 353 if (!can->timerinitflag) 354 { 355 can->timerinitflag = 1; 356 357 rt_timer_start(&can->timer); 358 } 359 360 CAN_UNLOCK(can); 361 362 return RT_EOK; 363 } 364 365 static rt_err_t rt_can_close(struct rt_device *dev) 366 { 367 struct rt_can_device *can; 368 369 RT_ASSERT(dev != RT_NULL); 370 can = (struct rt_can_device *)dev; 371 372 CAN_LOCK(can); 373 374 /* this device has more reference count */ 375 if (dev->ref_count > 1) 376 { 377 CAN_UNLOCK(can); 378 return RT_EOK; 379 } 380 381 if (can->timerinitflag) 382 { 383 can->timerinitflag = 0; 384 385 rt_timer_stop(&can->timer); 386 } 387 388 can->status_indicate.ind = RT_NULL; 389 can->status_indicate.args = RT_NULL; 390 391 #ifdef RT_CAN_USING_HDR 392 if (can->hdr != RT_NULL) 393 { 394 rt_free(can->hdr); 395 can->hdr = RT_NULL; 396 } 397 #endif 398 399 if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) 400 { 401 struct rt_can_rx_fifo *rx_fifo; 402 403 rx_fifo = (struct rt_can_rx_fifo *)can->can_rx; 404 RT_ASSERT(rx_fifo != RT_NULL); 405 406 rt_free(rx_fifo); 407 dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; 408 can->can_rx = RT_NULL; 409 /* configure low level device */ 410 can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); 411 } 412 413 if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) 414 { 415 struct rt_can_tx_fifo *tx_fifo; 416 417 tx_fifo = (struct rt_can_tx_fifo *)can->can_tx; 418 RT_ASSERT(tx_fifo != RT_NULL); 419 420 rt_free(tx_fifo); 421 dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; 422 can->can_tx = RT_NULL; 423 /* configure low level device */ 424 can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_TX); 425 } 426 427 can->ops->control(can, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_CAN_INT_ERR); 428 429 CAN_UNLOCK(can); 430 431 return RT_EOK; 432 } 433 434 static rt_size_t rt_can_read(struct rt_device *dev, 435 rt_off_t pos, 436 void *buffer, 437 rt_size_t size) 438 { 439 struct rt_can_device *can; 440 441 RT_ASSERT(dev != RT_NULL); 442 if (size == 0) return 0; 443 444 can = (struct rt_can_device *)dev; 445 446 if ((dev->open_flag & RT_DEVICE_FLAG_INT_RX) && (dev->ref_count > 0)) 447 { 448 return _can_int_rx(can, buffer, size); 449 } 450 451 return 0; 452 } 453 454 static rt_size_t rt_can_write(struct rt_device *dev, 455 rt_off_t pos, 456 const void *buffer, 457 rt_size_t size) 458 { 459 struct rt_can_device *can; 460 461 RT_ASSERT(dev != RT_NULL); 462 if (size == 0) return 0; 463 464 can = (struct rt_can_device *)dev; 465 466 if ((dev->open_flag & RT_DEVICE_FLAG_INT_TX) && (dev->ref_count > 0)) 467 { 468 if (can->config.privmode) 469 { 470 return _can_int_tx_priv(can, buffer, size); 471 } 472 else 473 { 474 return _can_int_tx(can, buffer, size); 475 } 476 } 477 return 0; 478 } 479 480 static rt_err_t rt_can_control(struct rt_device *dev, 481 int cmd, 482 void *args) 483 { 484 struct rt_can_device *can; 485 rt_err_t res; 486 487 RT_ASSERT(dev != RT_NULL); 488 can = (struct rt_can_device *)dev; 489 490 switch (cmd) 491 { 492 case RT_DEVICE_CTRL_SUSPEND: 493 /* suspend device */ 494 dev->flag |= RT_DEVICE_FLAG_SUSPENDED; 495 break; 496 497 case RT_DEVICE_CTRL_RESUME: 498 /* resume device */ 499 dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; 500 break; 501 502 case RT_DEVICE_CTRL_CONFIG: 503 /* configure device */ 504 can->ops->configure(can, (struct can_configure *)args); 505 break; 506 case RT_CAN_CMD_SET_PRIV: 507 /* configure device */ 508 if ((rt_uint32_t)args != can->config.privmode) 509 { 510 int i; 511 rt_base_t level; 512 struct rt_can_tx_fifo *tx_fifo; 513 514 res = can->ops->control(can, cmd, args); 515 if (res != RT_EOK) return res; 516 517 tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; 518 if (can->config.privmode) 519 { 520 for (i = 0; i < can->config.sndboxnumber; i++) 521 { 522 level = rt_hw_interrupt_disable(); 523 if(rt_list_isempty(&tx_fifo->buffer[i].list)) 524 { 525 rt_sem_release(&(tx_fifo->sem)); 526 } 527 else 528 { 529 rt_list_remove(&tx_fifo->buffer[i].list); 530 } 531 rt_hw_interrupt_enable(level); 532 } 533 534 } 535 else 536 { 537 for (i = 0; i < can->config.sndboxnumber; i++) 538 { 539 level = rt_hw_interrupt_disable(); 540 if (tx_fifo->buffer[i].result == RT_CAN_SND_RESULT_OK) 541 { 542 rt_list_insert_before(&tx_fifo->freelist, &tx_fifo->buffer[i].list); 543 } 544 rt_hw_interrupt_enable(level); 545 } 546 } 547 return RT_EOK; 548 } 549 break; 550 551 case RT_CAN_CMD_SET_STATUS_IND: 552 can->status_indicate.ind = ((rt_can_status_ind_type_t)args)->ind; 553 can->status_indicate.args = ((rt_can_status_ind_type_t)args)->args; 554 break; 555 556 #ifdef RT_CAN_USING_HDR 557 case RT_CAN_CMD_SET_FILTER: 558 res = can->ops->control(can, cmd, args); 559 if (res != RT_EOK || can->hdr == RT_NULL) 560 { 561 return res; 562 } 563 564 { 565 struct rt_can_filter_config *pfilter; 566 struct rt_can_filter_item *pitem; 567 rt_uint32_t count; 568 rt_base_t level; 569 570 pfilter = (struct rt_can_filter_config *)args; 571 count = pfilter->count; 572 pitem = pfilter->items; 573 if (pfilter->actived) 574 { 575 while (count) 576 { 577 if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) 578 { 579 count--; 580 pitem++; 581 continue; 582 } 583 584 level = rt_hw_interrupt_disable(); 585 if (!can->hdr[pitem->hdr].connected) 586 { 587 rt_hw_interrupt_enable(level); 588 rt_memcpy(&can->hdr[pitem->hdr].filter, pitem, 589 sizeof(struct rt_can_filter_item)); 590 level = rt_hw_interrupt_disable(); 591 can->hdr[pitem->hdr].connected = 1; 592 can->hdr[pitem->hdr].msgs = 0; 593 rt_list_init(&can->hdr[pitem->hdr].list); 594 } 595 rt_hw_interrupt_enable(level); 596 597 count--; 598 pitem++; 599 } 600 } 601 else 602 { 603 while (count) 604 { 605 if (pitem->hdr >= can->config.maxhdr || pitem->hdr < 0) 606 { 607 count--; 608 pitem++; 609 continue; 610 } 611 level = rt_hw_interrupt_disable(); 612 613 if (can->hdr[pitem->hdr].connected) 614 { 615 can->hdr[pitem->hdr].connected = 0; 616 can->hdr[pitem->hdr].msgs = 0; 617 if (!rt_list_isempty(&can->hdr[pitem->hdr].list)) 618 { 619 rt_list_remove(can->hdr[pitem->hdr].list.next); 620 } 621 rt_hw_interrupt_enable(level); 622 rt_memset(&can->hdr[pitem->hdr].filter, 0, 623 sizeof(struct rt_can_filter_item)); 624 } 625 else 626 { 627 rt_hw_interrupt_enable(level); 628 } 629 count--; 630 pitem++; 631 } 632 } 633 } 634 break; 635 #endif /*RT_CAN_USING_HDR*/ 636 #ifdef RT_CAN_USING_BUS_HOOK 637 case RT_CAN_CMD_SET_BUS_HOOK: 638 can->bus_hook = (rt_can_bus_hook) args; 639 break; 640 #endif /*RT_CAN_USING_BUS_HOOK*/ 641 default : 642 /* control device */ 643 if (can->ops->control != RT_NULL) 644 { 645 can->ops->control(can, cmd, args); 646 } 647 break; 648 } 649 650 return RT_EOK; 651 } 652 653 /* 654 * can timer 655 */ 656 static void cantimeout(void *arg) 657 { 658 rt_can_t can = (rt_can_t)arg; 659 660 rt_device_control((rt_device_t)can, RT_CAN_CMD_GET_STATUS, (void *)&can->status); 661 662 if (can->status_indicate.ind != RT_NULL) 663 { 664 can->status_indicate.ind(can, can->status_indicate.args); 665 } 666 #ifdef RT_CAN_USING_BUS_HOOK 667 if(can->bus_hook) 668 { 669 can->bus_hook(can); 670 } 671 #endif /*RT_CAN_USING_BUS_HOOK*/ 672 if (can->timerinitflag == 1) 673 { 674 can->timerinitflag = 0xFF; 675 } 676 } 677 678 #ifdef RT_USING_DEVICE_OPS 679 const static struct rt_device_ops can_device_ops = 680 { 681 rt_can_init, 682 rt_can_open, 683 rt_can_close, 684 rt_can_read, 685 rt_can_write, 686 rt_can_control 687 }; 688 #endif 689 690 /* 691 * can register 692 */ 693 rt_err_t rt_hw_can_register(struct rt_can_device *can, 694 const char *name, 695 const struct rt_can_ops *ops, 696 void *data) 697 { 698 struct rt_device *device; 699 RT_ASSERT(can != RT_NULL); 700 701 device = &(can->parent); 702 703 device->type = RT_Device_Class_CAN; 704 device->rx_indicate = RT_NULL; 705 device->tx_complete = RT_NULL; 706 #ifdef RT_CAN_USING_HDR 707 can->hdr = RT_NULL; 708 #endif 709 can->can_rx = RT_NULL; 710 can->can_tx = RT_NULL; 711 rt_mutex_init(&(can->lock), "can", RT_IPC_FLAG_PRIO); 712 #ifdef RT_CAN_USING_BUS_HOOK 713 can->bus_hook = RT_NULL; 714 #endif /*RT_CAN_USING_BUS_HOOK*/ 715 716 #ifdef RT_USING_DEVICE_OPS 717 device->ops = &can_device_ops; 718 #else 719 device->init = rt_can_init; 720 device->open = rt_can_open; 721 device->close = rt_can_close; 722 device->read = rt_can_read; 723 device->write = rt_can_write; 724 device->control = rt_can_control; 725 #endif 726 can->ops = ops; 727 728 can->status_indicate.ind = RT_NULL; 729 can->status_indicate.args = RT_NULL; 730 rt_memset(&can->status, 0, sizeof(can->status)); 731 732 device->user_data = data; 733 734 can->timerinitflag = 0; 735 rt_timer_init(&can->timer, 736 name, 737 cantimeout, 738 (void *)can, 739 can->config.ticks, 740 RT_TIMER_FLAG_PERIODIC); 741 /* register a character device */ 742 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); 743 } 744 745 /* ISR for can interrupt */ 746 void rt_hw_can_isr(struct rt_can_device *can, int event) 747 { 748 switch (event & 0xff) 749 { 750 case RT_CAN_EVENT_RXOF_IND: 751 { 752 rt_base_t level; 753 level = rt_hw_interrupt_disable(); 754 can->status.dropedrcvpkg++; 755 rt_hw_interrupt_enable(level); 756 } 757 case RT_CAN_EVENT_RX_IND: 758 { 759 struct rt_can_msg tmpmsg; 760 struct rt_can_rx_fifo *rx_fifo; 761 struct rt_can_msg_list *listmsg = RT_NULL; 762 #ifdef RT_CAN_USING_HDR 763 rt_int32_t hdr; 764 #endif 765 int ch = -1; 766 rt_base_t level; 767 rt_uint32_t no; 768 769 rx_fifo = (struct rt_can_rx_fifo *)can->can_rx; 770 RT_ASSERT(rx_fifo != RT_NULL); 771 /* interrupt mode receive */ 772 RT_ASSERT(can->parent.open_flag & RT_DEVICE_FLAG_INT_RX); 773 774 no = event >> 8; 775 ch = can->ops->recvmsg(can, &tmpmsg, no); 776 if (ch == -1) break; 777 778 /* disable interrupt */ 779 level = rt_hw_interrupt_disable(); 780 can->status.rcvpkg++; 781 can->status.rcvchange = 1; 782 if (!rt_list_isempty(&rx_fifo->freelist)) 783 { 784 listmsg = rt_list_entry(rx_fifo->freelist.next, struct rt_can_msg_list, list); 785 rt_list_remove(&listmsg->list); 786 #ifdef RT_CAN_USING_HDR 787 rt_list_remove(&listmsg->hdrlist); 788 if (listmsg->owner != RT_NULL && listmsg->owner->msgs) 789 { 790 listmsg->owner->msgs--; 791 } 792 listmsg->owner = RT_NULL; 793 #endif /*RT_CAN_USING_HDR*/ 794 RT_ASSERT(rx_fifo->freenumbers > 0); 795 rx_fifo->freenumbers--; 796 } 797 else if (!rt_list_isempty(&rx_fifo->uselist)) 798 { 799 listmsg = rt_list_entry(rx_fifo->uselist.next, struct rt_can_msg_list, list); 800 can->status.dropedrcvpkg++; 801 rt_list_remove(&listmsg->list); 802 #ifdef RT_CAN_USING_HDR 803 rt_list_remove(&listmsg->hdrlist); 804 if (listmsg->owner != RT_NULL && listmsg->owner->msgs) 805 { 806 listmsg->owner->msgs--; 807 } 808 listmsg->owner = RT_NULL; 809 #endif 810 } 811 /* enable interrupt */ 812 rt_hw_interrupt_enable(level); 813 814 if (listmsg != RT_NULL) 815 { 816 rt_memcpy(&listmsg->data, &tmpmsg, sizeof(struct rt_can_msg)); 817 level = rt_hw_interrupt_disable(); 818 rt_list_insert_before(&rx_fifo->uselist, &listmsg->list); 819 #ifdef RT_CAN_USING_HDR 820 hdr = tmpmsg.hdr; 821 if (can->hdr != RT_NULL) 822 { 823 RT_ASSERT(hdr < can->config.maxhdr && hdr >= 0); 824 if (can->hdr[hdr].connected) 825 { 826 rt_list_insert_before(&can->hdr[hdr].list, &listmsg->hdrlist); 827 listmsg->owner = &can->hdr[hdr]; 828 can->hdr[hdr].msgs++; 829 } 830 831 } 832 #endif 833 rt_hw_interrupt_enable(level); 834 } 835 836 /* invoke callback */ 837 #ifdef RT_CAN_USING_HDR 838 if (can->hdr != RT_NULL && can->hdr[hdr].connected && can->hdr[hdr].filter.ind) 839 { 840 rt_size_t rx_length; 841 RT_ASSERT(hdr < can->config.maxhdr && hdr >= 0); 842 843 level = rt_hw_interrupt_disable(); 844 rx_length = can->hdr[hdr].msgs * sizeof(struct rt_can_msg); 845 rt_hw_interrupt_enable(level); 846 can->hdr[hdr].filter.ind(&can->parent, can->hdr[hdr].filter.args, hdr, rx_length); 847 } 848 else 849 #endif 850 { 851 if (can->parent.rx_indicate != RT_NULL) 852 { 853 rt_size_t rx_length; 854 855 level = rt_hw_interrupt_disable(); 856 /* get rx length */ 857 rx_length = rx_fifo->freenumbers * sizeof(struct rt_can_msg); 858 rt_hw_interrupt_enable(level); 859 860 can->parent.rx_indicate(&can->parent, rx_length); 861 } 862 } 863 break; 864 } 865 866 case RT_CAN_EVENT_TX_DONE: 867 case RT_CAN_EVENT_TX_FAIL: 868 { 869 struct rt_can_tx_fifo *tx_fifo; 870 rt_uint32_t no; 871 no = event >> 8; 872 tx_fifo = (struct rt_can_tx_fifo *) can->can_tx; 873 RT_ASSERT(tx_fifo != RT_NULL); 874 875 if ((event & 0xff) == RT_CAN_EVENT_TX_DONE) 876 { 877 tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_OK; 878 } 879 else 880 { 881 tx_fifo->buffer[no].result = RT_CAN_SND_RESULT_ERR; 882 } 883 rt_completion_done(&(tx_fifo->buffer[no].completion)); 884 break; 885 } 886 } 887 } 888 889 #ifdef RT_USING_FINSH 890 #include <finsh.h> 891 int cmd_canstat(int argc, void **argv) 892 { 893 static const char *ErrCode[] = 894 { 895 "No Error!", 896 "Warning !", 897 "Passive !", 898 "Bus Off !" 899 }; 900 901 if (argc >= 2) 902 { 903 struct rt_can_status status; 904 rt_device_t candev = rt_device_find(argv[1]); 905 if (!candev) 906 { 907 rt_kprintf(" Can't find can device %s\n", argv[1]); 908 return -1; 909 } 910 rt_kprintf(" Finded can device: %s...", argv[1]); 911 912 rt_device_control(candev, RT_CAN_CMD_GET_STATUS, &status); 913 rt_kprintf("\n Receive...error..count: %010ld. Send.....error....count: %010ld.", 914 status.rcverrcnt, status.snderrcnt); 915 rt_kprintf("\n Bit..pad..error..count: %010ld. Format...error....count: %010ld", 916 status.bitpaderrcnt, status.formaterrcnt); 917 rt_kprintf("\n Ack.......error..count: %010ld. Bit......error....count: %010ld.", 918 status.ackerrcnt, status.biterrcnt); 919 rt_kprintf("\n CRC.......error..count: %010ld. Error.code.[%010ld]: ", 920 status.crcerrcnt, status.errcode); 921 switch (status.errcode) 922 { 923 case 0: 924 rt_kprintf("%s.", ErrCode[0]); 925 break; 926 case 1: 927 rt_kprintf("%s.", ErrCode[1]); 928 break; 929 case 2: 930 case 3: 931 rt_kprintf("%s.", ErrCode[2]); 932 break; 933 case 4: 934 case 5: 935 case 6: 936 case 7: 937 rt_kprintf("%s.", ErrCode[3]); 938 break; 939 } 940 rt_kprintf("\n Total.receive.packages: %010ld. Droped.receive.packages: %010ld.", 941 status.rcvpkg, status.dropedrcvpkg); 942 rt_kprintf("\n Total..send...packages: %010ld. Droped...send..packages: %010ld.\n", 943 status.sndpkg + status.dropedsndpkg, status.dropedsndpkg); 944 } 945 else 946 { 947 rt_kprintf(" Invalid Call %s\n", argv[0]); 948 rt_kprintf(" Please using %s cannamex .Here canname is driver name and x is candrive number.\n", argv[0]); 949 } 950 return 0; 951 } 952 FINSH_FUNCTION_EXPORT_ALIAS(cmd_canstat, __cmd_canstat, Stat Can Device Status.); 953 #endif 954 955