stm32_can.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. /*
  2. * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
  3. * Copyright (C) 2010 by Rittal GmbH & Co. KG. All rights reserved.
  4. * Copyright (C) 2012-2014 by Uwe Bonnes
  5. * (bon@elektron.ikp.physik.tu-darmstadt.de)
  6. *
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the copyright holders nor the names of
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  30. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  31. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. *
  34. * For additional information see http://www.ethernut.de/
  35. *
  36. */
  37. /*!
  38. * \verbatim
  39. * $Id$
  40. * \endverbatim
  41. */
  42. /*!
  43. * \file dev/can_dev.h
  44. * \brief Headers for canbus interface
  45. */
  46. #include <sys/event.h>
  47. #include <sys/heap.h>
  48. #include <sys/atom.h>
  49. #include <string.h>
  50. #include <dev/canbus.h>
  51. /* Time out for INAK bit */
  52. #define INAK_TimeOut ((uint32_t)0x0000FFFF)
  53. /* Time out for SLAK bit */
  54. #define SLAK_TimeOut ((uint32_t)0x0000FFFF)
  55. static int CanSetState(NUTCANBUS *bus, int enable)
  56. {
  57. int rc;
  58. uint32_t wait_ack = 0;
  59. __IO uint32_t *CANBBx = bus->bb_base;
  60. if (!bus->sig_tx_irq)
  61. /* we may not set the companion */
  62. return CAN_IS_COMPANION;
  63. if(enable)
  64. {
  65. CM3BB_OFFSETCLR(CANBBx, CAN_TypeDef, MCR, CAN_MCR_INRQ);
  66. /* Wait the acknowledge */
  67. for(wait_ack = 0, rc = 1; (rc) && (wait_ack < INAK_TimeOut); wait_ack++)
  68. rc = CM3BB_OFFSETGET(CANBBx, CAN_TypeDef, MSR, CAN_MSR_INAK);
  69. return (rc == 0)?0:CAN_BUS_OFF;
  70. }
  71. else
  72. {
  73. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, MCR, CAN_MCR_INRQ);
  74. /* Wait the acknowledge */
  75. for(wait_ack = 0, rc = 0; (!rc) && (wait_ack < INAK_TimeOut); wait_ack++)
  76. rc = CM3BB_OFFSETGET(CANBBx, CAN_TypeDef, MSR, CAN_MSR_INAK);
  77. return (rc==1)?0:CAN_ERROR;
  78. }
  79. }
  80. static void STMCanTXInterrupt( void *arg)
  81. {
  82. NUTCANBUS *bus = arg;
  83. CANBUSINFO *ci = bus->bus_ci;
  84. __IO uint32_t *CANBBx = bus->bb_base;
  85. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, IER, CAN_IER_TMEIE);
  86. ci->can_tx_interrupts++;
  87. NutEventPostFromIrq(&(ci->can_tx_rdy));
  88. }
  89. static void STMCanRX0Interrupt( void *arg)
  90. {
  91. NUTCANBUS *bus = arg;
  92. CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base;
  93. CANBUSINFO *ci = bus->bus_ci;
  94. CANBUFFER *rxbuf = &(ci->can_RxBuf);
  95. __IO uint32_t *CANBBx = bus->bb_base;
  96. if (CM3BB_OFFSETGET(CANBBx, CAN_TypeDef, RF0R, CAN_RF0R_FOVR0))
  97. {
  98. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, RF0R,_BI32(CAN_RF0R_FOVR0));
  99. ci->can_overruns++;
  100. }
  101. ci->can_rx_interrupts++;
  102. while(CANx->RF0R & 3)
  103. {
  104. // Space in buffer ?
  105. if (rxbuf->datalength < rxbuf->size)
  106. {
  107. int index = (rxbuf->dataindex + rxbuf->datalength) % rxbuf->size;
  108. CAN_FIFOMailBox_TypeDef*bufPtr = &rxbuf->dataptr[index];
  109. memcpy(bufPtr, &CANx->sFIFOMailBox[0], sizeof(CAN_FIFOMailBox_TypeDef));
  110. /*Increment buffer length */
  111. rxbuf->datalength++;
  112. NutEventPostFromIrq(&ci->can_rx_rdy);
  113. /* Statistic housekeeping */
  114. ci->can_rx_frames++;
  115. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, RF0R, CAN_RF0R_RFOM0);
  116. while(CM3BB_OFFSETGET(CANBBx, CAN_TypeDef, RF0R, CAN_RF0R_RFOM0));
  117. }
  118. else
  119. {
  120. /* No overrun yet, but we can't clean the FIFO yet */
  121. /* Disable the FIFO message pending interrupt*/
  122. CM3BB_OFFSETCLR(CANBBx, CAN_TypeDef, IER, CAN_IER_FMPIE0);
  123. return;
  124. }
  125. }
  126. }
  127. static void STMCanRX1Interrupt( void *arg)
  128. {
  129. NUTCANBUS *bus = arg;
  130. CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base;
  131. CANBUSINFO *ci = bus->bus_ci;
  132. CANBUFFER *rxbuf = &(ci->can_RxBuf);
  133. __IO uint32_t *CANBBx = bus->bb_base;
  134. if (CM3BB_OFFSETGET(CANBBx, CAN_TypeDef, RF1R, CAN_RF1R_FOVR1))
  135. {
  136. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, RF1R,_BI32(CAN_RF1R_FOVR1));
  137. ci->can_overruns++;
  138. }
  139. ci->can_rx_interrupts++;
  140. while(CANx->RF1R & 3)
  141. {
  142. // Space in buffer ?
  143. if (rxbuf->datalength < rxbuf->size)
  144. {
  145. int index = (rxbuf->dataindex + rxbuf->datalength) % rxbuf->size;
  146. CAN_FIFOMailBox_TypeDef*bufPtr = &rxbuf->dataptr[index];
  147. memcpy(bufPtr, &CANx->sFIFOMailBox[1], sizeof(CAN_FIFOMailBox_TypeDef));
  148. // Increment buffer length
  149. rxbuf->datalength++;
  150. NutEventPostFromIrq(&ci->can_rx_rdy);
  151. // Stat houskeeping
  152. ci->can_rx_frames++;
  153. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, RF1R, CAN_RF1R_RFOM1);
  154. while(CM3BB_OFFSETGET(CANBBx, CAN_TypeDef, RF1R, CAN_RF1R_RFOM1));
  155. }
  156. else
  157. {
  158. /* No overrun yet, but we can't clean the FIFO yet */
  159. /* Disable the FIFO message pending interrupt*/
  160. CM3BB_OFFSETCLR(CANBBx, CAN_TypeDef, IER, CAN_IER_FMPIE1);
  161. return;
  162. }
  163. }
  164. }
  165. /* Simple acknowledge the error and count it.
  166. * TODO: Better error handling
  167. */
  168. static void STMCanErrorInterrupt( void *arg)
  169. {
  170. NUTCANBUS *bus = arg;
  171. CANBUSINFO *ci = bus->bus_ci;
  172. __IO uint32_t *CANBBx = bus->bb_base;
  173. CM3BB_OFFSETCLR(CANBBx, CAN_TypeDef, MSR, CAN_MSR_ERRI);
  174. ci->can_sce_interrupts++;
  175. }
  176. /*
  177. * \brief Set a CAN identifier filter
  178. *
  179. * \param bus
  180. * \param filter
  181. * @return 0 if filter could be inserted in the list, CANRESULT else
  182. *
  183. * The Filter registers belong to CAN1
  184. *
  185. * Filter may be exact 29 bit match(29 E), 29 bit with mask (29M), exact 16 bit (16E) and
  186. * 11 bit with mask (16M)
  187. *
  188. * A STM32 filter bank entry may hold one 29M, two 29E, two 16M and four 16E, with all entries
  189. * in a bank of same type. if we e.g. add the first 29E entry, we mark the second 29E entry with
  190. * FILTER_EXPLICIT and replace this placeholder on the write of the second 29E entry. A 16(M|E) entry must
  191. * have the high 16 id/ask bits NULL
  192. *
  193. * We don't explicit stop reception, so when adding 29E/16M/16E to a partial populated
  194. * filter bank, the other entries of that filter bank are temporary inactive
  195. *
  196. */
  197. int CanAddFilter( NUTCANBUS *bus, CANFILTER *filter)
  198. {
  199. int i, index_start, max_index;
  200. uint32_t mode = CAN1->FM1R;
  201. uint32_t scale = CAN1->FS1R;
  202. uint32_t assignment = CAN1->FFA1R;
  203. uint32_t activation = CAN1->FA1R;
  204. int fifo = (bus->sig_tx_irq)?0:1; /* FIFO1 is reveive only*/
  205. if (bus->bus_base == CAN1_BASE)
  206. {
  207. index_start = 0;
  208. max_index = (CAN1->FMR)>>8 & 0x3f;
  209. }
  210. else
  211. {
  212. index_start = (CAN1->FMR)>>8 & 0x3f;
  213. max_index = sizeof(CAN1->sFilterRegister)/sizeof(CAN1->sFilterRegister[0]);
  214. }
  215. if(filter->mask == FILTER_EXPLICIT) /* Explicit*/
  216. {
  217. if ((filter-> id) > 0xffff) /* 29 E*/
  218. {
  219. uint32_t id_29 = (filter->id << 3) | ((filter->id_ext)?4:0) | ((filter->id_rtr)? 2:0);
  220. for(i=index_start; i<max_index; i++)
  221. {
  222. if (!(activation & (1<<i)))
  223. {
  224. CAN_FilterRegister_TypeDef *free_entry = &(CAN1->sFilterRegister[i]);
  225. free_entry->FR1 = id_29;
  226. free_entry->FR2 = 0xffffffff;
  227. activation |= (1<<i);
  228. if (fifo)
  229. assignment |= (1<<i);
  230. else
  231. assignment &= ~(1<<i);
  232. mode |= (1<<i);
  233. scale |= (1<<i);
  234. goto flt_success;
  235. }
  236. else if(((assignment & (1<<i)) == (fifo <<i)) &&
  237. ( mode & (1<<i)) &&
  238. ( scale & (1<<i)))
  239. /* Entry matches type and may have space */
  240. {
  241. CAN_FilterRegister_TypeDef *partial_entry = &(CAN1->sFilterRegister[i]);
  242. if (partial_entry->FR2 == 0xffffffff)
  243. {
  244. CAN1->FA1R = (activation & ~(1<<i)); /* Mark entry for writing */
  245. partial_entry->FR2 = id_29;
  246. goto flt_success;
  247. }
  248. }
  249. }
  250. }
  251. else
  252. {
  253. uint16_t id_16 = ((filter->id >>16) & 0x7) |((filter->id & 0x7ff) << 5) | ((filter->id_ext )?8:0) | ((filter->id_rtr )? 0x10:0);
  254. for(i=index_start; i<max_index; i++)
  255. {
  256. if (!(activation & (1<<i)))
  257. {
  258. CAN_FilterRegister_TypeDef *free_entry = &(CAN1->sFilterRegister[i]);
  259. free_entry->FR1 = 0xffff0000 | id_16;
  260. free_entry->FR2 = 0xffffffff;
  261. activation |= (1<<i);
  262. if (fifo)
  263. assignment |= (1<<i);
  264. else
  265. assignment &= ~(1<<i);
  266. mode |= (1<<i);
  267. scale &= ~(1<<i);
  268. goto flt_success;
  269. }
  270. else if(((assignment & (1<<i)) == (fifo <<i)) &&
  271. ( mode & (1<<i)) &&
  272. !( scale & (1<<i)))
  273. /* Entry matches type and may have space */
  274. {
  275. /* Only (32 bit) word access to CAN Registers allowed! */
  276. CAN_FilterRegister_TypeDef *partial_entry = &(CAN1->sFilterRegister[i]);
  277. if ((partial_entry->FR1 & 0xffff0000) == 0xffff0000)
  278. {
  279. CAN1->FA1R = (activation & ~(1<<i)); /* Mark entry for writing */
  280. partial_entry->FR1 &= 0x0000ffff;
  281. partial_entry->FR1 |= (id_16 <<16);
  282. goto flt_success;
  283. }
  284. else if (partial_entry->FR2 == 0xffffffff)
  285. {
  286. CAN1->FA1R = (activation & ~(1<<i)); /* Mark entry for writing */
  287. partial_entry->FR2 = 0xffff0000 | id_16;
  288. goto flt_success;
  289. }
  290. else if ((partial_entry->FR2 & 0xffff0000) == 0xffff0000)
  291. {
  292. CAN1->FA1R = (activation & ~(1<<i)); /* Mark entry for writing */
  293. partial_entry->FR2 &= 0x0000ffff;
  294. partial_entry->FR2 |= (id_16 <<16);
  295. goto flt_success;
  296. }
  297. }
  298. }
  299. }
  300. }
  301. else if (filter->mask > 0xffff) /* 29 M*/
  302. {
  303. for(i=index_start; i<max_index; i++)
  304. {
  305. /* find first free entry */
  306. if (!(activation & (1<<i)))
  307. {
  308. CAN_FilterRegister_TypeDef *free_entry = &(CAN1->sFilterRegister[i]);
  309. uint32_t id_29 = (filter->id << 3) | ((filter->id_ext )?4:0) | ((filter->id_rtr )?2:0);
  310. uint32_t mask_29 = (filter->mask << 3) | ((filter->mask_ext)?4:0) | ((filter->mask_rtr)?2:0);
  311. free_entry->FR1 = id_29;
  312. free_entry->FR2 = mask_29;
  313. activation |= (1<<i);
  314. if (fifo)
  315. assignment |= (1<<i);
  316. else
  317. assignment &= ~(1<<i);
  318. mode &= ~(1<<i);
  319. scale |= (1<<i);
  320. goto flt_success;
  321. }
  322. }
  323. }
  324. else
  325. {
  326. uint16_t id_16 = ((filter->id >>16) & 0x7) |((filter->id & 0x7ff) << 5) | ((filter->id_ext )?8:0) | ((filter->id_rtr )? 0x10:0);
  327. uint16_t mask_16 = ((filter->mask>>16) & 0x7) |((filter->mask& 0x7ff) << 5) | ((filter->mask_ext)?8:0) | ((filter->mask_rtr)? 0x10:0);
  328. for(i=index_start; i<max_index; i++)
  329. {
  330. if (!(activation & (1<<i)))
  331. {
  332. CAN_FilterRegister_TypeDef *free_entry = &(CAN1->sFilterRegister[i]);
  333. free_entry->FR1 = (mask_16 << 16) | id_16;
  334. free_entry->FR2 = 0xffffffff;
  335. activation |= (1<<i);
  336. if (fifo)
  337. assignment |= (1<<i);
  338. else
  339. assignment &= ~(1<<i);
  340. mode &= ~(1<<i);
  341. scale &= ~(1<<i);
  342. goto flt_success;
  343. }
  344. else if(((assignment & (1<<i)) == (fifo <<i)) &&
  345. !( mode & (1<<i)) &&
  346. !( scale & (1<<i)))
  347. /* Entry matches type and may have space */
  348. {
  349. CAN_FilterRegister_TypeDef *partial_entry = &(CAN1->sFilterRegister[i]);
  350. if (partial_entry->FR2 == 0xffffffff)
  351. {
  352. CAN1->FA1R = (activation & ~(1<<i)); /* Mark entry for writing */
  353. partial_entry->FR2 = (mask_16 << 16) |id_16;
  354. goto flt_success;
  355. }
  356. }
  357. }
  358. }
  359. return CAN_ILLEGAL_MOB;
  360. flt_success:
  361. CAN1->FM1R = mode;
  362. CAN1->FS1R = scale;
  363. CAN1->FFA1R = assignment;
  364. CAN1->FA1R = activation;
  365. return 0;
  366. }
  367. int CanRxAvail(NUTCANBUS *bus)
  368. {
  369. CANBUSINFO *ci = bus->bus_ci;
  370. CANBUFFER *rxbuf = &(ci->can_RxBuf);
  371. return rxbuf->datalength;
  372. }
  373. /*!
  374. * \brief Set CAN Bus features during initialization.
  375. *
  376. *
  377. */
  378. int CanSetFeatures( NUTCANBUS *bus, uint32_t flags, uint8_t ena)
  379. {
  380. int rc = 0;
  381. CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base;
  382. uint32_t mcr = CANx->MCR;
  383. if (!bus->sig_tx_irq)
  384. /* we may not set the companion */
  385. return CAN_IS_COMPANION;
  386. if (CanSetState(bus, 0))
  387. return CAN_ERROR;
  388. /* Set the time triggered communication mode */
  389. if (flags & CAN_TTCM) {
  390. if( ena)
  391. mcr |= CAN_MCR_TTCM;
  392. else
  393. mcr &= ~CAN_MCR_TTCM;
  394. }
  395. /* Set the automatic bus-off management */
  396. if (flags&CAN_ABOM) {
  397. if( ena)
  398. mcr |= CAN_MCR_ABOM;
  399. else
  400. mcr &= ~CAN_MCR_ABOM;
  401. }
  402. /* Set the automatic wake-up mode */
  403. if (flags&CAN_AWUM) {
  404. if (ena)
  405. mcr |= CAN_MCR_AWUM;
  406. else
  407. mcr &= ~CAN_MCR_AWUM;
  408. }
  409. /* Set the no automatic retransmission */
  410. if (flags&CAN_NART) {
  411. if (ena)
  412. mcr |= CAN_MCR_NART;
  413. else
  414. mcr &= ~CAN_MCR_NART;
  415. }
  416. /* Set the receive FIFO locked mode */
  417. if (flags&CAN_RFLM) {
  418. if (ena)
  419. mcr |= CAN_MCR_RFLM;
  420. else
  421. mcr &= ~CAN_MCR_RFLM;
  422. }
  423. /* Set the transmit FIFO priority */
  424. if (flags&CAN_TXFP) {
  425. if (ena)
  426. mcr |= CAN_MCR_TXFP;
  427. else
  428. mcr &= ~CAN_MCR_TXFP;
  429. }
  430. CANx->MCR = mcr;
  431. if (CanSetState(bus, 1))
  432. return CAN_BUS_OFF;
  433. return rc;
  434. }
  435. int CanGetFeatures( NUTCANBUS *bus, uint32_t flags)
  436. {
  437. int rc = CAN_ERROR;
  438. CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base;
  439. uint32_t mcr = CANx->MCR;
  440. if (flags&CAN_TTCM) {
  441. /* Get time triggered communication mode */
  442. rc = (mcr&CAN_MCR_TTCM)?1:0;
  443. }
  444. else if (flags&CAN_ABOM) {
  445. /* Get automatic bus-off management */
  446. rc = (mcr&CAN_MCR_ABOM)?1:0;
  447. }
  448. else if (flags&CAN_AWUM) {
  449. /* Get automatic wake-up mode */
  450. rc = (mcr&CAN_MCR_AWUM)?1:0;
  451. }
  452. else if (flags&CAN_NART) {
  453. /* Get the no automatic retransmission config */
  454. rc = (mcr&CAN_MCR_NART)?1:0;
  455. }
  456. else if (flags&CAN_RFLM) {
  457. /* Get receive FIFO locked mode */
  458. rc = (mcr&CAN_MCR_RFLM)?1:0;
  459. }
  460. else if (flags&CAN_TXFP) {
  461. /* Set the transmit FIFO priority */
  462. rc = (mcr&CAN_MCR_TXFP)?1:0;
  463. }
  464. return rc;
  465. }
  466. #define CAN_APB1_DIV(x) ((x-1) & 0x3ff)
  467. #define CAN_BS1(x) (((x-1) & 0xf) << 16)
  468. #define CAN_BS2(x) (((x-1) & 0x7) << 20)
  469. #define CAN_SJW(x) (((x-1) & 0x3) << 24)
  470. #if defined(MCU_STM32F1) || defined(MCU_STM32F3)
  471. #define STM_CAN_ABP1_CHECK 36000000
  472. #define STM_CAN_BTR_1M (CAN_APB1_DIV(2) |CAN_BS1(15)|CAN_BS2(2)|CAN_SJW(2))
  473. #define STM_CAN_BTR_800k (CAN_APB1_DIV(3) |CAN_BS1(12)|CAN_BS2(2)|CAN_SJW(2))
  474. #define STM_CAN_BTR_500k (CAN_APB1_DIV(4) |CAN_BS1(14)|CAN_BS2(3)|CAN_SJW(2))
  475. #define STM_CAN_BTR_250k (CAN_APB1_DIV(9) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  476. #define STM_CAN_BTR_125k (CAN_APB1_DIV(18) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  477. #define STM_CAN_BTR_100k (CAN_APB1_DIV(20) |CAN_BS1(14)|CAN_BS2(3)|CAN_SJW(2))
  478. #define STM_CAN_BTR_50k (CAN_APB1_DIV(45) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  479. #define STM_CAN_BTR_20k (CAN_APB1_DIV(100)|CAN_BS1(15)|CAN_BS2(2)|CAN_SJW(2))
  480. #define STM_CAN_BTR_10k (CAN_APB1_DIV(225)|CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  481. #elif defined(MCU_STM32L1)
  482. #define STM_CAN_ABP1_CHECK 32000000
  483. #define STM_CAN_BTR_1M (CAN_APB1_DIV(2) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  484. #define STM_CAN_BTR_800k (CAN_APB1_DIV(2) |CAN_BS1(16)|CAN_BS2(3)|CAN_SJW(2))
  485. #define STM_CAN_BTR_500k (CAN_APB1_DIV(4) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  486. #define STM_CAN_BTR_250k (CAN_APB1_DIV(8) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  487. #define STM_CAN_BTR_125k (CAN_APB1_DIV(16) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  488. #define STM_CAN_BTR_100k (CAN_APB1_DIV(20) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  489. #define STM_CAN_BTR_50k (CAN_APB1_DIV(40) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  490. #define STM_CAN_BTR_20k (CAN_APB1_DIV(100)|CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  491. #define STM_CAN_BTR_10k (CAN_APB1_DIV(200)|CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  492. #elif defined(MCU_STM32F2)
  493. #define STM_CAN_ABP1_CHECK 30000000
  494. #define STM_CAN_BTR_1M (CAN_APB1_DIV(2) |CAN_BS1(12)|CAN_BS2(2)|CAN_SJW(2))
  495. #define STM_CAN_BTR_800k 0
  496. #define STM_CAN_BTR_500k (CAN_APB1_DIV(3) |CAN_BS1(16)|CAN_BS2(3)|CAN_SJW(2))
  497. #define STM_CAN_BTR_250k (CAN_APB1_DIV(6) |CAN_BS1(16)|CAN_BS2(3)|CAN_SJW(2))
  498. #define STM_CAN_BTR_125k (CAN_APB1_DIV(15) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  499. #define STM_CAN_BTR_100k (CAN_APB1_DIV(20) |CAN_BS1(12)|CAN_BS2(2)|CAN_SJW(2))
  500. #define STM_CAN_BTR_50k (CAN_APB1_DIV(30) |CAN_BS1(16)|CAN_BS2(3)|CAN_SJW(2))
  501. #define STM_CAN_BTR_20k (CAN_APB1_DIV(75) |CAN_BS1(16)|CAN_BS2(3)|CAN_SJW(2))
  502. #define STM_CAN_BTR_10k (CAN_APB1_DIV(150)|CAN_BS1(16)|CAN_BS2(3)|CAN_SJW(2))
  503. #elif defined(MCU_STM32F4)
  504. #define STM_CAN_ABP1_CHECK 42000000
  505. #define STM_CAN_BTR_1M (CAN_APB1_DIV(2) |CAN_BS1(16)|CAN_BS2(4)|CAN_SJW(2))
  506. #define STM_CAN_BTR_800k 0
  507. #define STM_CAN_BTR_500k (CAN_APB1_DIV(4) |CAN_BS1(16)|CAN_BS2(4)|CAN_SJW(2))
  508. #define STM_CAN_BTR_250k (CAN_APB1_DIV(8) |CAN_BS1(16)|CAN_BS2(4)|CAN_SJW(2))
  509. #define STM_CAN_BTR_125k (CAN_APB1_DIV(21) |CAN_BS1(13)|CAN_BS2(2)|CAN_SJW(2))
  510. #define STM_CAN_BTR_100k (CAN_APB1_DIV(20) |CAN_BS1(16)|CAN_BS2(4)|CAN_SJW(2))
  511. #define STM_CAN_BTR_50k (CAN_APB1_DIV(40) |CAN_BS1(16)|CAN_BS2(4)|CAN_SJW(2))
  512. #define STM_CAN_BTR_20k (CAN_APB1_DIV(100)|CAN_BS1(16)|CAN_BS2(4)|CAN_SJW(2))
  513. #define STM_CAN_BTR_10k (CAN_APB1_DIV(200)|CAN_BS1(16)|CAN_BS2(4)|CAN_SJW(2))
  514. #else
  515. #warning "Unknown STM32 family"
  516. #endif
  517. #define BTR2FREQ(x) (((x & 0x3ff) + 1) * (((x >> 16) & 0xf) + ((x >> 20) & 0x7) + 3))
  518. /* Check the defines */
  519. #if (STM_CAN_BTR_10k != 0) && ((10000 * BTR2FREQ(STM_CAN_BTR_10k)) != STM_CAN_ABP1_CHECK)
  520. #warning "Bad BTR setting for STM_CAN_BTR_10k"
  521. #endif
  522. #if (STM_CAN_BTR_20k != 0) && ((20000 * BTR2FREQ(STM_CAN_BTR_20k)) != STM_CAN_ABP1_CHECK)
  523. #warning "Bad BTR setting for STM_CAN_BTR_20k"
  524. #endif
  525. #if (STM_CAN_BTR_50k != 0) && ((50000 * BTR2FREQ(STM_CAN_BTR_50k)) != STM_CAN_ABP1_CHECK)
  526. #warning "Bad BTR setting for STM_CAN_BTR_50k"
  527. #endif
  528. #if (STM_CAN_BTR_100k != 0) && ((100000 * BTR2FREQ(STM_CAN_BTR_100k)) != STM_CAN_ABP1_CHECK)
  529. #warning "Bad BTR setting for STM_CAN_BTR_100k"
  530. #endif
  531. #if (STM_CAN_BTR_125k != 0) && ((125000 * BTR2FREQ(STM_CAN_BTR_125k)) != STM_CAN_ABP1_CHECK)
  532. #warning "Bad BTR setting for STM_CAN_BTR_125k"
  533. #endif
  534. #if (STM_CAN_BTR_250k != 0) && ((250000 * BTR2FREQ(STM_CAN_BTR_250k)) != STM_CAN_ABP1_CHECK)
  535. #warning "Bad BTR setting for STM_CAN_BTR_250k"
  536. #endif
  537. #if (STM_CAN_BTR_500k != 0) && ((500000 * BTR2FREQ(STM_CAN_BTR_500k)) != STM_CAN_ABP1_CHECK)
  538. #warning "Bad BTR setting for STM_CAN_BTR_500k"
  539. #endif
  540. #if (STM_CAN_BTR_800k != 0) && ((800000 * BTR2FREQ(STM_CAN_BTR_800k)) != STM_CAN_ABP1_CHECK)
  541. #warning "Bad BTR setting for STM_CAN_BTR_800k"
  542. #endif
  543. #if (STM_CAN_BTR_1M != 0) && ((1000000 * BTR2FREQ(STM_CAN_BTR_1M)) != STM_CAN_ABP1_CHECK)
  544. #warning "Bad BTR setting for STM_CAN_BTR_1M"
  545. #endif
  546. /*!
  547. * Set the baudrate
  548. * \param bus Identifies the CANBUS
  549. * \param baud Symbolic value for the Baudrate
  550. * \param alt_btr Use given value with CAN_SPEED_CUSTOM
  551. *
  552. * For STM32, alt_btr may be used for setting silent/loopback silent+loopback mode
  553. *
  554. * \return 0 if baudrate can be delivered or -1 else
  555. */
  556. int CanSetBaud( NUTCANBUS *bus, int baud, uint32_t alt_btr)
  557. {
  558. /* CAN is connected to APB1 bus. Max frequency varies with family:
  559. F1: 36 MHz
  560. L1: 32 MHz
  561. F2: 30 MHz
  562. F3: 30 MHz
  563. F4: 42 MHz
  564. Assume this frequency for defining the BTR register for now.
  565. If we need to cope with other APB1 Clocks, this gets much more
  566. complicated.
  567. If my understanding is right, BS1 == 13 and BS2 == 2 gives the
  568. CiA proposed 87.5 % sampling point. Sync is always 1.
  569. (Sync + BS1) /(Sync + BS1 + BS2) = 14/16 = 0.875
  570. For high rates we keep and adjust BS1
  571. */
  572. uint32_t btr= 0;
  573. CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base;
  574. if (!bus->sig_tx_irq)
  575. /* we may not set the companion */
  576. return CAN_IS_COMPANION;
  577. if (CanSetState(bus, 0))
  578. return CAN_ERROR;
  579. switch (baud)
  580. {
  581. case CAN_SPEED_10K:
  582. btr = STM_CAN_BTR_10k;
  583. break;
  584. case CAN_SPEED_20K:
  585. btr = STM_CAN_BTR_20k;
  586. break;
  587. case CAN_SPEED_50K:
  588. btr = STM_CAN_BTR_50k;
  589. break;
  590. case CAN_SPEED_100K:
  591. btr = STM_CAN_BTR_100k;
  592. break;
  593. case CAN_SPEED_125K:
  594. btr = STM_CAN_BTR_125k;
  595. break;
  596. case CAN_SPEED_250K:
  597. btr = STM_CAN_BTR_250k;
  598. break;
  599. case CAN_SPEED_500K:
  600. btr = STM_CAN_BTR_500k;
  601. break;
  602. case CAN_SPEED_800K:
  603. btr = STM_CAN_BTR_800k;
  604. break;
  605. case CAN_SPEED_1M:
  606. btr = STM_CAN_BTR_1M;
  607. break;
  608. case CAN_SPEED_CUSTOM:
  609. btr = alt_btr;
  610. break;
  611. default:
  612. return CAN_INVALID_SPEED;
  613. }
  614. if (btr == 0)
  615. return CAN_ERROR;
  616. CANx->BTR &= ~0x03ff03ff ;
  617. CANx->BTR |= btr;
  618. if (CanSetState(bus, 1))
  619. return CAN_BUS_OFF;
  620. return 0;
  621. }
  622. void CANSetRxTimeout(NUTCANBUS *bus, uint32_t timeout)
  623. {
  624. CANBUSINFO *ci = bus->bus_ci;
  625. ci->can_rx_timeout = timeout;
  626. }
  627. void CANSetTxTimeout(NUTCANBUS *bus, uint32_t timeout)
  628. {
  629. CANBUSINFO *ci = bus->bus_ci;
  630. ci->can_tx_timeout = timeout;
  631. }
  632. static int Stm32CanBusInit( NUTCANBUS *bus)
  633. {
  634. int rc = 0;
  635. __IO uint32_t *CANBBx = bus->bb_base;
  636. uint32_t wait_ack = 0;
  637. if (!(bus->sig_tx_irq))
  638. { /* for the companion, we only check that CAN1/2 is clock */
  639. if (bus->bus_base == CAN1_BASE)
  640. rc = CM3BBGET(RCC_BASE, RCC_TypeDef, APB1ENR, _BI32(RCC_APB1ENR_CAN1EN));
  641. #ifdef RCC_APB1ENR_CAN2EN
  642. else
  643. rc = CM3BBGET(RCC_BASE, RCC_TypeDef, APB1ENR, _BI32(RCC_APB1ENR_CAN2EN));
  644. #endif
  645. if (rc)
  646. return 0;
  647. else
  648. return CAN_NO_COMPANION;
  649. }
  650. /* If bus has hardware init function, call it. */
  651. if( bus->bus_inithw) {
  652. rc = (bus->bus_inithw)();
  653. }
  654. if (rc)
  655. return rc;
  656. /* Software Master reset*/
  657. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, MCR, CAN_MCR_RESET);
  658. /* exit from sleep mode */
  659. CM3BB_OFFSETCLR(CANBBx, CAN_TypeDef, MCR, CAN_MCR_SLEEP);
  660. for(wait_ack = 0, rc = 1; (rc) && (wait_ack < SLAK_TimeOut); wait_ack++)
  661. rc = CM3BB_OFFSETGET(CANBBx, CAN_TypeDef, MSR, CAN_MSR_SLAK);
  662. return (rc == 0)?0:CAN_ERROR;
  663. /* We send tx mailboxes in chronological order and
  664. FOR NOW we don't retransmit on errer */
  665. CanSetFeatures( bus, CAN_TXFP | CAN_NART | CAN_ABOM , 1);
  666. return rc;
  667. }
  668. #define CAN_DEF_RX_ENTRIES 16
  669. /*!
  670. * \brief Initialize CAN interface.
  671. *
  672. * \param bus
  673. * \param entries Number of buffer Mailboxes, CAN_DEF_RX_ENTRIES if <1.
  674. *
  675. * Here we set up the Hardware, baudrate and special setting
  676. *
  677. */
  678. int NutRegisterCanBus( NUTCANBUS *bus, int entries )
  679. {
  680. int rc = CAN_ERROR;
  681. CANBUSINFO *ci = NULL;
  682. CANBUFFER *rxbuf;
  683. if (entries < 1)
  684. entries = CAN_DEF_RX_ENTRIES;
  685. void *dataptr = NutHeapAlloc(entries * sizeof(CAN_FIFOMailBox_TypeDef));
  686. if (dataptr == 0)
  687. return rc;
  688. memset( dataptr, 0, entries * sizeof(CAN_FIFOMailBox_TypeDef));
  689. ci = NutHeapAlloc(sizeof(CANBUSINFO));
  690. if( ci == NULL) {
  691. NutHeapFree(dataptr);
  692. return rc;
  693. }
  694. memset( ci, 0, sizeof(CANBUSINFO));
  695. rxbuf = &(ci->can_RxBuf);
  696. rxbuf->dataptr = dataptr;
  697. rxbuf->size = entries;
  698. rxbuf->dataindex = 0;
  699. rxbuf->datalength = 0;
  700. ci->can_rx_timeout = NUT_WAIT_INFINITE;
  701. /* Link bus and ci */
  702. bus->bus_ci = ci;
  703. if (bus->sig_tx_irq)
  704. {
  705. if( NutRegisterIrqHandler( bus->sig_tx_irq, STMCanTXInterrupt, bus ) ) {
  706. NutHeapFree(dataptr);
  707. NutHeapFree( ci);
  708. return rc;
  709. }
  710. }
  711. if (bus->sig_rx_irq)
  712. {
  713. if (bus->sig_tx_irq)
  714. {
  715. if( NutRegisterIrqHandler( bus->sig_rx_irq, STMCanRX0Interrupt, bus ) ) {
  716. NutHeapFree(dataptr);
  717. NutHeapFree( ci);
  718. return rc;
  719. }
  720. }
  721. else
  722. {
  723. if( NutRegisterIrqHandler( bus->sig_rx_irq, STMCanRX1Interrupt, bus ) ) {
  724. NutHeapFree(dataptr);
  725. NutHeapFree( ci);
  726. return rc;
  727. }
  728. }
  729. }
  730. if (bus->sig_sce_irq)
  731. {
  732. if( NutRegisterIrqHandler( bus->sig_sce_irq, STMCanErrorInterrupt, bus ) ) {
  733. NutHeapFree(dataptr);
  734. NutHeapFree( ci);
  735. return rc;
  736. }
  737. }
  738. rc= Stm32CanBusInit(bus);
  739. if (rc)
  740. {
  741. NutHeapFree(dataptr);
  742. NutHeapFree( ci);
  743. return rc;
  744. }
  745. if (bus->sig_tx_irq)
  746. {
  747. NutIrqSetPriority(bus->sig_tx_irq, 0);
  748. rc = NutIrqEnable(bus->sig_tx_irq);
  749. if( rc) {
  750. NutHeapFree(dataptr);
  751. NutHeapFree( ci);
  752. return rc;
  753. }
  754. }
  755. if (bus->sig_rx_irq)
  756. {
  757. NutIrqSetPriority(bus->sig_rx_irq, 1);
  758. rc = NutIrqEnable(bus->sig_rx_irq);
  759. if( rc) {
  760. NutHeapFree(dataptr);
  761. NutHeapFree( ci);
  762. return rc;
  763. }
  764. }
  765. if (bus->sig_sce_irq)
  766. {
  767. NutIrqSetPriority(bus->sig_sce_irq, 2);
  768. rc = NutIrqEnable(bus->sig_sce_irq);
  769. if( rc) {
  770. NutHeapFree(dataptr);
  771. NutHeapFree( ci);
  772. return rc;
  773. }
  774. }
  775. return rc;
  776. }
  777. /**
  778. * @internal
  779. * Search for a free mailbox
  780. * @return Index of first free mailbox or -1 if none is available
  781. */
  782. static int CANGetFreeMailbox(NUTCANBUS *bus)
  783. {
  784. CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base;
  785. uint32_t tsr = CANx->TSR;
  786. if (tsr & CAN_TSR_TME0)
  787. return 0;
  788. if (tsr & CAN_TSR_TME1)
  789. return 1;
  790. if (tsr & CAN_TSR_TME2)
  791. return 2;
  792. return CAN_TXBUF_FULL;
  793. }
  794. /* Fixme: This definition has to go to a common header to be agreed on*/
  795. #if defined(GCC)
  796. #define __MAY_ALIAS (__attribute__((__may_alias__)))
  797. #else
  798. #define __MAY_ALIAS
  799. #endif
  800. /**
  801. * Send a CAN message
  802. *
  803. * For buffers, we only use the internal tx mailboxes
  804. *
  805. * @param frame Container for CAN message to be sent
  806. * @return Result code. See @ref CAN_RESULT
  807. */
  808. static int StmCanSendMsg(NUTCANBUS *bus, CANFRAME *frame)
  809. {
  810. CAN_TypeDef *CANx = (CAN_TypeDef*)bus->bus_base;
  811. __IO uint32_t *CANBBx = bus->bb_base;
  812. uint32_t __MAY_ALIAS *tdlr = (uint32_t*) &(frame->byte[0]);
  813. uint32_t __MAY_ALIAS *tdhr = (uint32_t*) &(frame->byte[4]);
  814. uint32_t tir;
  815. CAN_TxMailBox_TypeDef *tx_mailbox;
  816. int index = CANGetFreeMailbox(bus);
  817. if (index < 0)
  818. {
  819. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, IER, CAN_IER_TMEIE);
  820. return CAN_TXBUF_FULL;
  821. }
  822. tx_mailbox = &(CANx->sTxMailBox[index]);
  823. tx_mailbox->TDLR = *tdlr;
  824. tx_mailbox->TDHR = *tdhr;
  825. tx_mailbox->TDTR = frame->len;
  826. if (frame->ext)
  827. {
  828. tir = frame->id << 3;
  829. tir |= CAN_TI0R_IDE;
  830. }
  831. else
  832. {
  833. tir = frame->id << 21;
  834. }
  835. tir |= CAN_TI0R_TXRQ | ((frame->rtr)?CAN_TI0R_RTR : 0);
  836. tx_mailbox->TIR = tir;
  837. return CAN_SUCCESS;
  838. }
  839. /*!
  840. * Checks if there's still space in output buffer
  841. *
  842. * \param dev Pointer to the device structure
  843. * \return 1 if space is available
  844. */
  845. int CanTxFree(NUTCANBUS *bus)
  846. {
  847. if (!bus->sig_tx_irq)
  848. /* companion can not transmitt */
  849. return 0;
  850. return (CANGetFreeMailbox(bus) >= 0)?1:0;
  851. }
  852. /*!
  853. * Reads a frame from input buffer
  854. *
  855. * This function reads a frame from the input buffer. If the input buffer
  856. * is empty the function will block unitl new frames are received,
  857. * or the timeout is reached.
  858. *
  859. * \param dev Pointer to the device structure
  860. * \param frame Pointer to the receive frame
  861. * \return 1 if timeout, 0 otherwise
  862. */
  863. int CanInput(NUTCANBUS *bus, CANFRAME * frame)
  864. {
  865. CANBUSINFO *ci = bus->bus_ci;
  866. __IO uint32_t *CANBBx = bus->bb_base;
  867. uint32_t __MAY_ALIAS *rdlr = (uint32_t*) &(frame->byte[0]);
  868. uint32_t __MAY_ALIAS *rdhr = (uint32_t*) &(frame->byte[4]);
  869. CANBUFFER *rxbuf = &(ci->can_RxBuf);
  870. CAN_FIFOMailBox_TypeDef *dataPtr ;
  871. while (rxbuf->datalength == 0)
  872. {
  873. if (NutEventWait(&ci->can_rx_rdy, ci->can_rx_timeout))
  874. return 1;
  875. }
  876. NutEnterCritical();
  877. dataPtr = &rxbuf->dataptr[rxbuf->dataindex];
  878. rxbuf->dataindex++;
  879. if (rxbuf->dataindex >= rxbuf->size)
  880. rxbuf->dataindex -= rxbuf->size;
  881. rxbuf->datalength--;
  882. NutExitCritical();
  883. /* Reenable interrupt*/
  884. if (bus->sig_tx_irq)
  885. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, IER, CAN_IER_FMPIE0);
  886. else
  887. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, IER, CAN_IER_FMPIE1);
  888. frame->rtr = (dataPtr->RIR & CAN_RI0R_RTR)?1:0;
  889. frame->id = dataPtr->RIR >>((dataPtr->RIR & CAN_RI0R_IDE)?3:21);
  890. if(frame->rtr)
  891. frame->id &= 0x3ff;
  892. frame->ext = (dataPtr->RIR & CAN_RI0R_IDE)?1:0;
  893. frame->rtr = (dataPtr->RIR & CAN_RI0R_RTR)?1:0;
  894. *rdlr = dataPtr->RDLR;
  895. *rdhr = dataPtr->RDHR;
  896. frame->len = dataPtr->RDTR & 0xf;
  897. return 0;
  898. }
  899. /*
  900. * Enable FIFO message pending interrupt and activate filters
  901. */
  902. void CanEnableRx(NUTCANBUS *bus)
  903. {
  904. __IO uint32_t *CANBBx = bus->bb_base;
  905. if(bus->sig_tx_irq)
  906. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, IER, CAN_IER_FMPIE0);
  907. else
  908. CM3BB_OFFSETSET(CANBBx, CAN_TypeDef, IER, CAN_IER_FMPIE1);
  909. CM3BB_OFFSETCLR(CANBBx, CAN_TypeDef, FMR, CAN_FMR_FINIT);
  910. }
  911. /*!
  912. * Write a frame from to output buffer
  913. *
  914. * This function writes a frame to the output buffer. If the output buffer
  915. * is full the function will block until frames are send.
  916. *
  917. * \param bus Pointer to the device structure
  918. * \param frame Pointer to the receive frame
  919. */
  920. int CanOutput(NUTCANBUS *bus, CANFRAME * frame)
  921. {
  922. int rc;
  923. CANBUSINFO *ci = bus->bus_ci;
  924. if (!bus->sig_tx_irq)
  925. /* companion can not send */
  926. return CAN_IS_COMPANION;
  927. while ((rc = StmCanSendMsg(bus, frame)) == CAN_TXBUF_FULL)
  928. {
  929. if (NutEventWait(&ci->can_rx_rdy, ci->can_tx_timeout))
  930. return 1;
  931. };
  932. ci->can_tx_frames++;
  933. return rc;
  934. }
  935. /*!
  936. * Report the counter values
  937. *
  938. * This function writes a frame to the output buffer. If the output buffer
  939. * is full the function will block until frames are send.
  940. *
  941. * \param bus Pointer to the device structure
  942. * \param index Number of pointer to receive
  943. *
  944. * \return -1 if counter not available, counter value otherwise
  945. */
  946. int CanGetCounter(NUTCANBUS *bus, enum CAN_COUNTERS index)
  947. {
  948. CANBUSINFO *ci = bus->bus_ci;
  949. switch (index)
  950. {
  951. case CAN_RX_FRAMES: return ci->can_rx_frames;
  952. case CAN_TX_FRAMES: return ci->can_tx_frames;
  953. case CAN_INTERRUPTS:
  954. return (ci->can_rx_interrupts +ci->can_tx_interrupts +ci->can_sce_interrupts);
  955. case CAN_RX_INTERRUPTS:
  956. return ci->can_rx_interrupts;
  957. case CAN_TX_INTERRUPTS:
  958. return ci->can_tx_interrupts;
  959. case CAN_SCE_INTERRUPTS:
  960. return ci->can_sce_interrupts;
  961. case CAN_OVERRUNS:
  962. return ci->can_overruns;
  963. case CAN_ERRORS:
  964. return ci->can_errors;
  965. default:
  966. return -1;
  967. }
  968. return -1;
  969. }