├── .github ├── FUNDING.yml └── workflows │ └── stale-issue-bot.yaml ├── COPYING ├── README.md ├── docs ├── API.md ├── Code_Overview.md ├── Features.md ├── Releases.md ├── Tools.md └── img │ ├── pico-wiring.jpg │ └── pulseview-canbus.png ├── example ├── CMakeLists.txt ├── canbuild.docker ├── canexample.c └── pico_sdk_import.cmake ├── pio ├── README.md ├── can2040.pio └── pioasm.docker ├── scripts ├── bitstuf.py └── crc.py └── src ├── can2040.c └── can2040.h /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: koconnor 2 | -------------------------------------------------------------------------------- /.github/workflows/stale-issue-bot.yaml: -------------------------------------------------------------------------------- 1 | # Close and warn on tickets that have become stale 2 | name: "Close stale tickets" 3 | on: 4 | schedule: 5 | - cron: '0 3 * * *' 6 | jobs: 7 | # Check for stale issues (no updates in 2 months) 8 | stale: 9 | if: github.repository == 'KevinOConnor/can2040' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/stale@v3 13 | with: 14 | stale-issue-message: | 15 | Hello, 16 | 17 | It looks like there hasn't been any recent updates on this 18 | github ticket. We prefer to only list tickets as "open" if 19 | they are actively being worked on. Feel free to provide an 20 | update on this ticket. Otherwise the ticket will be 21 | automatically closed in a few days. 22 | 23 | Best regards, 24 | 25 | ~ Your friendly GitIssueBot 26 | 27 | PS: I'm just an automated script, not a human being. 28 | 29 | stale-pr-message: | 30 | Hello, 31 | 32 | It looks like there hasn't been any recent updates on this 33 | github ticket. We prefer to only list tickets as "open" if 34 | they are actively being worked on. Feel free to provide an 35 | update on this ticket. Otherwise the ticket will be 36 | automatically closed in a few days. 37 | 38 | Best regards, 39 | 40 | ~ Your friendly GitIssueBot 41 | 42 | PS: I'm just an automated script, not a human being. 43 | 44 | exempt-issue-labels: 'enhancement,bug' 45 | days-before-stale: 60 46 | days-before-close: 7 47 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The can2040 project is a software CAN bus implementation for Raspberry 2 | Pi [rp2040](https://www.raspberrypi.com/products/rp2040/) and 3 | [rp2350](https://www.raspberrypi.com/products/rp2350/) 4 | micro-controllers. It enables these chips to implement 5 | [CAN bus](https://en.wikipedia.org/wiki/CAN_bus) using a standard CAN 6 | transceiver chip. The code supports reading and writing CAN 2.0B data 7 | frames at rates up to 1Mbit per second. 8 | 9 | For further information see: 10 | - [Features](docs/Features.md): Details about this software CAN bus 11 | implementation. 12 | - [API](docs/API.md): The can2040 programmer interface. 13 | - [Tools](docs/Tools.md): Useful testing and deployment tools. 14 | - [Code Overview](docs/Code_Overview.md): Information on can2040 15 | internals (for developers working on can2040 itself). 16 | - [Releases](docs/Releases.md): History of can2040 releases. 17 | -------------------------------------------------------------------------------- /docs/API.md: -------------------------------------------------------------------------------- 1 | This document describes how one may use can2040 in an application. 2 | 3 | Note that can2040 uses the GNU GPLv3 license. See the [COPYING 4 | file](../COPYING) for more information. 5 | 6 | # Compiling 7 | 8 | It is possible to use the standard 9 | [pico sdk](https://github.com/raspberrypi/pico-sdk.git) to build and 10 | deploy can2040 based applications. See the 11 | [example directory](../example/) for a demo application and its 12 | corresponding cmake rules. 13 | 14 | The can2040 code can also be used in environments that do not utilize 15 | the full pico sdk. The can2040 implementation is contained in the 16 | [can2040.c](../src/can2040.c) and [can2040.h](../src/can2040.h) C 17 | files. The can2040 code should be compiled using the "gcc" C 18 | compiler. The code is intended to be compiled at `-O2` (or higher) 19 | optimization. 20 | 21 | Even when not using the full sdk, the code will require a few files 22 | from the [pico sdk](https://github.com/raspberrypi/pico-sdk.git) that 23 | must be in the include path when compiling can2040 (sdk version 1.3.0 24 | or later is required). For example: 25 | `arm-none-eabi-gcc -O2 -I/path/to/sdk/src/rp2040/ ...` 26 | If compiling for the rp2350 then pico sdk version 2.0.0 or later is 27 | required and the compiler flags must include `-DPICO_RP2350`. 28 | 29 | # Startup 30 | 31 | The following provides example startup C code for can2040: 32 | 33 | ```c 34 | static struct can2040 cbus; 35 | 36 | static void 37 | can2040_cb(struct can2040 *cd, uint32_t notify, struct can2040_msg *msg) 38 | { 39 | // Add message processing code here... 40 | } 41 | 42 | static void 43 | PIOx_IRQHandler(void) 44 | { 45 | can2040_pio_irq_handler(&cbus); 46 | } 47 | 48 | void 49 | canbus_setup(void) 50 | { 51 | uint32_t pio_num = 0; 52 | uint32_t sys_clock = SYS_CLK_HZ, bitrate = 500000; 53 | uint32_t gpio_rx = 4, gpio_tx = 5; 54 | 55 | // Setup canbus 56 | can2040_setup(&cbus, pio_num); 57 | can2040_callback_config(&cbus, can2040_cb); 58 | 59 | // Enable irqs 60 | irq_set_exclusive_handler(PIO0_IRQ_0, PIOx_IRQHandler); 61 | irq_set_priority(PIO0_IRQ_0, 1); 62 | irq_set_enabled(PIO0_IRQ_0, 1); 63 | 64 | // Start canbus 65 | can2040_start(&cbus, sys_clock, bitrate, gpio_rx, gpio_tx); 66 | } 67 | ``` 68 | 69 | The `can2040.h` header file provides the definition of `struct 70 | can2040`. This definition is exported so that one may statically 71 | allocate an instance of it. (It is also valid to dynamically allocate 72 | it if desired.) The content of the `struct can2040` is considered 73 | "private" - callers should not inspect or modify its content for any 74 | reason. All interaction with can2040 is done via can2040 API 75 | functions. 76 | 77 | The can2040 code does not dynamically allocate memory; all storage is 78 | contained in the `struct can2040` that the caller allocates. 79 | 80 | # can2040_msg 81 | 82 | The `can2040.h` header file provides a definition for `struct 83 | can2040_msg`. This struct is used for transmitting and receiving CAN 84 | bus messages. 85 | 86 | The `id` field contains the CAN bus message id. It may also have the 87 | `CAN2040_ID_RTR` bit and/or `CAN2040_ID_EFF` bits set. The 88 | `CAN2040_ID_RTR` bit indicates that a "remote" frame should be used. 89 | The `CAN2040_ID_EFF` bit indicates that a 29-bit extended header 90 | should be used. 91 | 92 | The `dlc` field specifies the number of data bytes the CAN bus message 93 | contains. In accordance with the CAN bus specification, the value may 94 | be between 0 and 15, however there are at most 8 data bytes. (A dlc 95 | value between 8 to 15 will have 8 data bytes.) 96 | 97 | The `data` field contains the data bytes of the CAN bus message. 98 | 99 | # Function reference 100 | 101 | ## can2040_setup 102 | 103 | `void can2040_setup(struct can2040 *cd, uint32_t pio_num)` 104 | 105 | This function initializes the `struct can2040` passed in the `cd` 106 | parameter. The caller must either statically or dynamically allocate 107 | it prior to calling this function. 108 | 109 | The `pio_num` should be either `0` or `1` to use either the `PIO0` or 110 | `PIO1` hardware block. On the rp2350 the `pio_num` may be `2` for 111 | `PIO2`. 112 | 113 | ## can2040_callback_config 114 | 115 | `void can2040_callback_config(struct can2040 *cd, can2040_rx_cb rx_cb)` 116 | 117 | This function specifies the main can2040 callback (as specified in the 118 | `rx_cb` parameter). 119 | 120 | The `can2040_rx_cb` callback function will be invoked with each 121 | successfully received and transmitted message. It must be provided by 122 | the user code. 123 | 124 | The callback uses the function prototype: 125 | `void can2040_rx_cb(struct can2040 *cd, uint32_t notify, struct can2040_msg *msg)` 126 | 127 | The `cd` parameter of the callback contains the same pointer passed to 128 | `can2040_callback_config()`. 129 | 130 | The `notify` parameter of the callback contains one of 131 | `CAN2040_NOTIFY_RX`, `CAN2040_NOTIFY_TX`, `CAN2040_NOTIFY_ERROR`. 132 | * A `CAN2040_NOTIFY_RX` event indicates a message has been 133 | successfully read. The message contents will be in the `msg` 134 | parameter. 135 | * A `CAN2040_NOTIFY_TX` event indicates a message has been 136 | successfully transmitted on the CAN bus. The transmitted message 137 | contents will be in the `msg` parameter. 138 | * A `CAN2040_NOTIFY_ERROR` event indicates that the internal receive 139 | buffers have overflowed and that some number of CAN bus messages may 140 | have been lost. The `msg` parameter will point to an allocated but 141 | otherwise empty `struct can2040_msg` in this event. 142 | 143 | The callback is invoked in IRQ context (it is called from 144 | `can2040_pio_irq_handler()`). To keep irq latency low, it is 145 | recommended that the callback copy the given message to memory to be 146 | processed during normal (non-irq) context. 147 | 148 | The `msg` pointer is only valid during the duration of the callback. 149 | The callback code should copy any desired content from `msg` to its 150 | own storage during the callback. 151 | 152 | The callback is invoked for all valid received messages on the CAN 153 | bus. The can2040 code does not implement receive message filtering. 154 | It is expected that the caller will implement any desired filtering in 155 | their callback function. 156 | 157 | ## can2040_start 158 | 159 | `void can2040_start(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate, uint32_t gpio_rx, uint32_t gpio_tx)` 160 | 161 | This function starts the main can2040 CAN bus implementation. The 162 | provided GPIO pins will be configured and associated with the 163 | rp2040/rp2350 PIO hardware block. 164 | 165 | The `sys_clock` parameter specifies the system clock rate (for example 166 | `125000000` for an rp2040/rp2350 ARM core running at 125Mhz). 167 | 168 | The `bitrate` parameter specifies the CAN bus speed (for example 169 | `500000` for a 500Kbit/s CAN bus). 170 | 171 | The `gpio_rx` parameter specifies the gpio number that is routed to 172 | the "CAN RX" pin of the CAN bus transceiver. On rp2040 it should be 173 | between 0 and 29 (for GPIO0 to GPIO29). On the rp2350 chips it may be 174 | between 0 and 31 (for GPIO0 to GPIO31), or alternatively between 16 175 | and 47 (for GPIO16 to GPIO47) if both `gpio_rx` and `gpio_tx` are 176 | between 16 and 47. 177 | 178 | The `gpio_tx` parameter specifies the gpio number that is routed to 179 | the "CAN TX" pin of the CAN bus transceiver. On rp2040 chips it 180 | should be between 0 and 29 (for GPIO0 to GPIO29). On the rp2350 chips 181 | it may be between 0 and 31 (for GPIO0 to GPIO31), or alternatively 182 | between 16 and 47 (for GPIO16 to GPIO47) if both `gpio_rx` and 183 | `gpio_tx` are between 16 and 47. 184 | 185 | After calling this function, activity on the CAN bus may result in the 186 | user specified `can2040_rx_cb` callback being invoked. 187 | 188 | ## can2040_pio_irq_handler 189 | 190 | `void can2040_pio_irq_handler(struct can2040 *cd)` 191 | 192 | This function should be invoked on each PIO hardware IRQ event. The 193 | caller should define the underlying IRQ handler function, enable it, 194 | and arrange to call `can2040_pio_irq_handler()` with each event. The 195 | can2040 code uses the first IRQ of each PIO block (`PIO0_IRQ_0_IRQn` 196 | for PIO0, or `PIO1_IRQ_0_IRQn` for PIO1). 197 | 198 | This function is intended to be invoked from IRQ context. It is 199 | reentrant safe with respect to other can2040 function calls made on 200 | the same ARM core. 201 | 202 | ## can2040_transmit 203 | 204 | `int can2040_transmit(struct can2040 *cd, struct can2040_msg *msg)` 205 | 206 | This function schedules a message for transmission on the CAN bus. 207 | The `msg` parameter should contain a pointer to the `struct 208 | can2040_msg` that should be sent. The function returns `0` if the 209 | message is successfully queued, or a negative number if there is no 210 | space for the message in the internal queue. If scheduled, the 211 | contents of the `msg` pointer are copied to internal storage during 212 | the `can2040_transmit()` call. 213 | 214 | When a scheduled message is successfully transmitted on the CAN bus 215 | the user supplied `can2040_rx_cb` callback will be invoked with a 216 | `CAN2040_NOTIFY_TX` event. 217 | 218 | The can2040 code may buffer up to four messages for transmission. If 219 | multiple messages are buffered then they are transmitted in "first in 220 | first out" order. (The buffered transmit messages are not reordered 221 | by message id priority.) 222 | 223 | It is valid to invoke `can2040_transmit()` from the user supplied 224 | `can2040_rx_cb` callback function, however doing so is not 225 | recommended. The `can2040_transmit()` function has processing 226 | overhead (it performs CRC calculation and bitstuffing on the message) 227 | and calling it from IRQ context may increase irq latency. 228 | 229 | It is valid to invoke `can2040_transmit()` on one ARM core while the 230 | other ARM core may be running `can2040_pio_irq_handler()`. 231 | 232 | ## can2040_check_transmit 233 | 234 | `int can2040_check_transmit(struct can2040 *cd)` 235 | 236 | This function may be called to determine if there is space available 237 | to schedule a message transmission. That is, it may be used to 238 | determine if a call to `can2040_transmit()` will succeed. 239 | 240 | It is valid to invoke `can2040_check_transmit()` from the user 241 | supplied `can2040_rx_cb` callback function. 242 | 243 | It is valid to invoke `can2040_check_transmit()` on one ARM core while 244 | the other ARM core may be running `can2040_pio_irq_handler()`. 245 | 246 | ## can2040_stop 247 | 248 | `void can2040_stop(struct can2040 *cd)` 249 | 250 | This function disables processing of can2040 CAN bus messages. Upon 251 | completion of this function the user supplied `can2040_rx_cb()` 252 | callback function will no longer be invoked. 253 | 254 | If this function is called while a message is queued for transmit then 255 | it is possible that the message may be successfully transmitted 256 | without it being removed from the local transmit queue and without a 257 | `CAN2040_NOTIFY_TX` event sent to the user supplied `can2040_rx_cb()` 258 | callback function. 259 | 260 | The can2040 CAN bus processing may be restarted by calling 261 | `can2040_start()`. 262 | 263 | To clear the transmit queue before restarting, call `can2040_setup()`, 264 | `can2040_callback_config()`, and then `can2040_start()`. 265 | 266 | ## can2040_get_statistics 267 | 268 | `void can2040_get_statistics(struct can2040 *cd, struct can2040_stats *stats)` 269 | 270 | This function may be called to obtain can2040 receive and transmit 271 | statistics. This may be useful for insight on how well the CAN bus 272 | network hardware is performing. 273 | 274 | The caller must allocate a `struct can2040_stats` and pass a pointer 275 | to it in the `stats` parameter. The `can2040_get_statistics()` 276 | function will copy its internal can2040 statistics to the provided 277 | struct. The caller may then inspect its local copy of `struct 278 | can2040_stats` after the function completes. 279 | 280 | The `can2040.h` header file provides the definition for `struct 281 | can2040_stats`. It has the following fields: 282 | * `rx_total`: The total number of successfully received messages. 283 | This is the number of times that `can2040_rx_cb()` is invoked with 284 | `CAN2040_NOTIFY_RX`. 285 | * `tx_total`: The total number of successfully transmitted messages. 286 | This is the number of times that `can2040_rx_cb()` is invoked with 287 | `CAN2040_NOTIFY_TX`. 288 | * `tx_attempt`: The total number of transmit attempts. If this is 289 | more than one greater than `tx_total` it indicates some transmits 290 | were retried. A transmit may be retried due to line arbitration (a 291 | transmit attempt was interrupted by a higher priority transmission 292 | from another node on the CAN bus), due to the lack of an 293 | acknowledgment from another node on the CAN bus, or due to some 294 | other parse error during a transmit attempt. 295 | * `parse_error`: The total number of data errors observed during 296 | content parsing on the CAN bus. This may increment due to hardware 297 | noise on the CAN bus, due to error frames generated from other nodes 298 | on the CAN bus, due to lack of transmit acknowledgments on the CAN 299 | bus, or due to some other error in read data. 300 | 301 | The above counters are only set to zero during the initial call to 302 | `can2040_setup()`. One may call `can2040_get_statistics()` 303 | periodically and subtract each counter from the value found at the 304 | previous call to obtain the statistics over that discrete period. 305 | When subtracting, it is recommended to store the difference in a 306 | `uint32_t` for improved handling of 32bit counter rollovers. 307 | 308 | It is valid to invoke `can2040_get_statistics()` at any time after 309 | `can2040_setup()` is called (including from another ARM core and 310 | including from the user supplied `can2040_rx_cb` callback function). 311 | 312 | # Not reentrant safe 313 | 314 | Unless explicitly stated otherwise, the can2040 code is not reentrant 315 | safe. For example, unless stated otherwise, one may not invoke 316 | can2040 functions from IRQ context (where they might preempt a can2040 317 | function running in another context), one may not invoke can2040 318 | functions from multiple ARM cores (such that two can2040 functions 319 | could be running simultaneously), nor invoke can2040 functions from 320 | the user supplied `can2040_rx_cb` callback function. 321 | 322 | # Multiple can2040 instances 323 | 324 | Each instance of can2040 uses one of the PIO hardware blocks on the 325 | rp2040/rp2350. If there are separate CAN transceivers (and separate 326 | sets of CAN rx and CAN tx gpio pins) then one may create multiple 327 | simultaneous instances of can2040. 328 | 329 | To use this functionality, the [startup code](#startup) should be run 330 | multiple times, each with their own separate instance of a `struct 331 | can2040`. 332 | 333 | In this case, the multiple instances of can2040 do not share state. 334 | Therefore, no particular synchronization is needed between instances. 335 | That is, one must ensure each instance is not reentrant with respect 336 | to itself, but it is not required to synchronize between instances. 337 | One may run multiple can2040 instances on the same ARM core or 338 | different ARM cores. 339 | 340 | # Low interrupt latency 341 | 342 | The can2040 implementation requires low interrupt response time for 343 | proper operation. See the 344 | [Features Document](Features.md#software-utilization) 345 | for more information on the impact of latency to can2040. 346 | 347 | To ensure low-latency it is recommended to limit the amount of code 348 | that runs at a higher interrupt priority than can2040. Higher 349 | priority code would be any code that disables interrupts and any 350 | interrupt handling code that is registered with a higher priority (a 351 | lower or equal value passed to `irq_set_priority()` or 352 | `NVIC_SetPriority()`). 353 | 354 | Also consider loading the can2040 code (and any code that runs at a 355 | higher priority) into memory on the rp2040/rp2350 chip. An rp2040 356 | running at 125Mhz will take a minimum of 320ns for each 32bit load 357 | from flash. Thus, even a handful of flash accesses (to load 358 | instructions or data) may cause a delay sufficient to impact can2040. 359 | Be sure to also load the can2040 callback function into ram. Consider 360 | also loading the ARM core interrupt vector table into ram (if it is 361 | not already in ram). 362 | 363 | If building with the Pico SDK then it may be possible to load the 364 | entire application into ram by adding `-DPICO_COPY_TO_RAM` to the 365 | cmake flags (or by using something like 366 | `pico_set_binary_type(my_executable copy_to_ram)` in the cmake files). 367 | 368 | It is also possible to load just the can2040 code into ram. The 369 | specifics of doing that are beyond the scope of this document, but at 370 | a high-level it typically involves locating the build "linker script" 371 | and adding `can2040.o(.text*)` and `can2040.o(.rodata*)` to the ram 372 | segment. 373 | 374 | # Using can2040 from C++ 375 | 376 | The can2040 code is intended to be compiled with gcc. If can2040.c is 377 | compiled with a C compiler and linked with a C++ application then be 378 | careful to always import the `can2040.h` header file into C++ code in 379 | "C" mode - for example: 380 | 381 | ```c 382 | extern "C" { 383 | #include "can2040.h" 384 | } 385 | ``` 386 | -------------------------------------------------------------------------------- /docs/Code_Overview.md: -------------------------------------------------------------------------------- 1 | This document is intended for developers interested in understanding 2 | the can2040 implementation itself. It provides some high-level 3 | information on the can2040 code organization and objectives. 4 | 5 | # PIO state machines 6 | 7 | The can2040 code uses the rp2040/rp2350 PIO (Programmable Input 8 | Output) hardware feature. See the [rp2040 9 | datasheet](https://www.raspberrypi.com/documentation/microcontrollers/rp2040.html) 10 | for information on the hardware. 11 | 12 | The PIO instructions used by can2040 are contained in the can2040.c 13 | code. However, a version of the PIO instructions with additional 14 | comments and other reference information can be found in the 15 | [can2040.pio](../pio/can2040.pio) file. 16 | 17 | The rp2040 chip contains two PIO hardware blocks and each PIO hardware 18 | block contains four PIO state machines. The can2040 code uses one PIO 19 | block and uses all four state machines of that block. 20 | 21 | ## PIO "sync" state machine 22 | 23 | The main task of the PIO "sync" state machine is to synchronize bit 24 | sampling to the incoming data. This enables communication between CAN 25 | bus nodes that have a slightly different clock rate. That is, the 26 | sampling time for each transmitted bit is adjusted to account for a 27 | slightly faster or slower bitrate of the transmitter. The PIO "sync" 28 | state machine raises a "sample" irq (pio irq 4) at each sampling point 29 | and other state machines read the "CAN rx" line after receiving that 30 | signal. 31 | 32 | A secondary task of the PIO "sync" state machine is to detect when a 33 | new transmission may start. It will raise a "maytx" irq (pio irq 0) 34 | after 11 passive bits are detected (in some cases, based on settings 35 | from the ARM core, this may instead be after 17 passive bits). The 36 | "maytx" irq will also be raised if another transmitter starts a 37 | transmission after 10 passive bits. This ensures a local message 38 | transmission can participate in line arbitration and that these bit 39 | transmissions are synchronized. 40 | 41 | A third task of the PIO "sync" state machine is to disable PIO 42 | "sample" irqs when the CAN bus is idle (after ten passive bits are 43 | detected) and to resume "sample" irqs upon the start of the next 44 | message. This reduces ARM core processing overhead. 45 | 46 | ## PIO "rx" state machine 47 | 48 | The main task of the PIO "rx" state machine is to relay bits on the 49 | CAN bus to the ARM processing core. The state machine reads bits from 50 | the "CAN rx" line after each "sample" irq and accumulates the data in 51 | the rx fifo. After every 10 raw input bits the ARM core is notified 52 | of the pending data. 53 | 54 | ## PIO "match" state machine 55 | 56 | The main task of the PIO "match" state machine is to detect an 57 | anticipated CRC bit sequence and to generate a "matched" signal (PIO 58 | irq 2). This mechanism is used to transmit an ack bit (a single 59 | dominant bit) at the appropriate point in a received message so as to 60 | acknowledge that message. 61 | 62 | The "match" state machine tracks the last 21 raw bits (as read from 63 | the "CAN rx" line after each "sample" irq) along with the total number 64 | of bits that have been read since the PIO hardware block was started 65 | (stored as an 11 bit integer). The ARM core can send a 32 bit 66 | "match_key" to the PIO containing this combination of raw bits and bit 67 | position. A "matched" irq is raised when both the sampled raw bits 68 | and counter match the requested match_key. 69 | 70 | A secondary task of the PIO "match" state machine is to provide 71 | "matched" signals to the main ARM core for timely notification of 72 | message completion. The same "match_key" mechanism described above is 73 | used. 74 | 75 | ## PIO "tx" state machine 76 | 77 | The main task of the PIO "tx" state machine is to transmit messages on 78 | the "CAN tx" line. For each bit to be transmitted, the state machine 79 | sets the tx line, reads the "CAN rx" line, and will stop a 80 | transmission if a dominant/passive bit conflict is found. This 81 | enables transmissions to properly participate in CAN bus line 82 | arbitration. To transmit a message, the ARM core fills the tx fifo 83 | with the raw bits of the message and arranges for the "tx" state 84 | machine to start after a "maytx" irq. The "tx" state machine performs 85 | its own bit time synchronization to resynchronize bit timing to other 86 | simultaneous transmitters that may be transmitting at a slightly 87 | faster bit rate. 88 | 89 | A secondary task of the PIO "tx" state machine is to inject an ack bit 90 | to acknowledge messages received from other CAN bus nodes. To perform 91 | this task, the ARM core fills the tx fifo with a single dominant bit 92 | and arranges for the "tx" state machine to start after a "matched" 93 | irq. After the ack bit is transmitted the PIO "tx" state machine will 94 | raise an "ackdone" signal (PIO irq 3). 95 | 96 | # ARM core state tracking 97 | 98 | The ARM core C code must process the raw bits read from the PIO and 99 | arrange for timely signals to be sent to the PIO. In effect, the PIO 100 | could be thought of as a separate processor with four running threads. 101 | Unfortunately, due to limitations in the PIO's ability to track state, 102 | the ARM C code has a high burden to ensure proper synchronization. 103 | 104 | To facilitate this state tracking, the C code maintains three state 105 | tracking variables: `parse_state`, `report_state`, and `tx_state`. 106 | 107 | ## Parse state 108 | 109 | The `parse_state` variable tracks the current message position (eg, 110 | header, data, trailer) as data is read from the "rx" state machine 111 | fifo. When the "rx" state machine fills an rx fifo the ARM core is 112 | alerted and the ARM PIO irq handler will read that data. The raw bits 113 | are then checked for bit stuffing and the resulting unstuffed data is 114 | accumulated to assemble the incoming message. 115 | 116 | The [CAN bus wikipedia article](https://en.wikipedia.org/wiki/CAN_bus) 117 | is a useful reference for the parts of a CAN bus message and the 118 | corresponding `parse_state` states that are tracked. 119 | 120 | Each rx fifo entry is filled after every ten raw bits of data. The 121 | bits in each fifo entry will not be aligned to message boundaries (a 122 | message start-of-header bit could occur in any of the ten bits in a 123 | fifo entry). Updates to `parse_state` tracking will typically lag the 124 | actual raw bitstream seen by the PIO by a minimum of five bits, but 125 | could be much larger due to ARM core "irq latency". Also, the "sync" 126 | state machine disables "sample" irqs after ten passive bits, which 127 | could result in up to nine bits of a message not being observed by the 128 | `parse_state` tracking until the start of the next message (a 129 | potentially significant delay). The `report_state` tracker is used to 130 | account for these timing limitations. 131 | 132 | ## Report state 133 | 134 | The `report_state` tracking combines information from the rx fifo (as 135 | tracked by `parse_state`) along with direct PIO irq signals to provide 136 | more timely handling of incoming messages. 137 | 138 | The `report_state` handling has notable complexity due to its need to 139 | handle several asynchronous events - for example, the rx fifo may be 140 | one or more entries behind the PIO state, ARM core irq latency may 141 | delay observation of a PIO irq until after the PIO state has changed, 142 | a PIO irq may be observed before or after the corresponding bits are 143 | observed from the rx fifo, a scheduled PIO irq may not be scheduled in 144 | time to observe the event and thus never be received, etc. . 145 | Unfortunately, due to limitations in the PIO's ability to perform 146 | state tracking, handling this state tracking complexity in the ARM 147 | core seems to be necessary. 148 | 149 | There are five states that `report_state` may be in: `RS_IDLE`, 150 | `RS_NEED_RX_ACK`, `RS_NEED_RX_EOF`, `RS_NEED_TX_ACK`, and 151 | `RS_NEED_TX_EOF`. 152 | 153 | The main goal of the `report_state` tracking is to "look ahead" of the 154 | current message state found in `parse_state` to detect successful ack 155 | and eof states as soon as they are observed by the PIO. This allows 156 | the can2040 code to more quickly report messages to the user code. 157 | This code also arranges for the PIO to generate timely ack bits for 158 | incoming messages and to timely queue outgoing messages in the PIO so 159 | that they are available for line arbitration. 160 | 161 | ## Transmit state 162 | 163 | The `tx_state` variable tracks the current state of messages queued 164 | for transmission in the PIO "tx" state machine. It is used to 165 | determine if a message needs to be re-queued (for example, if a 166 | previous transmit attempt was preempted by a higher priority message). 167 | It is also used to determine if the current incoming message (as 168 | tracked by `parse_state`) is actually feedback from a locally 169 | transmitted message. 170 | -------------------------------------------------------------------------------- /docs/Features.md: -------------------------------------------------------------------------------- 1 | This document describes features and limitations of the can2040 CAN 2 | bus implementation. 3 | 4 | # Main features 5 | 6 | * Support for sending and receiving CAN 2.0B data frames. Support for 7 | both standard headers (11-bit ids) and extended headers (29-bit 8 | ids). 9 | 10 | * Support for bus speeds up to 1Mbit/s. 11 | 12 | * Interoperates with other CAN bus implementations. A bus may consist 13 | of one or more can2040 nodes along with non-can2040 nodes. 14 | 15 | * The implementation uses one rp2040/rp2350 PIO hardware block. A 16 | single rp2040 chip may have two separate CAN bus interfaces by using 17 | both of its PIO blocks. A single rp2350 chip may have three 18 | separate CAN bus interfaces. 19 | 20 | * Works with standard CAN bus transceivers. On the rp2040, any two 21 | gpio pins may be used for the "can rx" and "can tx" wires. On the 22 | rp2350, any two gpio pins from GPIO0 to GPIO31 or any two pins from 23 | GPIO16 to GPIO47 may be used. 24 | 25 | # Protocol details 26 | 27 | This section provides some low-level details on can2040's 28 | implementation of the CAN bus protocol. This section is targeted at 29 | CAN bus experts interested in implementation details. 30 | 31 | * Supports clock synchronization for bit timing. That is, the 32 | sampling time is resynchronized on each passive to dominant bit 33 | transition. 34 | 35 | * Supports verification of SOF (start-of-frame), header, data, CRC, 36 | ack, and EOF (end-of-frame) portions of each frame on the CAN bus. 37 | 38 | * Will inject an ack bit after verification of message CRC when 39 | receiving a message. 40 | 41 | * Transmissions will perform "line arbitration". That is, lower 42 | priority transmissions (as based on message id) will yield the bus 43 | to higher priority messages. In addition, the start of 44 | transmissions will be aligned to the SOF bit of other transmitters 45 | for proper bit timing during line arbitration. 46 | 47 | * Support for automatic retransmissions. If a transmission does not 48 | complete successfully (for example, due to an error, lack of 49 | acknowledgment, or interrupted by a higher priority message) then 50 | it will be automatically retransmitted at the next opportunity. 51 | 52 | * Supports sending and receiving "remote frames". 53 | 54 | * Support for receiving "overload frames" (they will successfully 55 | delay transmission of messages). The can2040 code does not transmit 56 | "overload frames". 57 | 58 | * Support for receiving "error frames" (they will halt an active 59 | transmission). However, can2040 does not transmit "error frames". 60 | 61 | There are some known limitations with CAN bus error handling: 62 | 63 | * The CAN bus specification defines three error handling states: 64 | "error active" (ie, normal state), "error passive", and "bus off". 65 | Automatic transition between these states is not implemented. The 66 | can2040 code does not transmit "error frames". The can2040 code 67 | will not automatically enter a "bus off" state. In this regard, the 68 | can2040 code may be thought of as always being in the "error 69 | passive" state. 70 | 71 | # Software utilization 72 | 73 | The can2040 system is a software CAN bus implementation. It utilizes 74 | the rp2040/rp2350 PIO device as well as processing time on one of the 75 | rp2040/rp2350 ARM cores. 76 | 77 | One may dedicate an ARM core to can2040. It is also possible for 78 | can2040 to share an ARM core with application code. This section is 79 | targeted at software developers interested in understanding the 80 | software overhead of can2040 when sharing an ARM core. 81 | 82 | * The ARM core processing time is dependent on the amount of bus 83 | traffic, even if that bus traffic is not intended for the node. It 84 | is expected that a fully saturated CAN bus at the fastest supported 85 | rate of 1Mbit/s may use up to ~25% of one of the two rp2040 ARM 86 | cores (when the ARM core is running at 125Mhz). The same rate on an 87 | rp2350 is expected to use up to ~15% of one ARM core (when running 88 | at 150Mhz). A slower CAN bus speed would have a lower worst case 89 | processing time (for example, a bus speed of 500kbit/s is expected 90 | to have half the worst case processing time of a 1Mbit/s bus). A 91 | CAN bus that is idle does not consume any ARM core processing time. 92 | 93 | * The can2040 code requires low ARM core "irq latency" for proper 94 | functionality. If an ARM core is shared with both application code 95 | and can2040, and that application code disables irqs, has high 96 | priority irqs that preempt the can2040 irq handler, or takes similar 97 | actions that increase irq latency then it may impact can2040. 98 | 99 | It is desirable to keep application irq latency low. The following 100 | paragraphs provide some guidance on what may happen if irq latency 101 | exceeds certain thresholds. The "bit time" refers to the amount of 102 | time it takes to transmit one bit on the CAN bus. It is dependent 103 | on the CAN bus speed (for example, a bus frequency of 500000 would 104 | have a bit time of 2 microseconds). 105 | 106 | Above ~3 bit times of irq latency: After successfully transmitting a 107 | message, the can2040 code may not have sufficient time to schedule 108 | the next transmission before another node starts a transmission of 109 | lower priority. As a result, back-to-back high-priority transmits 110 | may be delayed access to a highly contended bus. That is, even if 111 | the node has many high-priority messages it may only get access to 112 | the bus on every other message. 113 | 114 | Above ~7 bit times: The code may not have sufficient time to 115 | schedule an acknowledgment for a received message, and/or the code 116 | may not have sufficient time to schedule a high-priority 117 | transmission before another node starts a transmission of lower 118 | priority. This may result in message retransmissions and it may 119 | result in a high-priority message from the node being delayed during 120 | periods of high bus contention. 121 | 122 | Above ~80 bit times: The code may not have sufficient time to read 123 | all bytes before the "PIO FIFO queue" overflows. As a result, 124 | received messages on the CAN bus sent to the node may be permanently 125 | lost and messages transmitted from the node may be transmitted 126 | multiple times. 127 | 128 | The can2040 irq handler itself may introduce some irq latency (to 129 | itself and other irq handlers of equal or lower priority). With an 130 | ARM core running at 125Mhz, it is expected that each can2040 irq 131 | will typically take between 1 to 3 microseconds. (An rp2040/rp2350 132 | instruction flash cache miss and/or higher priority irqs may 133 | increase this time.) 134 | -------------------------------------------------------------------------------- /docs/Releases.md: -------------------------------------------------------------------------------- 1 | History of can2040 releases. 2 | 3 | # v1.7.0 4 | 5 | Available on 20250102. Major features in this release: 6 | * Support for rp2350 chips. The can2040 code can now run on either 7 | rp2040 chips or rp2350 chips. 8 | * Support for v2.0.0 of the pico-sdk. 9 | 10 | # v1.6.0 11 | 12 | Available on 20231001. Major features in this release: 13 | * Added a new `can2040_stop()` API function. This function can be used 14 | to either temporary pause or permanently halt the processing of CAN 15 | bus messages. It is effectively the inverse of the existing 16 | `can2040_start()` function. 17 | * Added a new `can2040_get_statistics()` API function. This can be 18 | used to monitor the low-level performance of the CAN bus interface. 19 | In particular it can monitor the number of can2040 parse errors and 20 | retransmit attempts. 21 | 22 | # v1.5.0 23 | 24 | Available on 20230520. Major features in this release: 25 | * Message transmit bit timing will now only synchronize to faster 26 | transmitters (as is recommended by the CAN bus specification). This 27 | avoids poor transmit timing due to delays between CAN Tx and CAN Rx 28 | signals. 29 | * Improved multi-core support in `can2040_transmit()`. This function 30 | can now be called on one core while the other core may be running 31 | `can2040_pio_irq_handler()`. 32 | * Fixed a possible "transmit hang" that could occur if a transmit 33 | fails due to reception of an error frame. 34 | 35 | # v1.4.0 36 | 37 | Available on 20221121. Major features in this release: 38 | * Reduce scheduling latency of new transmit requests that occur while 39 | parsing the end of an incoming message. 40 | * Reduce ARM core processing load by reading 10 bits at a time from 41 | the PIO. 42 | * Fixed message retransmit handling when no other node on the bus is 43 | transmitting. 44 | * Fixed selection of PIO1 hardware block. 45 | * Assorted documentation and internal code cleanups. 46 | 47 | The v1.4.0 release was retroactively tagged on 20230313. 48 | 49 | ## v1.4.1 50 | 51 | Available on 20230314. This is a bug fix only release: 52 | * Fixed error that could cause a "duplicate ack" to be generated in 53 | rare situations. 54 | 55 | # v1.3.0 56 | 57 | Available on 20220725. Major features in this release: 58 | * Reduce scheduling latency for transmissions immediately after 59 | receiving a message. 60 | * Assorted documentation and internal code cleanups. 61 | 62 | The v1.3.0 release was retroactively tagged on 20230313. 63 | 64 | # v0.2.0 65 | 66 | Available on 20220630. Major features in this release: 67 | * Initial API and user documentation. 68 | * Support "extended" and "remote" frames. 69 | * Increase PIO frequency to improve receive message sample timing. 70 | * No need to require DMA hardware. This simplifies the user-facing API. 71 | * Improved handling of invalid data found during message parsing. 72 | * Assorted ARM CPU processing optimizations. 73 | * Assorted internal code cleanups. 74 | 75 | The v0.2.0 release was retroactively tagged on 20230313. 76 | 77 | # v0.1.0 78 | 79 | Available on 20220602. Major features in this release: 80 | * Initial code release. 81 | * Basic support for sending and receiving CAN 2.0B data frames. 82 | 83 | The v0.1.0 release was retroactively tagged on 20230313. 84 | -------------------------------------------------------------------------------- /docs/Tools.md: -------------------------------------------------------------------------------- 1 | This document describes some available tools that may be useful for 2 | testing and debugging the can2040 code. These tools may also 3 | facilitate development and may be useful as coding examples. 4 | 5 | # Klipper 6 | 7 | The [Klipper](https://www.klipper3d.org/) code utilizes can2040 for 8 | micro-controller CAN bus communication on rp2040/rp2350 chips. 9 | 10 | Klipper can also be compiled in a [USB to CAN bus bridge 11 | mode](https://www.klipper3d.org/CANBUS.html#usb-to-can-bus-bridge-mode) 12 | so that an rp2040/rp2350 device appears as a standard Linux USB to CAN 13 | bus adapter (using the "gs_usb" Linux driver). Compiling the Klipper 14 | micro-controller code in this mode may be useful for CAN bus 15 | diagnostics even when not using Klipper. See the [Klipper 16 | installation](https://www.klipper3d.org/Installation.html) 17 | instructions for the full installation instructions. Briefly, on a 18 | Raspberry Pi computer the installation involves: 19 | 1. Download the Klipper code 20 | (`git clone https://github.com/Klipper3d/klipper`). 21 | 2. Install compiler tools 22 | (`sudo apt-get update && sudo apt-get install build-essential libncurses-dev libusb-dev libnewlib-arm-none-eabi gcc-arm-none-eabi binutils-arm-none-eabi libusb-1.0 pkg-config`). 23 | 3. Configure the micro-controller software (`make menuconfig`). 24 | Select "Enable extra low-level configuration options", select 25 | "Raspberry Pi RP2040/RP235x" as the micro-controller, select "No 26 | bootloader", select "USB to CAN bus bridge", set the appropriate 27 | gpio pins for CAN RX and CAN TX, and set the desired CAN bus 28 | frequency. 29 | 4. Build the micro-controller software (`make`). 30 | 5. Place the rp2040/rp2350 micro-controller in bootloader mode and 31 | flash the software (`make flash FLASH_DEVICE=2e8a:0003`). 32 | 33 | Once the Klipper micro-controller code is running on the rp2040/rp2350 34 | it is possible to use the Linux 35 | [can-utils](https://github.com/linux-can/can-utils) tools. Briefly: 36 | 1. Install the can-utils package 37 | (`sudo apt-get update && sudo apt-get install can-utils`). 38 | 2. Bring up the "can0" Linux interface 39 | (eg, `sudo ip link set can0 up type can bitrate 1000000`). Note 40 | that Klipper currently uses the CAN bus frequency set during "make 41 | menuconfig" and the value set in Linux is ignored. 42 | 3. In one window run the candump utility to show all packets read by 43 | the interface (eg, `candump -t z -Ddex can0,#FFFFFFFF`). 44 | 4. In another window, send packets on the CAN bus 45 | (eg, `cansend can0 123#121212121212`). 46 | 47 | # Katapult 48 | 49 | The [Katapult](https://github.com/Arksine/Katapult) code implements a 50 | cross-platform bootloader that supports flashing an rp2040 51 | micro-controller over CAN bus. It utilizes can2040 on rp2040 chips. 52 | 53 | # Testing CAN bus 54 | 55 | Note that can2040 (and CAN bus in general) requires a functional 56 | hardware bus for proper message generation. At a minimum, can2040 57 | requires a functioning transceiver, functioning "CAN H" and "CAN L" 58 | wiring, two 120 Ohm resistors on that wiring, at least one additional 59 | CAN bus enabled chip with its own transceiver, and all chips much be 60 | configured with the same CAN bus frequency. If any of the above 61 | hardware is missing or not properly connected/configured then the bus 62 | will not function correctly; not even for debugging purposes. 63 | 64 | # Testing with Raspberry Pi Pico board 65 | 66 | It is possible to use a Raspberry Pi Pico board with a CAN bus 67 | transceiver board for testing. The following picture shows an example 68 | wiring with a "Waveshare SN65HVD230 CAN Board": 69 | 70 | ![pico-wiring](img/pico-wiring.jpg) 71 | 72 | In the above picture, 3.3V on the transceiver board is wired to 3.3V 73 | on the Pico, GND is wired to GND, CAN Rx is wired to GPIO4, and CAN Tx 74 | is wired to GPIO5. (Note that the "Waveshare SN65HVD230 CAN Board" 75 | has a builtin 120 Ohm resistor between the CANH and CANL wires which 76 | is not easy to remove.) 77 | 78 | # Sigrok logic analyzer 79 | 80 | The [Sigrok Pulseview](https://sigrok.org/wiki/PulseView) software 81 | along with a low-cost logic analyzer can be useful for diagnosing CAN 82 | bus signaling. 83 | 84 | One can often find "USB logic analyzers" for under $15 (US pricing as 85 | of 2023). These devices are often listed as "Saleae logic clones" or 86 | as "24MHz 8 channel USB logic analyzers". 87 | 88 | ![pulseview-canbus](img/pulseview-canbus.png) 89 | 90 | The above picture was taken while using pulseview with a "Saleae 91 | clone" logic analyzer. The Sigrok and pulseview software was 92 | installed on a desktop machine (also install the "fx2lafw" firmware if 93 | that is packaged separately). The CH0 pin on the logic analyzer was 94 | routed to the rp2040 CAN Rx line, the CH1 pin was wired to the CAN Tx 95 | pin, and GND was wired to GND. Pulseview was configured to only 96 | display the D0 and D1 lines (red "probe" icon center top toolbar). 97 | The number of samples was set to 5 million (top toolbar) and the 98 | sample rate was set to 24Mhz (top toolbar). The CAN decoder was added 99 | (yellow and green "bubble icon" right top toolbar). The D0 channel 100 | was labeled as RX and set to trigger on a falling edge (click on black 101 | D0 label at left). The D1 channel was labeled as TX (click on brown 102 | D1 label at left). The CAN decoder was configured for 1Mbit rate 103 | (click on green CAN label at left). The CAN decoder was moved to the 104 | top of the display (click and drag green CAN label). Finally, the 105 | capture was started (click "Run" at top left) and a packet was 106 | transmitted on the CAN bus (`cansend can0 123#121212121212`). 107 | 108 | The logic analyzer can provide an independent tool for capturing 109 | packets and verifying bit timing. 110 | -------------------------------------------------------------------------------- /docs/img/pico-wiring.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinOConnor/can2040/bcfadf84bf248f662b20676494df7757cfc55cb0/docs/img/pico-wiring.jpg -------------------------------------------------------------------------------- /docs/img/pulseview-canbus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinOConnor/can2040/bcfadf84bf248f662b20676494df7757cfc55cb0/docs/img/pulseview-canbus.png -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Demo cmake rules for the can2040 example using Pico SDK 2 | # 3 | # This is a minimal set of build rules. See the PICO SDK 4 | # documentation for more information. In brief, from a Unix 5 | # command-line one would issue commands similar to: 6 | # mkdir build 7 | # cd build 8 | # cmake -D PICO_BOARD=pico .. 9 | # make 10 | # Then flash the resulting canexample.uf2 to the target board. 11 | 12 | cmake_minimum_required(VERSION 3.13) 13 | 14 | # Download SDK from git (or "cmake -D PICO_SDK_PATH=/some/path ..." to avoid) 15 | set(PICO_SDK_FETCH_FROM_GIT on) 16 | 17 | include(pico_sdk_import.cmake) 18 | 19 | project(can2040_example) 20 | 21 | pico_sdk_init() 22 | 23 | add_executable(canexample 24 | canexample.c 25 | ../src/can2040.c 26 | ) 27 | 28 | pico_set_binary_type(canexample copy_to_ram) 29 | target_link_libraries(canexample pico_stdlib) 30 | pico_enable_stdio_usb(canexample 1) 31 | pico_enable_stdio_uart(canexample 0) 32 | 33 | pico_add_extra_outputs(canexample) 34 | -------------------------------------------------------------------------------- /example/canbuild.docker: -------------------------------------------------------------------------------- 1 | # This dockerfile is a reference for building and running a container 2 | # utilizing the Raspberry Pi pico-sdk. 3 | # 4 | # Typically one would build the container with something like: 5 | # docker build -t canbuild -f example/canbuild.docker 6 | # And then one could generate the canexample.uf2 file with something like: 7 | # mkdir build 8 | # docker run --rm -it -v ./example:/root/example -v ./src:/root/src -v ./build:/root/build -w /root/build localhost/canbuild /bin/bash -c 'cmake -D PICO_SDK_PATH=../pico-sdk -D PICO_BOARD=pico ../example && make' 9 | 10 | FROM ubuntu:22.04 as base 11 | 12 | ENV DEBIAN_FRONTEND=noninteractive 13 | 14 | RUN apt update && apt install -y \ 15 | cmake python3 build-essential gcc-arm-none-eabi \ 16 | libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib \ 17 | git 18 | 19 | RUN cd ~ && git clone --depth 1 --branch 2.1.1 https://github.com/raspberrypi/pico-sdk.git && cd pico-sdk && git submodule update --init 20 | -------------------------------------------------------------------------------- /example/canexample.c: -------------------------------------------------------------------------------- 1 | // This is a simple example program using can2040 and the PICO SDK. 2 | // 3 | // See the CMakeLists.txt file for information on compiling. 4 | 5 | #include 6 | #include 7 | 8 | #include "../src/can2040.h" 9 | 10 | // Simple example of irq safe queue (this is not multi-core safe) 11 | #define QUEUE_SIZE 128 // Must be power of 2 12 | static struct { 13 | uint32_t pull_pos; 14 | volatile uint32_t push_pos; 15 | struct can2040_msg queue[QUEUE_SIZE]; 16 | } MessageQueue; 17 | 18 | // Internal storage for can2040 module 19 | static struct can2040 cbus; 20 | 21 | // Main canbus callback (called from irq handler) 22 | static void 23 | can2040_cb(struct can2040 *cd, uint32_t notify, struct can2040_msg *msg) 24 | { 25 | if (notify == CAN2040_NOTIFY_RX) { 26 | // Example message filter 27 | uint32_t id = msg->id; 28 | if (id < 0x101 || id > 0x201) 29 | return; 30 | 31 | // Add to queue 32 | uint32_t push_pos = MessageQueue.push_pos; 33 | uint32_t pull_pos = MessageQueue.pull_pos; 34 | if (push_pos + 1 == pull_pos) 35 | // No space in queue 36 | return; 37 | MessageQueue.queue[push_pos % QUEUE_SIZE] = *msg; 38 | MessageQueue.push_pos = push_pos + 1; 39 | } 40 | } 41 | 42 | // PIO interrupt handler 43 | static void 44 | PIOx_IRQHandler(void) 45 | { 46 | can2040_pio_irq_handler(&cbus); 47 | } 48 | 49 | // Initialize the can2040 module 50 | void 51 | canbus_setup(void) 52 | { 53 | uint32_t pio_num = 0; 54 | uint32_t sys_clock = SYS_CLK_HZ, bitrate = 500000; 55 | uint32_t gpio_rx = 4, gpio_tx = 5; 56 | 57 | // Setup canbus 58 | can2040_setup(&cbus, pio_num); 59 | can2040_callback_config(&cbus, can2040_cb); 60 | 61 | // Enable irqs 62 | irq_set_exclusive_handler(PIO0_IRQ_0, PIOx_IRQHandler); 63 | irq_set_priority(PIO0_IRQ_0, 1); 64 | irq_set_enabled(PIO0_IRQ_0, 1); 65 | 66 | // Start canbus 67 | can2040_start(&cbus, sys_clock, bitrate, gpio_rx, gpio_tx); 68 | } 69 | 70 | int 71 | main(void) 72 | { 73 | stdio_init_all(); 74 | canbus_setup(); 75 | 76 | // Main loop 77 | for (;;) { 78 | uint32_t push_pos = MessageQueue.push_pos; 79 | uint32_t pull_pos = MessageQueue.pull_pos; 80 | if (push_pos == pull_pos) 81 | // No new messages read. 82 | continue; 83 | 84 | // Pop message from local receive queue 85 | struct can2040_msg *qmsg = &MessageQueue.queue[pull_pos % QUEUE_SIZE]; 86 | struct can2040_msg msg = *qmsg; 87 | MessageQueue.pull_pos++; 88 | 89 | // Report message found on local receive queue 90 | printf("msg: id=0x%x dlc=%d data=%02x%02x%02x%02x%02x%02x%02x%02x\n", 91 | msg.id, msg.dlc, msg.data[0], msg.data[1], msg.data[2], 92 | msg.data[3], msg.data[4], msg.data[5], msg.data[6], msg.data[7]); 93 | 94 | // Demo of message transmit 95 | if (msg.id == 0x101) { 96 | struct can2040_msg tmsg; 97 | tmsg.id = 0x102; 98 | tmsg.dlc = 8; 99 | tmsg.data32[0] = 0xabcd; 100 | tmsg.data32[1] = msg.data32[0]; 101 | int sts = can2040_transmit(&cbus, &tmsg); 102 | printf("Sent message (status=%d)\n", sts); 103 | } 104 | } 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /example/pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # This is a copy of /external/pico_sdk_import.cmake 2 | 3 | # This can be dropped into an external project to help locate this SDK 4 | # It should be include()ed prior to project() 5 | 6 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 9 | endif () 10 | 11 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 14 | endif () 15 | 16 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 19 | endif () 20 | 21 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG)) 22 | set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG}) 23 | message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')") 24 | endif () 25 | 26 | if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG) 27 | set(PICO_SDK_FETCH_FROM_GIT_TAG "master") 28 | message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG") 29 | endif() 30 | 31 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 32 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 33 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 34 | set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK") 35 | 36 | if (NOT PICO_SDK_PATH) 37 | if (PICO_SDK_FETCH_FROM_GIT) 38 | include(FetchContent) 39 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 40 | if (PICO_SDK_FETCH_FROM_GIT_PATH) 41 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 42 | endif () 43 | # GIT_SUBMODULES_RECURSE was added in 3.17 44 | if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") 45 | FetchContent_Declare( 46 | pico_sdk 47 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 48 | GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} 49 | GIT_SUBMODULES_RECURSE FALSE 50 | ) 51 | else () 52 | FetchContent_Declare( 53 | pico_sdk 54 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 55 | GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} 56 | ) 57 | endif () 58 | 59 | if (NOT pico_sdk) 60 | message("Downloading Raspberry Pi Pico SDK") 61 | FetchContent_Populate(pico_sdk) 62 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 63 | endif () 64 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 65 | else () 66 | message(FATAL_ERROR 67 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 68 | ) 69 | endif () 70 | endif () 71 | 72 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 73 | if (NOT EXISTS ${PICO_SDK_PATH}) 74 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 75 | endif () 76 | 77 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 78 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 79 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 80 | endif () 81 | 82 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 83 | 84 | include(${PICO_SDK_INIT_CMAKE_FILE}) 85 | -------------------------------------------------------------------------------- /pio/README.md: -------------------------------------------------------------------------------- 1 | This directory contains reference information on can2040's usage of 2 | the Raspberry Pi rp2040 "Programmable Input/Output block" (PIO). 3 | 4 | One may use the can2040 code without needing to build or utilize the 5 | files in this directory. 6 | 7 | This information here may be useful for those interested in the 8 | internal behavior of the can2040 implementation. 9 | -------------------------------------------------------------------------------- /pio/can2040.pio: -------------------------------------------------------------------------------- 1 | // Reference code for rp2040 PIO handlers 2 | // 3 | // Copyright (C) 2022 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU GPLv3 license. 6 | 7 | .program can2040 8 | 9 | // This is the main PIO code for the can2040 CANbus software. The 10 | // code is convoluted due to space constraints of the PIO (a max of 32 11 | // instructions). 12 | 13 | // This implementation is designed to run at 32 times the bitrate. 14 | // The "cp=" comments in the code indicate the "clock phase" - which 15 | // ranges from 0 to 31 (32 is 0 again). At "cp=0" a one to zero edge 16 | // is first detected, at "cp=26" is the sampling point, and "cp=31" 17 | // output changes are made (so that they are observed by "cp=32"). 18 | 19 | // State machine "sync" code - clock and start/end of message signaling 20 | sync_recessive_edge: 21 | jmp y--, sync_scan_edge ; cp=31,33,35,37 22 | jmp x--, sync_signal_sample ; cp=6 23 | public sync_found_end_of_message: 24 | set x, 9 ; cp=7 25 | sync_loop_end_of_message: 26 | jmp pin sync_check_idle 27 | public sync_signal_start: 28 | irq set 0 29 | sync_scan_edge: 30 | jmp pin sync_recessive_edge ; cp=30,32,34,36 31 | public sync_entry: 32 | irq clear 0 ; cp=1 33 | sync_got_dominant: 34 | set x, 9 [4] ; cp=2 35 | sync_signal_sample: 36 | set y, 3 [16] ; cp=7 37 | irq set 4 [1] ; cp=24 38 | jmp pin sync_scan_edge [3] ; cp=26 39 | jmp sync_got_dominant [3] ; cp=30 40 | sync_check_idle: 41 | jmp x-- sync_loop_end_of_message 42 | public sync_end: 43 | ;jmp sync_signal_start ; wrap based jump 44 | 45 | // State machine "rx" code - forward data to cpu 46 | public shared_rx_read: 47 | wait 1 irq 4 48 | in pins, 1 ; cp=26 49 | public shared_rx_end: 50 | ;jmp shared_rx_read ; wrap based jump 51 | 52 | // State machine "match" code - raise "matched" signal on a raw bitstream match 53 | mov y, isr ; cp=27 54 | jmp x!=y match_load_next [1]; cp=28 55 | match_signal: 56 | irq set 2 ; cp=30 57 | public match_load_next: 58 | in osr, 11 ; load next_counter and bits into isr 59 | in y, 20 60 | mov y, osr 61 | match_check_next: 62 | pull noblock ; reload target_compare into x 63 | mov x, osr 64 | jmp y-- f2 ; setup next_counter 65 | public tx_conflict: 66 | f2:mov osr, y 67 | public match_end: 68 | ;jmp shared_rx_read ; wrap based jump 69 | 70 | // State machine "tx" code - write messages to bus 71 | public tx_got_recessive: 72 | out x, 1 ; cp=27 73 | jmp pin tx_align ; cp=28 74 | public tx_write_pin: 75 | mov pins, x [24] ; cp=31 76 | jmp pin tx_got_recessive [2]; cp=24 77 | jmp x-- tx_conflict ; cp=27 On conflict, spin forever on dummy insn 78 | out x, 1 ; cp=28 79 | tx_align: 80 | jmp tx_write_pin [1] ; cp=29 81 | 82 | 83 | // 84 | // Setup code (reference only) 85 | // 86 | 87 | // Setup for "sync" state machine 88 | .program sm_sync_setup 89 | set pindirs, 0 90 | // CPU pushes 105 into tx fifo - to set OSR for alternative slow start mode 91 | pull 92 | ;jmp sync_got_dominant 93 | 94 | // Alternate code for sync_found_end_of_message when slow start needed 95 | .program sm_sync_alt_slow_start 96 | mov x, osr [1] 97 | 98 | // Setup for "rx" state machine 99 | .program sm_rx_setup 100 | ;jmp shared_rx_read 101 | 102 | // Setup for "match" state machine 103 | .program sm_match_setup 104 | set y, 0 105 | mov osr, y 106 | mov x, !y 107 | ;jmp match_load_next 108 | 109 | // Setup for "tx" state machine 110 | .program sm_tx_setup 111 | set pins, 1 112 | set pindirs, 1 113 | 114 | // Transmit sequence for "tx" state machine 115 | .program sm_tx_transmit 116 | // CPU first disables state machine execution 117 | // CPU clears irq 2 and irq 3 118 | // CPU then loads tx fifos with full (bitstuffed) message 119 | set pins, 1 120 | out x, 1 121 | ;jmp tx_write_pin 122 | wait 1 irq 0 123 | // CPU then starts state machine execution 124 | 125 | // Transmit sequence for "tx" state machine ack injection 126 | .program sm_tx_ack 127 | // CPU first disables state machine execution 128 | // CPU clears irq 2 and irq 3 129 | // CPU changes instruction at tx_got_recessive from "out x, 1" to: 130 | irq wait 3 131 | // CPU then loads tx fifo with ack (single off bit) 132 | set pins, 1 133 | out x, 1 134 | ;jmp tx_write_pin 135 | wait 1 irq 2 136 | // CPU then starts state machine execution 137 | // CPU then loads match fifo with CRC/position sequence to check 138 | 139 | 140 | // 141 | // Reference "sync" state machine without code size reduction hacks 142 | // 143 | 144 | .program reference_sync_sm 145 | 146 | sync_got_dominant: 147 | set x, 9 148 | jmp sync_signal_sample 149 | 150 | sync_signal_sample: 151 | irq set 4 152 | jmp pin sync_scan_edge 153 | jmp sync_got_dominant 154 | 155 | sync_scan_edge: 156 | set y, 3 157 | sync_loop_scan_edge: 158 | jmp pin sync_recessive_edge 159 | jmp sync_got_dominant 160 | sync_recessive_edge: 161 | jmp y--, sync_loop_scan_edge 162 | jmp x--, sync_signal_sample 163 | jmp sync_found_end_of_message 164 | 165 | sync_found_end_of_message: 166 | set x, 8 167 | sync_loop_end_of_message: 168 | jmp pin sync_check_idle 169 | jmp sync_signal_start 170 | sync_check_idle: 171 | jmp x-- sync_loop_end_of_message 172 | jmp sync_found_idle 173 | 174 | sync_found_idle: 175 | irq set 0 176 | sync_loop_idle: 177 | jmp pin sync_loop_idle 178 | jmp sync_signal_start 179 | 180 | sync_signal_start: 181 | irq set 0 182 | irq clear 0 183 | jmp sync_got_dominant 184 | -------------------------------------------------------------------------------- /pio/pioasm.docker: -------------------------------------------------------------------------------- 1 | # This dockerfile is a reference for building and running a container 2 | # for the Raspberry Pi pico "pioasm" utility. 3 | # 4 | # Typically one would build the container with something like: 5 | # docker build -t pioasm -f pio/pioasm.docker 6 | # And then one could assemble the can2040.pio file with something like: 7 | # docker run --rm -it -v ./pio:/project localhost/pioasm /project/can2040.pio 8 | 9 | FROM ubuntu:22.04 as base 10 | 11 | ENV DEBIAN_FRONTEND=noninteractive 12 | 13 | RUN apt update && apt install -y \ 14 | build-essential \ 15 | cmake \ 16 | git 17 | 18 | RUN cd ~ && git clone --depth 1 --branch 2.1.1 https://github.com/raspberrypi/pico-sdk.git 19 | 20 | RUN mkdir ~/piobuild && cd ~/piobuild \ 21 | && cmake ~/pico-sdk/tools/pioasm \ 22 | && make 23 | 24 | ENTRYPOINT ["/root/piobuild/pioasm"] 25 | -------------------------------------------------------------------------------- /scripts/bitstuf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Tool for testing bitstuffing implementations 3 | # 4 | # Copyright (C) 2022-2024 Kevin O'Connor 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import sys 8 | 9 | TESTBITS=20 10 | 11 | def report(msg): 12 | sys.stderr.write("\n" + msg + "\n") 13 | 14 | def clz(v): 15 | v &= 0xffffffff 16 | return 32 - v.bit_length() 17 | 18 | LOOP = UNLOOP = 0 19 | 20 | def bitstuf(b, num_bits): 21 | global LOOP 22 | edges = b ^ (b >> 1) 23 | count = num_bits 24 | i = num_bits-1 25 | while i >= 0: 26 | LOOP += 1 27 | if not ((edges >> i) & 0xf): 28 | mask = (1 << (i + 1)) - 1 29 | low = b & mask 30 | high = (b & ~(mask >> 1)) << 1 31 | b = high ^ low ^ (1 << i) 32 | i -= 3 33 | count += 1 34 | edges = b ^ (b >> 1) 35 | i -= 1 36 | return b, count 37 | 38 | def bitstuf_batch(b, num_bits): 39 | global LOOP 40 | count = num_bits 41 | while 1: 42 | edges = b ^ (b >> 1) 43 | e2 = edges | (edges >> 1) 44 | e4 = e2 | (e2 >> 2) 45 | add_bits = ~e4 46 | try_cnt = num_bits 47 | while 1: 48 | LOOP += 1 49 | try_mask = ((1 << try_cnt) - 1) << (num_bits - try_cnt) 50 | if not add_bits & try_mask: 51 | # No stuff bits needed in try_cnt bits 52 | if try_cnt >= num_bits: 53 | return b, count 54 | num_bits -= try_cnt 55 | try_cnt = (num_bits + 1) // 2 56 | continue 57 | if add_bits & (1 << (num_bits - 1)): 58 | # A stuff bit must be inserted prior to the high bit 59 | low_mask = (1 << num_bits) - 1 60 | low = b & low_mask 61 | high = (b & ~(low_mask >> 1)) << 1 62 | b = high ^ low ^ (1 << (num_bits - 1)) 63 | count += 1 64 | if num_bits <= 4: 65 | return b, count 66 | num_bits -= 4 67 | break 68 | # High bit doesn't need stuff bit - accept it, limit try_cnt, retry 69 | num_bits -= 1 70 | try_cnt //= 2 71 | 72 | def bitstuf_clz(b, num_bits): 73 | global LOOP 74 | count = num_bits 75 | while 1: 76 | LOOP += 1 77 | edges = b ^ (b >> 1) 78 | e2 = edges | (edges >> 1) 79 | e4 = e2 | (e2 >> 2) 80 | add_bits = ~e4 81 | mask = (1 << num_bits) - 1 82 | add_masked_bits = add_bits & mask 83 | if not add_masked_bits: 84 | # No more stuff bits needed 85 | return b, count 86 | # Insert a stuff bit 87 | stuff_pos = 1 + 31 - clz(add_masked_bits) 88 | low_mask = (1 << stuff_pos) - 1 89 | low = b & low_mask 90 | high = (b & ~(low_mask >> 1)) << 1 91 | b = high ^ low ^ (1 << (stuff_pos - 1)) 92 | count += 1 93 | if stuff_pos <= 4: 94 | return b, count 95 | num_bits = stuff_pos - 4 96 | 97 | def bitunstuf(sb, num_bits): 98 | global UNLOOP 99 | edges = sb ^ (sb >> 1) 100 | unstuffed_bits = 0 101 | cu = TESTBITS 102 | cs = num_bits 103 | while 1: 104 | UNLOOP += 1 105 | if not cu: 106 | # Extracted desired bits 107 | return unstuffed_bits 108 | if not cs: 109 | # Need more data 110 | return -999 111 | cs -= 1 112 | if (edges >> (cs+1)) & 0xf: 113 | # Normal data 114 | cu -= 1 115 | unstuffed_bits |= ((sb >> cs) & 1) << cu 116 | elif ((edges >> cs) & 0x1f) == 0x00: 117 | # Six consecutive bits - a bitstuff error 118 | if (sb >> cs) & 1: 119 | return -cs 120 | return -cs 121 | 122 | def bitunstuf_batch(sb, num_bits): 123 | global UNLOOP 124 | edges = sb ^ (sb >> 1) 125 | e2 = edges | (edges >> 1) 126 | e4 = e2 | (e2 >> 2) 127 | rm_bits = ~e4 128 | unstuffed_bits = 0 129 | cu = TESTBITS 130 | cs = num_bits 131 | while 1: 132 | try_cnt = cu if cu < cs else cs 133 | while 1: 134 | UNLOOP += 1 135 | try_mask = ((1 << try_cnt) - 1) << (cs + 1 - try_cnt) 136 | if not (rm_bits & try_mask): 137 | # No stuff bits in try_cnt bits - copy into unstuffed_bits 138 | cu -= try_cnt 139 | cs -= try_cnt 140 | unstuffed_bits |= ((sb >> cs) & ((1 << try_cnt) - 1)) << cu 141 | if not cu: 142 | # Extracted desired bits 143 | return unstuffed_bits 144 | break 145 | cs -= 1 146 | if rm_bits & (1 << (cs + 1)): 147 | # High bit of try_cnt a stuff bit 148 | if rm_bits & (1 << cs): 149 | # Six consecutive bits - a bitstuff error 150 | if (sb >> cs) & 1: 151 | return -cs 152 | return -cs 153 | break 154 | # High bit not a stuff bit - limit try_cnt and retry 155 | cu -= 1 156 | unstuffed_bits |= ((sb >> cs) & 1) << cu 157 | try_cnt //= 2 158 | if not cs: 159 | # Need more data 160 | return -999 161 | 162 | def bitunstuf_batch_pass4(sb, num_bits): 163 | global UNLOOP 164 | edges = sb ^ (sb >> 1) 165 | e2 = edges | (edges >> 1) 166 | e4 = e2 | (e2 >> 2) 167 | rm_bits = ~e4 168 | unstuffed_bits = 0 169 | cu = TESTBITS 170 | cs = num_bits 171 | try_cnt = cu if cu < cs else cs 172 | while 1: 173 | UNLOOP += 1 174 | pass_cnt = try_cnt 175 | try_mask = ((1 << try_cnt) - 1) << (cs + 1 - try_cnt) 176 | if rm_bits & try_mask: 177 | # There is a stuff bit somewhere in try_cnt 178 | if rm_bits & (1 << cs): 179 | # High bit is a stuff bit 180 | cs -= 1 181 | if rm_bits & (1 << cs): 182 | # Six consecutive bits - a bitstuff error 183 | if (sb >> cs) & 1: 184 | return -cs 185 | return -cs 186 | rem_cnt = cu if cu < cs else cs 187 | pass_cnt = try_cnt = rem_cnt if rem_cnt < 4 else 4 188 | else: 189 | # High bit is not a stuff bit - pass 1, limit try_cnt, retry 190 | pass_cnt = 1 191 | # Copy pass_cnt bits into unstuffed_bits 192 | cu -= pass_cnt 193 | cs -= pass_cnt 194 | unstuffed_bits |= ((sb >> cs) & ((1 << pass_cnt) - 1)) << cu 195 | if not cu: 196 | # Extracted desired bits 197 | return unstuffed_bits 198 | if not cs: 199 | # Need more data 200 | return -999 201 | if pass_cnt >= try_cnt: 202 | try_cnt = cu if cu < cs else cs 203 | else: 204 | try_cnt //= 2 205 | 206 | def bitunstuf_clz(sb, num_bits): 207 | global UNLOOP 208 | edges = sb ^ (sb >> 1) 209 | e2 = edges | (edges >> 1) 210 | e4 = e2 | (e2 >> 2) 211 | rm_bits = ~e4 212 | unstuffed_bits = 0 213 | cu = TESTBITS 214 | cs = num_bits 215 | while 1: 216 | UNLOOP += 1 217 | if not cs: 218 | # Need more data 219 | return -999 220 | try_cnt = cu if cu < cs else cs 221 | try_mask = ((1 << try_cnt) - 1) << (cs + 1 - try_cnt) 222 | rm_masked_bits = rm_bits & try_mask 223 | if not rm_masked_bits: 224 | # No stuff bits in try_cnt bits - copy into unstuffed_bits 225 | cu -= try_cnt 226 | cs -= try_cnt 227 | unstuffed_bits |= ((sb >> cs) & ((1 << try_cnt) - 1)) << cu 228 | if not cu: 229 | # Extracted desired bits 230 | return unstuffed_bits 231 | # Need more data 232 | return -999 233 | # Copy any leading bits prior to stuff bit (may be zero) 234 | copy_cnt = cs - (31 - clz(rm_masked_bits)) 235 | cs -= copy_cnt 236 | cu -= copy_cnt 237 | unstuffed_bits |= ((sb >> cs) & ((1 << copy_cnt) - 1)) << cu 238 | # High bit is now a stuff bit - remove it 239 | cs -= 1 240 | if rm_bits & (1 << cs): 241 | # Six consecutive bits - a bitstuff error 242 | if (sb >> cs) & 1: 243 | return -cs 244 | return -cs 245 | 246 | def main(): 247 | stuf_func = bitstuf_batch 248 | unstuf_func = bitunstuf_batch 249 | for i in range(1< %s -> %s (%d)" 258 | % (i, format(val, '025b'), format(sv, '025b') 259 | , format(uv, '025b'), sv)) 260 | sys.exit(-1) 261 | report("Test completed successfully (avg passes: %.3f stuff, %.3f unstuff)" 262 | % (LOOP / (1< 5 | # 6 | # This file may be distributed under the terms of the GNU GPLv3 license. 7 | import sys 8 | 9 | def report(msg): 10 | sys.stderr.write(msg + "\n") 11 | 12 | # Basic bit-by-bit canbus crc implementation 13 | def crc_bitloop(data): 14 | crc = 0 15 | l = len(data) - 1 16 | val = sum([v << ((l-i)*8) for i, v in enumerate(data)]) 17 | count = len(data) * 8 18 | for i in range(count-1, -1, -1): 19 | bit = (val >> i) & 1 20 | if ((crc >> 14) & 1) ^ bit: 21 | crc = (crc << 1) ^ 0x4599 22 | else: 23 | crc = crc << 1 24 | return crc & 0x7fff 25 | 26 | # Simple bit manipulation improvement 27 | def crc_bitloop2(data): 28 | crc = 0 29 | l = len(data) - 1 30 | val = sum([v << ((l-i)*8) for i, v in enumerate(data)]) 31 | count = len(data) * 8 32 | for i in range(count-1, -1, -1): 33 | bit = (val >> i) << 15 34 | crc <<= 1 35 | if (crc ^ bit) & (1 << 15): 36 | crc ^= 0x4599 37 | return crc & 0x7fff 38 | 39 | # Byte at a time version 40 | def crc_byteloop(data): 41 | crc = 0 42 | for v in data: 43 | crc ^= v << 7 44 | for i in range(7, -1, -1): 45 | crc <<= 1 46 | if crc & 0x8000: 47 | crc ^= 0x4599 48 | return crc & 0x7fff 49 | 50 | # A 4-bit at a time table lookup version 51 | def crc_4bit_table(table, data): 52 | crc = 0 53 | l = len(data) - 1 54 | val = sum([v << ((l-i)*8) for i, v in enumerate(data)]) 55 | count = len(data) * 8 56 | for i in range(count-4, -4, -4): 57 | pos = ((crc >> 11) ^ (val >> i)) & 0x0f 58 | crc = (crc << 4) ^ table[pos] 59 | return crc & 0x7fff 60 | 61 | # A 8-bit at a time table lookup version 62 | def crc_8bit_table(table, data): 63 | crc = 0 64 | for v in data: 65 | crc = (crc << 8) ^ table[((crc >> 7) ^ v) & 0xff] 66 | return crc & 0x7fff 67 | 68 | TESTDATA = b"Some string of data" 69 | 70 | def main(): 71 | # Build 4bit table version 72 | bit4_table = [crc_bitloop([i]) for i in range(16)] 73 | print("Table 4bit:", ", ".join(["0x%04x" % i for i in bit4_table])) 74 | # Build 8bit table version 75 | bit8_table = [crc_bitloop([i]) for i in range(256)] 76 | print("Table 8bit:", ",".join(["0x%04x" % i for i in bit8_table])) 77 | # Test versions 78 | for i in range(len(TESTDATA)): 79 | d = TESTDATA[i:] 80 | crc1 = crc_bitloop(d) 81 | crc2 = crc_8bit_table(bit8_table, d) 82 | if crc1 != crc2: 83 | report("Got mismatch on '%s' %02x vs %02x" % (d, crc1, crc2)) 84 | sys.exit(-1) 85 | report("Test completed successfully") 86 | 87 | if __name__ == '__main__': 88 | main() 89 | -------------------------------------------------------------------------------- /src/can2040.c: -------------------------------------------------------------------------------- 1 | // Software CANbus implementation for rp2040 2 | // 3 | // Copyright (C) 2022-2025 Kevin O'Connor 4 | // 5 | // This file may be distributed under the terms of the GNU GPLv3 license. 6 | 7 | #include // uint32_t 8 | #include // memset 9 | #include "can2040.h" // can2040_setup 10 | #include "hardware/regs/dreq.h" // DREQ_PIO0_RX1 11 | #include "hardware/structs/dma.h" // dma_hw 12 | #include "hardware/structs/iobank0.h" // iobank0_hw 13 | #include "hardware/structs/padsbank0.h" // padsbank0_hw 14 | #include "hardware/structs/pio.h" // pio0_hw 15 | #include "hardware/structs/resets.h" // RESETS_RESET_PIO0_BITS 16 | 17 | 18 | /**************************************************************** 19 | * rp2040 and low-level helper functions 20 | ****************************************************************/ 21 | 22 | // Determine if the target is an rp2350 23 | #ifdef PICO_RP2350 24 | #define IS_RP2350 1 25 | #else 26 | #define IS_RP2350 0 27 | #endif 28 | 29 | // Helper compiler definitions 30 | #define barrier() __asm__ __volatile__("": : :"memory") 31 | #define likely(x) __builtin_expect(!!(x), 1) 32 | #define unlikely(x) __builtin_expect(!!(x), 0) 33 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 34 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 35 | #define __DMB() __asm__ __volatile__("dmb 0xF": : :"memory") 36 | 37 | // Helper functions for writing to "io" memory 38 | static inline void writel(void *addr, uint32_t val) { 39 | barrier(); 40 | *(volatile uint32_t *)addr = val; 41 | } 42 | static inline uint32_t readl(const void *addr) { 43 | uint32_t val = *(volatile const uint32_t *)addr; 44 | barrier(); 45 | return val; 46 | } 47 | 48 | // rp2040 helper function to clear a hardware reset bit 49 | static void 50 | rp2040_clear_reset(uint32_t reset_bit) 51 | { 52 | if (resets_hw->reset & reset_bit) { 53 | hw_clear_bits(&resets_hw->reset, reset_bit); 54 | while (!(resets_hw->reset_done & reset_bit)) 55 | ; 56 | } 57 | } 58 | 59 | // Helper to set the mode and extended function of a pin 60 | static void 61 | rp2040_gpio_peripheral(uint32_t gpio, int func, int pull_up) 62 | { 63 | padsbank0_hw->io[gpio] = ( 64 | PADS_BANK0_GPIO0_IE_BITS 65 | | (PADS_BANK0_GPIO0_DRIVE_VALUE_4MA << PADS_BANK0_GPIO0_DRIVE_MSB) 66 | | (pull_up > 0 ? PADS_BANK0_GPIO0_PUE_BITS : 0) 67 | | (pull_up < 0 ? PADS_BANK0_GPIO0_PDE_BITS : 0)); 68 | iobank0_hw->io[gpio].ctrl = func << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; 69 | } 70 | 71 | 72 | /**************************************************************** 73 | * rp2040 PIO support 74 | ****************************************************************/ 75 | 76 | #define PIO_CLOCK_PER_BIT 32 77 | #define PIO_RX_WAKE_BITS 10 78 | 79 | #define can2040_offset_sync_found_end_of_message 2u 80 | #define can2040_offset_sync_signal_start 4u 81 | #define can2040_offset_sync_entry 6u 82 | #define can2040_offset_sync_end 13u 83 | #define can2040_offset_shared_rx_read 13u 84 | #define can2040_offset_shared_rx_end 15u 85 | #define can2040_offset_match_load_next 18u 86 | #define can2040_offset_tx_conflict 24u 87 | #define can2040_offset_match_end 25u 88 | #define can2040_offset_tx_got_recessive 25u 89 | #define can2040_offset_tx_write_pin 27u 90 | 91 | static const uint16_t can2040_program_instructions[] = { 92 | 0x0085, // 0: jmp y--, 5 93 | 0x0048, // 1: jmp x--, 8 94 | 0xe029, // 2: set x, 9 95 | 0x00cc, // 3: jmp pin, 12 96 | 0xc000, // 4: irq nowait 0 97 | 0x00c0, // 5: jmp pin, 0 98 | 0xc040, // 6: irq clear 0 99 | 0xe429, // 7: set x, 9 [4] 100 | 0xf043, // 8: set y, 3 [16] 101 | 0xc104, // 9: irq nowait 4 [1] 102 | 0x03c5, // 10: jmp pin, 5 [3] 103 | 0x0307, // 11: jmp 7 [3] 104 | 0x0043, // 12: jmp x--, 3 105 | 0x20c4, // 13: wait 1 irq, 4 106 | 0x4001, // 14: in pins, 1 107 | 0xa046, // 15: mov y, isr 108 | 0x01b2, // 16: jmp x != y, 18 [1] 109 | 0xc002, // 17: irq nowait 2 110 | 0x40eb, // 18: in osr, 11 111 | 0x4054, // 19: in y, 20 112 | 0xa047, // 20: mov y, osr 113 | 0x8080, // 21: pull noblock 114 | 0xa027, // 22: mov x, osr 115 | 0x0098, // 23: jmp y--, 24 116 | 0xa0e2, // 24: mov osr, y 117 | 0x6021, // 25: out x, 1 118 | 0x00df, // 26: jmp pin, 31 119 | 0xb801, // 27: mov pins, x [24] 120 | 0x02d9, // 28: jmp pin, 25 [2] 121 | 0x0058, // 29: jmp x--, 24 122 | 0x6021, // 30: out x, 1 123 | 0x011b, // 31: jmp 27 [1] 124 | }; 125 | 126 | // Local names for PIO state machine IRQs 127 | #define SI_MAYTX PIO_IRQ0_INTE_SM0_BITS 128 | #define SI_MATCHED PIO_IRQ0_INTE_SM2_BITS 129 | #define SI_ACKDONE PIO_IRQ0_INTE_SM3_BITS 130 | #define SI_RX_DATA PIO_IRQ0_INTE_SM1_RXNEMPTY_BITS 131 | #define SI_TXPENDING PIO_IRQ0_INTE_SM1_BITS // Misc bit manually forced 132 | 133 | // Local names of the four PIO state machines 134 | enum { SM_SYNC = 0, SM_RX = 1, SM_MATCH = 2, SM_TX = 3 }; 135 | 136 | // Return the gpio bank offset (on rp2350 chips) 137 | static uint32_t 138 | pio_gpiobase(struct can2040 *cd) 139 | { 140 | if (!IS_RP2350) 141 | return 0; 142 | return (cd->gpio_rx > 31 || cd->gpio_tx > 31) ? 16 : 0; 143 | } 144 | 145 | // Setup PIO "sync" state machine (state machine 0) 146 | static void 147 | pio_sync_setup(struct can2040 *cd) 148 | { 149 | pio_hw_t *pio_hw = cd->pio_hw; 150 | pio_sm_hw_t *sm = &pio_hw->sm[SM_SYNC]; 151 | uint32_t gpio_rx = (cd->gpio_rx - pio_gpiobase(cd)) & 0x1f; 152 | sm->execctrl = ( 153 | gpio_rx << PIO_SM0_EXECCTRL_JMP_PIN_LSB 154 | | (can2040_offset_sync_end - 1) << PIO_SM0_EXECCTRL_WRAP_TOP_LSB 155 | | can2040_offset_sync_signal_start << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB); 156 | sm->pinctrl = ( 157 | 1 << PIO_SM0_PINCTRL_SET_COUNT_LSB 158 | | gpio_rx << PIO_SM0_PINCTRL_SET_BASE_LSB); 159 | sm->instr = 0xe080; // set pindirs, 0 160 | sm->pinctrl = 0; 161 | pio_hw->txf[SM_SYNC] = 9 + 6 * PIO_CLOCK_PER_BIT / 2; 162 | sm->instr = 0x80a0; // pull block 163 | sm->instr = can2040_offset_sync_entry; // jmp sync_entry 164 | } 165 | 166 | // Setup PIO "rx" state machine (state machine 1) 167 | static void 168 | pio_rx_setup(struct can2040 *cd) 169 | { 170 | pio_hw_t *pio_hw = cd->pio_hw; 171 | pio_sm_hw_t *sm = &pio_hw->sm[SM_RX]; 172 | uint32_t gpio_rx = (cd->gpio_rx - pio_gpiobase(cd)) & 0x1f; 173 | sm->execctrl = ( 174 | (can2040_offset_shared_rx_end - 1) << PIO_SM0_EXECCTRL_WRAP_TOP_LSB 175 | | can2040_offset_shared_rx_read << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB); 176 | sm->pinctrl = gpio_rx << PIO_SM0_PINCTRL_IN_BASE_LSB; 177 | sm->shiftctrl = 0; // flush fifo on a restart 178 | sm->shiftctrl = (PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS 179 | | PIO_RX_WAKE_BITS << PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB 180 | | PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS); 181 | sm->instr = can2040_offset_shared_rx_read; // jmp shared_rx_read 182 | } 183 | 184 | // Setup PIO "match" state machine (state machine 2) 185 | static void 186 | pio_match_setup(struct can2040 *cd) 187 | { 188 | pio_hw_t *pio_hw = cd->pio_hw; 189 | pio_sm_hw_t *sm = &pio_hw->sm[SM_MATCH]; 190 | sm->execctrl = ( 191 | (can2040_offset_match_end - 1) << PIO_SM0_EXECCTRL_WRAP_TOP_LSB 192 | | can2040_offset_shared_rx_read << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB); 193 | uint32_t gpio_rx = (cd->gpio_rx - pio_gpiobase(cd)) & 0x1f; 194 | sm->pinctrl = gpio_rx << PIO_SM0_PINCTRL_IN_BASE_LSB; 195 | sm->shiftctrl = 0; 196 | sm->instr = 0xe040; // set y, 0 197 | sm->instr = 0xa0e2; // mov osr, y 198 | sm->instr = 0xa02a; // mov x, !y 199 | sm->instr = can2040_offset_match_load_next; // jmp match_load_next 200 | } 201 | 202 | // Setup PIO "tx" state machine (state machine 3) 203 | static void 204 | pio_tx_setup(struct can2040 *cd) 205 | { 206 | pio_hw_t *pio_hw = cd->pio_hw; 207 | pio_sm_hw_t *sm = &pio_hw->sm[SM_TX]; 208 | uint32_t gpio_rx = (cd->gpio_rx - pio_gpiobase(cd)) & 0x1f; 209 | uint32_t gpio_tx = (cd->gpio_tx - pio_gpiobase(cd)) & 0x1f; 210 | sm->execctrl = ( 211 | gpio_rx << PIO_SM0_EXECCTRL_JMP_PIN_LSB 212 | | can2040_offset_tx_conflict << PIO_SM0_EXECCTRL_WRAP_TOP_LSB 213 | | can2040_offset_tx_conflict << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB); 214 | sm->shiftctrl = (PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS 215 | | PIO_SM0_SHIFTCTRL_AUTOPULL_BITS); 216 | sm->pinctrl = (1 << PIO_SM0_PINCTRL_SET_COUNT_LSB 217 | | 1 << PIO_SM0_PINCTRL_OUT_COUNT_LSB 218 | | gpio_tx << PIO_SM0_PINCTRL_SET_BASE_LSB 219 | | gpio_tx << PIO_SM0_PINCTRL_OUT_BASE_LSB); 220 | sm->instr = 0xe001; // set pins, 1 221 | sm->instr = 0xe081; // set pindirs, 1 222 | } 223 | 224 | // Set PIO "sync" machine to signal "may transmit" (sm irq 0) on 11 idle bits 225 | static void 226 | pio_sync_normal_start_signal(struct can2040 *cd) 227 | { 228 | pio_hw_t *pio_hw = cd->pio_hw; 229 | uint32_t eom_idx = can2040_offset_sync_found_end_of_message; 230 | pio_hw->instr_mem[eom_idx] = 0xe12a; // set x, 10 [1] 231 | } 232 | 233 | // Set PIO "sync" machine to signal "may transmit" (sm irq 0) on 17 idle bits 234 | static void 235 | pio_sync_slow_start_signal(struct can2040 *cd) 236 | { 237 | pio_hw_t *pio_hw = cd->pio_hw; 238 | uint32_t eom_idx = can2040_offset_sync_found_end_of_message; 239 | pio_hw->instr_mem[eom_idx] = 0xa127; // mov x, osr [1] 240 | } 241 | 242 | // Test if PIO "rx" state machine has overflowed its fifos 243 | static int 244 | pio_rx_check_stall(struct can2040 *cd) 245 | { 246 | pio_hw_t *pio_hw = cd->pio_hw; 247 | return pio_hw->fdebug & (1 << (PIO_FDEBUG_RXSTALL_LSB + 1)); 248 | } 249 | 250 | // Set PIO "match" state machine to raise a "matched" signal on a bit sequence 251 | static void 252 | pio_match_check(struct can2040 *cd, uint32_t match_key) 253 | { 254 | pio_hw_t *pio_hw = cd->pio_hw; 255 | pio_hw->txf[SM_MATCH] = match_key; 256 | } 257 | 258 | // Calculate pos+bits identifier for PIO "match" state machine 259 | static uint32_t 260 | pio_match_calc_key(uint32_t raw_bits, uint32_t rx_bit_pos) 261 | { 262 | return (raw_bits & 0x1fffff) | ((-rx_bit_pos) << 21); 263 | } 264 | 265 | // Cancel any pending checks on PIO "match" state machine 266 | static void 267 | pio_match_clear(struct can2040 *cd) 268 | { 269 | pio_match_check(cd, 0); 270 | } 271 | 272 | // Flush and halt PIO "tx" state machine 273 | static void 274 | pio_tx_reset(struct can2040 *cd) 275 | { 276 | pio_hw_t *pio_hw = cd->pio_hw; 277 | pio_hw->ctrl = 0x07 << PIO_CTRL_SM_ENABLE_LSB; 278 | pio_hw->ctrl = ((0x07 << PIO_CTRL_SM_ENABLE_LSB) 279 | | (0x08 << PIO_CTRL_SM_RESTART_LSB)); 280 | pio_hw->irq = (SI_MATCHED | SI_ACKDONE) >> 8; // clear PIO irq flags 281 | // Clear tx fifo 282 | pio_sm_hw_t *sm = &pio_hw->sm[SM_TX]; 283 | sm->shiftctrl = 0; 284 | sm->shiftctrl = (PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS 285 | | PIO_SM0_SHIFTCTRL_AUTOPULL_BITS); 286 | } 287 | 288 | // Queue a message for transmission on PIO "tx" state machine 289 | static void 290 | pio_tx_send(struct can2040 *cd, uint32_t *data, uint32_t count) 291 | { 292 | pio_hw_t *pio_hw = cd->pio_hw; 293 | pio_tx_reset(cd); 294 | pio_hw->instr_mem[can2040_offset_tx_got_recessive] = 0x6021; // out x, 1 295 | uint32_t i; 296 | for (i=0; itxf[SM_TX] = data[i]; 298 | pio_sm_hw_t *sm = &pio_hw->sm[SM_TX]; 299 | sm->instr = 0xe001; // set pins, 1 300 | sm->instr = 0x6021; // out x, 1 301 | sm->instr = can2040_offset_tx_write_pin; // jmp tx_write_pin 302 | sm->instr = 0x20c0; // wait 1 irq, 0 303 | pio_hw->ctrl = 0x0f << PIO_CTRL_SM_ENABLE_LSB; 304 | } 305 | 306 | // Set PIO "tx" state machine to inject an ack after a CRC match 307 | static void 308 | pio_tx_inject_ack(struct can2040 *cd, uint32_t match_key) 309 | { 310 | pio_hw_t *pio_hw = cd->pio_hw; 311 | pio_tx_reset(cd); 312 | pio_hw->instr_mem[can2040_offset_tx_got_recessive] = 0xc023; // irq wait 3 313 | pio_hw->txf[SM_TX] = 0x7fffffff; 314 | pio_sm_hw_t *sm = &pio_hw->sm[SM_TX]; 315 | sm->instr = 0xe001; // set pins, 1 316 | sm->instr = 0x6021; // out x, 1 317 | sm->instr = can2040_offset_tx_write_pin; // jmp tx_write_pin 318 | sm->instr = 0x20c2; // wait 1 irq, 2 319 | pio_hw->ctrl = 0x0f << PIO_CTRL_SM_ENABLE_LSB; 320 | 321 | pio_match_check(cd, match_key); 322 | } 323 | 324 | // Did PIO "tx" state machine unexpectedly finish a transmit attempt? 325 | static int 326 | pio_tx_did_fail(struct can2040 *cd) 327 | { 328 | pio_hw_t *pio_hw = cd->pio_hw; 329 | // Check for passive/dominant bit conflict without parser noticing 330 | if (pio_hw->sm[SM_TX].addr == can2040_offset_tx_conflict) 331 | return !(pio_hw->intr & SI_RX_DATA); 332 | // Check for unexpected drain of transmit queue without parser noticing 333 | return (!(pio_hw->flevel & PIO_FLEVEL_TX3_BITS) 334 | && (pio_hw->intr & (SI_MAYTX | SI_RX_DATA)) == SI_MAYTX); 335 | } 336 | 337 | // Enable host irqs for state machine signals 338 | static void 339 | pio_irq_set(struct can2040 *cd, uint32_t sm_irqs) 340 | { 341 | pio_hw_t *pio_hw = cd->pio_hw; 342 | pio_hw->inte0 = sm_irqs | SI_RX_DATA; 343 | } 344 | 345 | // Completely disable host irqs 346 | static void 347 | pio_irq_disable(struct can2040 *cd) 348 | { 349 | pio_hw_t *pio_hw = cd->pio_hw; 350 | pio_hw->inte0 = 0; 351 | } 352 | 353 | // Return current host irq mask 354 | static uint32_t 355 | pio_irq_get(struct can2040 *cd) 356 | { 357 | pio_hw_t *pio_hw = cd->pio_hw; 358 | return pio_hw->inte0; 359 | } 360 | 361 | // Raise the txpending flag 362 | static void 363 | pio_signal_set_txpending(struct can2040 *cd) 364 | { 365 | pio_hw_t *pio_hw = cd->pio_hw; 366 | pio_hw->irq_force = SI_TXPENDING >> 8; 367 | } 368 | 369 | // Clear the txpending flag 370 | static void 371 | pio_signal_clear_txpending(struct can2040 *cd) 372 | { 373 | pio_hw_t *pio_hw = cd->pio_hw; 374 | pio_hw->irq = SI_TXPENDING >> 8; 375 | } 376 | 377 | // Setup PIO state machines 378 | static void 379 | pio_sm_setup(struct can2040 *cd) 380 | { 381 | // Reset state machines 382 | pio_hw_t *pio_hw = cd->pio_hw; 383 | pio_hw->ctrl = PIO_CTRL_SM_RESTART_BITS | PIO_CTRL_CLKDIV_RESTART_BITS; 384 | pio_hw->fdebug = 0xffffffff; 385 | pio_hw->irq = 0xff; 386 | pio_signal_set_txpending(cd); 387 | 388 | // Load pio program 389 | uint32_t i; 390 | for (i=0; iinstr_mem[i] = can2040_program_instructions[i]; 392 | 393 | // Set initial state machine state 394 | pio_sync_setup(cd); 395 | pio_rx_setup(cd); 396 | pio_match_setup(cd); 397 | pio_tx_setup(cd); 398 | 399 | // Start state machines 400 | pio_hw->ctrl = 0x07 << PIO_CTRL_SM_ENABLE_LSB; 401 | } 402 | 403 | // Initial setup of gpio pins and PIO state machines 404 | static void 405 | pio_setup(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate) 406 | { 407 | // Configure pio0 clock 408 | uint32_t rb = cd->pio_num ? RESETS_RESET_PIO1_BITS : RESETS_RESET_PIO0_BITS; 409 | #if IS_RP2350 410 | if (cd->pio_num == 2) 411 | rb = RESETS_RESET_PIO2_BITS; 412 | #endif 413 | rp2040_clear_reset(rb); 414 | 415 | // Setup and sync pio state machine clocks 416 | pio_hw_t *pio_hw = cd->pio_hw; 417 | uint32_t div = (256 / PIO_CLOCK_PER_BIT) * sys_clock / bitrate; 418 | int i; 419 | for (i=0; i<4; i++) 420 | pio_hw->sm[i].clkdiv = div << PIO_SM0_CLKDIV_FRAC_LSB; 421 | 422 | // Configure gpiobase (on rp2350) 423 | #if IS_RP2350 424 | pio_hw->gpiobase = pio_gpiobase(cd); 425 | #endif 426 | 427 | // Configure state machines 428 | pio_sm_setup(cd); 429 | 430 | // Map Rx/Tx gpios 431 | uint32_t pio_func = 6 + cd->pio_num; 432 | rp2040_gpio_peripheral(cd->gpio_rx, pio_func, 1); 433 | rp2040_gpio_peripheral(cd->gpio_tx, pio_func, 0); 434 | } 435 | 436 | 437 | /**************************************************************** 438 | * CRC calculation 439 | ****************************************************************/ 440 | 441 | // Calculated 8-bit crc table (see scripts/crc.py) 442 | static const uint16_t crc_table[256] = { 443 | 0x0000,0x4599,0x4eab,0x0b32,0x58cf,0x1d56,0x1664,0x53fd,0x7407,0x319e, 444 | 0x3aac,0x7f35,0x2cc8,0x6951,0x6263,0x27fa,0x2d97,0x680e,0x633c,0x26a5, 445 | 0x7558,0x30c1,0x3bf3,0x7e6a,0x5990,0x1c09,0x173b,0x52a2,0x015f,0x44c6, 446 | 0x4ff4,0x0a6d,0x5b2e,0x1eb7,0x1585,0x501c,0x03e1,0x4678,0x4d4a,0x08d3, 447 | 0x2f29,0x6ab0,0x6182,0x241b,0x77e6,0x327f,0x394d,0x7cd4,0x76b9,0x3320, 448 | 0x3812,0x7d8b,0x2e76,0x6bef,0x60dd,0x2544,0x02be,0x4727,0x4c15,0x098c, 449 | 0x5a71,0x1fe8,0x14da,0x5143,0x73c5,0x365c,0x3d6e,0x78f7,0x2b0a,0x6e93, 450 | 0x65a1,0x2038,0x07c2,0x425b,0x4969,0x0cf0,0x5f0d,0x1a94,0x11a6,0x543f, 451 | 0x5e52,0x1bcb,0x10f9,0x5560,0x069d,0x4304,0x4836,0x0daf,0x2a55,0x6fcc, 452 | 0x64fe,0x2167,0x729a,0x3703,0x3c31,0x79a8,0x28eb,0x6d72,0x6640,0x23d9, 453 | 0x7024,0x35bd,0x3e8f,0x7b16,0x5cec,0x1975,0x1247,0x57de,0x0423,0x41ba, 454 | 0x4a88,0x0f11,0x057c,0x40e5,0x4bd7,0x0e4e,0x5db3,0x182a,0x1318,0x5681, 455 | 0x717b,0x34e2,0x3fd0,0x7a49,0x29b4,0x6c2d,0x671f,0x2286,0x2213,0x678a, 456 | 0x6cb8,0x2921,0x7adc,0x3f45,0x3477,0x71ee,0x5614,0x138d,0x18bf,0x5d26, 457 | 0x0edb,0x4b42,0x4070,0x05e9,0x0f84,0x4a1d,0x412f,0x04b6,0x574b,0x12d2, 458 | 0x19e0,0x5c79,0x7b83,0x3e1a,0x3528,0x70b1,0x234c,0x66d5,0x6de7,0x287e, 459 | 0x793d,0x3ca4,0x3796,0x720f,0x21f2,0x646b,0x6f59,0x2ac0,0x0d3a,0x48a3, 460 | 0x4391,0x0608,0x55f5,0x106c,0x1b5e,0x5ec7,0x54aa,0x1133,0x1a01,0x5f98, 461 | 0x0c65,0x49fc,0x42ce,0x0757,0x20ad,0x6534,0x6e06,0x2b9f,0x7862,0x3dfb, 462 | 0x36c9,0x7350,0x51d6,0x144f,0x1f7d,0x5ae4,0x0919,0x4c80,0x47b2,0x022b, 463 | 0x25d1,0x6048,0x6b7a,0x2ee3,0x7d1e,0x3887,0x33b5,0x762c,0x7c41,0x39d8, 464 | 0x32ea,0x7773,0x248e,0x6117,0x6a25,0x2fbc,0x0846,0x4ddf,0x46ed,0x0374, 465 | 0x5089,0x1510,0x1e22,0x5bbb,0x0af8,0x4f61,0x4453,0x01ca,0x5237,0x17ae, 466 | 0x1c9c,0x5905,0x7eff,0x3b66,0x3054,0x75cd,0x2630,0x63a9,0x689b,0x2d02, 467 | 0x276f,0x62f6,0x69c4,0x2c5d,0x7fa0,0x3a39,0x310b,0x7492,0x5368,0x16f1, 468 | 0x1dc3,0x585a,0x0ba7,0x4e3e,0x450c,0x0095 469 | }; 470 | 471 | // Update a crc with 8 bits of data 472 | static uint32_t 473 | crc_byte(uint32_t crc, uint32_t data) 474 | { 475 | return (crc << 8) ^ crc_table[((crc >> 7) ^ data) & 0xff]; 476 | } 477 | 478 | // Update a crc with 8, 16, 24, or 32 bits of data 479 | static inline uint32_t 480 | crc_bytes(uint32_t crc, uint32_t data, uint32_t num) 481 | { 482 | switch (num) { 483 | default: crc = crc_byte(crc, data >> 24); /* FALLTHRU */ 484 | case 3: crc = crc_byte(crc, data >> 16); /* FALLTHRU */ 485 | case 2: crc = crc_byte(crc, data >> 8); /* FALLTHRU */ 486 | case 1: crc = crc_byte(crc, data); 487 | } 488 | return crc; 489 | } 490 | 491 | 492 | /**************************************************************** 493 | * Bit unstuffing 494 | ****************************************************************/ 495 | 496 | // Add 'count' number of bits from 'data' to the 'bu' unstuffer 497 | static void 498 | unstuf_add_bits(struct can2040_bitunstuffer *bu, uint32_t data, uint32_t count) 499 | { 500 | uint32_t mask = (1 << count) - 1; 501 | bu->stuffed_bits = (bu->stuffed_bits << count) | (data & mask); 502 | bu->count_stuff = count; 503 | } 504 | 505 | // Reset state and set the next desired 'num_bits' unstuffed bits to extract 506 | static void 507 | unstuf_set_count(struct can2040_bitunstuffer *bu, uint32_t num_bits) 508 | { 509 | bu->unstuffed_bits = 0; 510 | bu->count_unstuff = num_bits; 511 | } 512 | 513 | // Clear bitstuffing state (used after crc field to avoid bitstuffing ack field) 514 | static void 515 | unstuf_clear_state(struct can2040_bitunstuffer *bu) 516 | { 517 | uint32_t lb = 1 << bu->count_stuff; 518 | bu->stuffed_bits = (bu->stuffed_bits & (lb - 1)) | (lb << 1); 519 | } 520 | 521 | // Restore raw bitstuffing state (used to undo unstuf_clear_state() ) 522 | static void 523 | unstuf_restore_state(struct can2040_bitunstuffer *bu, uint32_t data) 524 | { 525 | uint32_t cs = bu->count_stuff; 526 | bu->stuffed_bits = (bu->stuffed_bits & ((1 << cs) - 1)) | (data << cs); 527 | } 528 | 529 | // Pull bits from unstuffer (as specified in unstuf_set_count() ) 530 | static int 531 | unstuf_pull_bits_rp2040(struct can2040_bitunstuffer *bu) 532 | { 533 | uint32_t sb = bu->stuffed_bits, edges = sb ^ (sb >> 1); 534 | uint32_t e2 = edges | (edges >> 1), e4 = e2 | (e2 >> 2), rm_bits = ~e4; 535 | uint32_t cs = bu->count_stuff, cu = bu->count_unstuff; 536 | if (!cs) 537 | // Need more data 538 | return 1; 539 | for (;;) { 540 | uint32_t try_cnt = cs > cu ? cu : cs; 541 | for (;;) { 542 | uint32_t try_mask = ((1 << try_cnt) - 1) << (cs + 1 - try_cnt); 543 | if (likely(!(rm_bits & try_mask))) { 544 | // No stuff bits in try_cnt bits - copy into unstuffed_bits 545 | bu->count_unstuff = cu = cu - try_cnt; 546 | bu->count_stuff = cs = cs - try_cnt; 547 | bu->unstuffed_bits |= ((sb >> cs) & ((1 << try_cnt) - 1)) << cu; 548 | if (! cu) 549 | // Extracted desired bits 550 | return 0; 551 | break; 552 | } 553 | bu->count_stuff = cs = cs - 1; 554 | if (rm_bits & (1 << (cs + 1))) { 555 | // High bit is a stuff bit 556 | if (unlikely(rm_bits & (1 << cs))) { 557 | // Six consecutive bits - a bitstuff error 558 | if (sb & (1 << cs)) 559 | return -1; 560 | return -2; 561 | } 562 | break; 563 | } 564 | // High bit not a stuff bit - limit try_cnt and retry 565 | bu->count_unstuff = cu = cu - 1; 566 | bu->unstuffed_bits |= ((sb >> cs) & 1) << cu; 567 | try_cnt /= 2; 568 | } 569 | if (likely(!cs)) 570 | // Need more data 571 | return 1; 572 | } 573 | } 574 | 575 | // Pull bits from unstuffer (optimized for rp2350) 576 | static int 577 | unstuf_pull_bits(struct can2040_bitunstuffer *bu) 578 | { 579 | if (!IS_RP2350) 580 | return unstuf_pull_bits_rp2040(bu); 581 | uint32_t sb = bu->stuffed_bits, edges = sb ^ (sb >> 1); 582 | uint32_t e2 = edges | (edges >> 1), e4 = e2 | (e2 >> 2), rm_bits = ~e4; 583 | uint32_t cs = bu->count_stuff, cu = bu->count_unstuff; 584 | for (;;) { 585 | if (!cs) 586 | // Need more data 587 | return 1; 588 | uint32_t try_cnt = cs > cu ? cu : cs; 589 | uint32_t try_mask = ((1 << try_cnt) - 1) << (cs + 1 - try_cnt); 590 | uint32_t rm_masked_bits = rm_bits & try_mask; 591 | if (likely(!rm_masked_bits)) { 592 | // No stuff bits in try_cnt bits - copy into unstuffed_bits 593 | bu->count_unstuff = cu = cu - try_cnt; 594 | bu->count_stuff = cs = cs - try_cnt; 595 | bu->unstuffed_bits |= ((sb >> cs) & ((1 << try_cnt) - 1)) << cu; 596 | if (! cu) 597 | // Extracted desired bits 598 | return 0; 599 | // Need more data 600 | return 1; 601 | } 602 | // Copy any leading bits prior to stuff bit (may be zero) 603 | uint32_t copy_cnt = cs - (31 - __builtin_clz(rm_masked_bits)); 604 | cs -= copy_cnt; 605 | bu->count_unstuff = cu = cu - copy_cnt; 606 | bu->unstuffed_bits |= ((sb >> cs) & ((1 << copy_cnt) - 1)) << cu; 607 | // High bit is now a stuff bit - remove it 608 | bu->count_stuff = cs = cs - 1; 609 | if (unlikely(rm_bits & (1 << cs))) { 610 | // Six consecutive bits - a bitstuff error 611 | if (sb & (1 << cs)) 612 | return -1; 613 | return -2; 614 | } 615 | } 616 | } 617 | 618 | // Return most recent raw (still stuffed) bits 619 | static uint32_t 620 | unstuf_get_raw(struct can2040_bitunstuffer *bu) 621 | { 622 | return bu->stuffed_bits >> bu->count_stuff; 623 | } 624 | 625 | 626 | /**************************************************************** 627 | * Bit stuffing 628 | ****************************************************************/ 629 | 630 | // Stuff 'num_bits' bits in '*pb' - upper bits must already be stuffed 631 | static uint32_t 632 | bitstuff_rp2040(uint32_t *pb, uint32_t num_bits) 633 | { 634 | uint32_t b = *pb, count = num_bits; 635 | for (;;) { 636 | uint32_t try_cnt = num_bits, edges = b ^ (b >> 1); 637 | uint32_t e2 = edges | (edges >> 1), e4 = e2 | (e2 >> 2), add_bits = ~e4; 638 | for (;;) { 639 | uint32_t try_mask = ((1 << try_cnt) - 1) << (num_bits - try_cnt); 640 | if (!(add_bits & try_mask)) { 641 | // No stuff bits needed in try_cnt bits 642 | if (try_cnt >= num_bits) 643 | goto done; 644 | num_bits -= try_cnt; 645 | try_cnt = (num_bits + 1) / 2; 646 | continue; 647 | } 648 | if (add_bits & (1 << (num_bits - 1))) { 649 | // A stuff bit must be inserted prior to the high bit 650 | uint32_t low_mask = (1 << num_bits) - 1, low = b & low_mask; 651 | uint32_t high = (b & ~(low_mask >> 1)) << 1; 652 | b = high ^ low ^ (1 << (num_bits - 1)); 653 | count += 1; 654 | if (num_bits <= 4) 655 | goto done; 656 | num_bits -= 4; 657 | break; 658 | } 659 | // High bit doesn't need stuff bit - accept it, limit try_cnt, retry 660 | num_bits--; 661 | try_cnt /= 2; 662 | } 663 | } 664 | done: 665 | *pb = b; 666 | return count; 667 | } 668 | 669 | // Stuff 'num_bits' bits in '*pb' (optimized for rp2350) 670 | static uint32_t 671 | bitstuff(uint32_t *pb, uint32_t num_bits) 672 | { 673 | if (!IS_RP2350) 674 | return bitstuff_rp2040(pb, num_bits); 675 | uint32_t b = *pb, count = num_bits; 676 | for (;;) { 677 | uint32_t edges = b ^ (b >> 1); 678 | uint32_t e2 = edges | (edges >> 1), e4 = e2 | (e2 >> 2), add_bits = ~e4; 679 | uint32_t mask = (1 << num_bits) - 1, add_masked_bits = add_bits & mask; 680 | if (!add_masked_bits) 681 | // No more stuff bits needed 682 | break; 683 | // Insert a stuff bit 684 | uint32_t stuff_pos = 1 + 31 - __builtin_clz(add_masked_bits); 685 | uint32_t low_mask = (1 << stuff_pos) - 1, low = b & low_mask; 686 | uint32_t high = (b & ~(low_mask >> 1)) << 1; 687 | b = high ^ low ^ (1 << (stuff_pos - 1)); 688 | count += 1; 689 | if (stuff_pos <= 4) 690 | break; 691 | num_bits = stuff_pos - 4; 692 | } 693 | *pb = b; 694 | return count; 695 | } 696 | 697 | // State storage for building bit stuffed transmit messages 698 | struct bitstuffer_s { 699 | uint32_t prev_stuffed, bitpos, *buf; 700 | }; 701 | 702 | // Push 'count' bits of 'data' into stuffer without performing bit stuffing 703 | static void 704 | bs_pushraw(struct bitstuffer_s *bs, uint32_t data, uint32_t count) 705 | { 706 | uint32_t bitpos = bs->bitpos; 707 | uint32_t wp = bitpos / 32, bitused = bitpos % 32, bitavail = 32 - bitused; 708 | uint32_t *fb = &bs->buf[wp]; 709 | if (bitavail >= count) { 710 | fb[0] |= data << (bitavail - count); 711 | } else { 712 | fb[0] |= data >> (count - bitavail); 713 | fb[1] |= data << (32 - (count - bitavail)); 714 | } 715 | bs->bitpos = bitpos + count; 716 | } 717 | 718 | // Push 'count' bits of 'data' into stuffer 719 | static void 720 | bs_push(struct bitstuffer_s *bs, uint32_t data, uint32_t count) 721 | { 722 | data &= (1 << count) - 1; 723 | uint32_t stuf = (bs->prev_stuffed << count) | data; 724 | uint32_t newcount = bitstuff(&stuf, count); 725 | bs_pushraw(bs, stuf, newcount); 726 | bs->prev_stuffed = stuf; 727 | } 728 | 729 | // Pad final word of stuffer with high bits 730 | static uint32_t 731 | bs_finalize(struct bitstuffer_s *bs) 732 | { 733 | uint32_t bitpos = bs->bitpos; 734 | uint32_t words = DIV_ROUND_UP(bitpos, 32); 735 | uint32_t extra = words * 32 - bitpos; 736 | if (extra) 737 | bs->buf[words - 1] |= (1 << extra) - 1; 738 | return words; 739 | } 740 | 741 | 742 | /**************************************************************** 743 | * Transmit state tracking 744 | ****************************************************************/ 745 | 746 | // Transmit states (stored in cd->tx_state) 747 | enum { 748 | TS_IDLE = 0, TS_QUEUED = 1, TS_ACKING_RX = 2, TS_CONFIRM_TX = 3 749 | }; 750 | 751 | // Calculate queue array position from a transmit index 752 | static uint32_t 753 | tx_qpos(struct can2040 *cd, uint32_t pos) 754 | { 755 | return pos % ARRAY_SIZE(cd->tx_queue); 756 | } 757 | 758 | // Queue the next message for transmission in the PIO 759 | static uint32_t 760 | tx_schedule_transmit(struct can2040 *cd) 761 | { 762 | if (cd->tx_state == TS_QUEUED && !pio_tx_did_fail(cd)) 763 | // Already queued or actively transmitting 764 | return 0; 765 | uint32_t tx_pull_pos = cd->tx_pull_pos; 766 | if (readl(&cd->tx_push_pos) == tx_pull_pos) { 767 | // No new messages to transmit 768 | cd->tx_state = TS_IDLE; 769 | pio_signal_clear_txpending(cd); 770 | __DMB(); 771 | if (likely(readl(&cd->tx_push_pos) == tx_pull_pos)) 772 | return SI_TXPENDING; 773 | // Raced with can2040_transmit() - msg is now available for transmit 774 | pio_signal_set_txpending(cd); 775 | } 776 | cd->tx_state = TS_QUEUED; 777 | cd->stats.tx_attempt++; 778 | struct can2040_transmit *qt = &cd->tx_queue[tx_qpos(cd, tx_pull_pos)]; 779 | pio_tx_send(cd, qt->stuffed_data, qt->stuffed_words); 780 | return 0; 781 | } 782 | 783 | // Setup PIO state for ack injection 784 | static void 785 | tx_inject_ack(struct can2040 *cd, uint32_t match_key) 786 | { 787 | cd->tx_state = TS_ACKING_RX; 788 | pio_tx_inject_ack(cd, match_key); 789 | } 790 | 791 | // Check if the current parsed message is feedback from current transmit 792 | static int 793 | tx_check_local_message(struct can2040 *cd) 794 | { 795 | if (cd->tx_state != TS_QUEUED) 796 | return 0; 797 | struct can2040_transmit *qt = &cd->tx_queue[tx_qpos(cd, cd->tx_pull_pos)]; 798 | struct can2040_msg *pm = &cd->parse_msg, *tm = &qt->msg; 799 | if (tm->id == pm->id) { 800 | if (qt->crc != cd->parse_crc || tm->dlc != pm->dlc 801 | || tm->data32[0] != pm->data32[0] || tm->data32[1] != pm->data32[1]) 802 | // Message with same id that differs in content - an error 803 | return -1; 804 | // This is a self transmit 805 | cd->tx_state = TS_CONFIRM_TX; 806 | return 1; 807 | } 808 | return 0; 809 | } 810 | 811 | 812 | /**************************************************************** 813 | * Notification callbacks 814 | ****************************************************************/ 815 | 816 | // Report state flags (stored in cd->report_state) 817 | enum { 818 | RS_NEED_EOF_FLAG = 1<<2, 819 | // States 820 | RS_IDLE = 0, RS_NEED_RX_ACK = 1, RS_NEED_TX_ACK = 2, 821 | RS_NEED_RX_EOF = RS_NEED_RX_ACK | RS_NEED_EOF_FLAG, 822 | RS_NEED_TX_EOF = RS_NEED_TX_ACK | RS_NEED_EOF_FLAG, 823 | }; 824 | 825 | // Report error to calling code (via callback interface) 826 | static void 827 | report_callback_error(struct can2040 *cd, uint32_t error_code) 828 | { 829 | struct can2040_msg msg = {}; 830 | cd->rx_cb(cd, CAN2040_NOTIFY_ERROR | error_code, &msg); 831 | } 832 | 833 | // Report a received message to calling code (via callback interface) 834 | static void 835 | report_callback_rx_msg(struct can2040 *cd) 836 | { 837 | cd->stats.rx_total++; 838 | cd->rx_cb(cd, CAN2040_NOTIFY_RX, &cd->parse_msg); 839 | } 840 | 841 | // Report a message that was successfully transmited (via callback interface) 842 | static void 843 | report_callback_tx_msg(struct can2040 *cd) 844 | { 845 | writel(&cd->tx_pull_pos, cd->tx_pull_pos + 1); 846 | cd->stats.tx_total++; 847 | cd->rx_cb(cd, CAN2040_NOTIFY_TX, &cd->parse_msg); 848 | } 849 | 850 | // EOF phase complete - report message (rx or tx) to calling code 851 | static void 852 | report_handle_eof(struct can2040 *cd) 853 | { 854 | if (cd->report_state & RS_NEED_EOF_FLAG) { // RS_NEED_xX_EOF 855 | // Successfully processed a new message - report to calling code 856 | pio_sync_normal_start_signal(cd); 857 | if (cd->report_state == RS_NEED_TX_EOF) 858 | report_callback_tx_msg(cd); 859 | else 860 | report_callback_rx_msg(cd); 861 | } 862 | cd->report_state = RS_IDLE; 863 | pio_match_clear(cd); 864 | } 865 | 866 | // Check if message being processed is an rx message (not self feedback from tx) 867 | static int 868 | report_is_not_in_tx(struct can2040 *cd) 869 | { 870 | return !(cd->report_state & RS_NEED_TX_ACK); 871 | } 872 | 873 | // Parser found a new message start 874 | static void 875 | report_note_message_start(struct can2040 *cd) 876 | { 877 | pio_irq_set(cd, SI_MAYTX); 878 | } 879 | 880 | // Setup for ack injection (if receiving) or ack confirmation (if transmit) 881 | static int 882 | report_note_crc_start(struct can2040 *cd) 883 | { 884 | int ret = tx_check_local_message(cd); 885 | if (ret) { 886 | if (ret < 0) 887 | return -1; 888 | // This is a self transmit - setup tx eof "matched" signal 889 | cd->report_state = RS_NEED_TX_ACK; 890 | uint32_t bits = (cd->parse_crc_bits << 9) | 0x0ff; 891 | pio_match_check(cd, pio_match_calc_key(bits, cd->parse_crc_pos + 9)); 892 | return 0; 893 | } 894 | 895 | // Setup for ack inject (after rx fifos fully drained) 896 | cd->report_state = RS_NEED_RX_ACK; 897 | pio_signal_set_txpending(cd); 898 | pio_irq_set(cd, SI_MAYTX | SI_TXPENDING); 899 | return 0; 900 | } 901 | 902 | // Parser successfully found matching crc 903 | static void 904 | report_note_crc_success(struct can2040 *cd) 905 | { 906 | if (cd->report_state == RS_NEED_TX_ACK) 907 | // Enable "matched" irq for fast back-to-back transmit scheduling 908 | pio_irq_set(cd, SI_MAYTX | SI_MATCHED); 909 | } 910 | 911 | // Parser found successful ack 912 | static void 913 | report_note_ack_success(struct can2040 *cd) 914 | { 915 | if (cd->report_state == RS_IDLE) 916 | // Got "matched" signal already 917 | return; 918 | // Transition RS_NEED_xX_ACK to RS_NEED_xX_EOF 919 | cd->report_state |= RS_NEED_EOF_FLAG; 920 | } 921 | 922 | // Parser found successful EOF 923 | static void 924 | report_note_eof_success(struct can2040 *cd) 925 | { 926 | if (cd->report_state == RS_IDLE) 927 | // Got "matched" signal already 928 | return; 929 | report_handle_eof(cd); 930 | pio_irq_set(cd, SI_TXPENDING); 931 | } 932 | 933 | // Parser found unexpected data on input 934 | static void 935 | report_note_discarding(struct can2040 *cd) 936 | { 937 | if (cd->report_state != RS_IDLE) { 938 | cd->report_state = RS_IDLE; 939 | pio_match_clear(cd); 940 | } 941 | pio_sync_slow_start_signal(cd); 942 | pio_irq_set(cd, SI_MAYTX | SI_TXPENDING); 943 | } 944 | 945 | // Received PIO "ackdone" irq ("tx" state machine completed ack bit transmit) 946 | static void 947 | report_line_ackdone(struct can2040 *cd) 948 | { 949 | // Setup rx eof "matched" signal for fast rx callbacks 950 | uint32_t bits = (cd->parse_crc_bits << 8) | 0x7f; 951 | pio_match_check(cd, pio_match_calc_key(bits, cd->parse_crc_pos + 8)); 952 | // Schedule next transmit (so it is ready for next frame line arbitration) 953 | uint32_t check_txpending = tx_schedule_transmit(cd); 954 | pio_irq_set(cd, SI_MAYTX | SI_MATCHED | check_txpending); 955 | } 956 | 957 | // Received PIO "matched" irq ("match" state machine detected eof match_key) 958 | static void 959 | report_line_matched(struct can2040 *cd) 960 | { 961 | // A match event indicates an ack and eof are present 962 | if (cd->report_state != RS_IDLE) { 963 | // Transition RS_NEED_xX_ACK to RS_NEED_xX_EOF (if not already there) 964 | cd->report_state |= RS_NEED_EOF_FLAG; 965 | report_handle_eof(cd); 966 | } 967 | // Implement fast back-to-back tx scheduling (if applicable) 968 | uint32_t check_txpending = tx_schedule_transmit(cd); 969 | pio_irq_set(cd, check_txpending); 970 | } 971 | 972 | // Received 10+ passive bits on the line (between 10 and 17 bits) 973 | static void 974 | report_line_maytx(struct can2040 *cd) 975 | { 976 | // Line is idle - may be unexpected EOF, missed ack injection, 977 | // or missed "matched" signal. 978 | if (cd->report_state != RS_IDLE) 979 | report_handle_eof(cd); 980 | uint32_t check_txpending = tx_schedule_transmit(cd); 981 | pio_irq_set(cd, check_txpending); 982 | } 983 | 984 | // Schedule a transmit 985 | static void 986 | report_line_txpending(struct can2040 *cd) 987 | { 988 | uint32_t pio_irqs = pio_irq_get(cd); 989 | if (pio_irqs == (SI_MAYTX | SI_TXPENDING | SI_RX_DATA) 990 | && cd->report_state == RS_NEED_RX_ACK) { 991 | // Ack inject request from report_note_crc_start() 992 | uint32_t mk = pio_match_calc_key(cd->parse_crc_bits, cd->parse_crc_pos); 993 | tx_inject_ack(cd, mk); 994 | pio_irq_set(cd, SI_MAYTX | SI_ACKDONE); 995 | return; 996 | } 997 | // Tx request from can2040_transmit(), report_note_eof_success(), 998 | // or report_note_discarding(). 999 | uint32_t check_txpending = tx_schedule_transmit(cd); 1000 | pio_irq_set(cd, (pio_irqs & ~SI_TXPENDING) | check_txpending); 1001 | } 1002 | 1003 | 1004 | /**************************************************************** 1005 | * Input state tracking 1006 | ****************************************************************/ 1007 | 1008 | // Parsing states (stored in cd->parse_state) 1009 | enum { 1010 | MS_START, MS_HEADER, MS_EXT_HEADER, MS_DATA0, MS_DATA1, 1011 | MS_CRC, MS_ACK, MS_EOF0, MS_EOF1, MS_DISCARD 1012 | }; 1013 | 1014 | // Reset any bits in the incoming parsing state 1015 | static void 1016 | data_state_clear_bits(struct can2040 *cd) 1017 | { 1018 | cd->raw_bit_count = cd->unstuf.stuffed_bits = cd->unstuf.count_stuff = 0; 1019 | } 1020 | 1021 | // Transition to the next parsing state 1022 | static void 1023 | data_state_go_next(struct can2040 *cd, uint32_t state, uint32_t num_bits) 1024 | { 1025 | cd->parse_state = state; 1026 | unstuf_set_count(&cd->unstuf, num_bits); 1027 | } 1028 | 1029 | // Transition to the MS_DISCARD state - drop all bits until 6 passive bits 1030 | static void 1031 | data_state_go_discard(struct can2040 *cd) 1032 | { 1033 | if (pio_rx_check_stall(cd)) { 1034 | // CPU couldn't keep up for some read data - must reset pio state 1035 | data_state_clear_bits(cd); 1036 | pio_sm_setup(cd); 1037 | report_callback_error(cd, 0); 1038 | } 1039 | 1040 | data_state_go_next(cd, MS_DISCARD, 32); 1041 | 1042 | // Clear report state and update hw irqs after transition to MS_DISCARD 1043 | report_note_discarding(cd); 1044 | } 1045 | 1046 | // Note a data parse error and transition to discard state 1047 | static void 1048 | data_state_go_error(struct can2040 *cd) 1049 | { 1050 | cd->stats.parse_error++; 1051 | data_state_go_discard(cd); 1052 | } 1053 | 1054 | // Received six dominant bits on the line 1055 | static void 1056 | data_state_line_error(struct can2040 *cd) 1057 | { 1058 | if (cd->parse_state == MS_DISCARD) 1059 | data_state_go_discard(cd); 1060 | else 1061 | data_state_go_error(cd); 1062 | } 1063 | 1064 | // Received six unexpected passive bits on the line 1065 | static void 1066 | data_state_line_passive(struct can2040 *cd) 1067 | { 1068 | if (cd->parse_state != MS_DISCARD && cd->parse_state != MS_START) { 1069 | // Bitstuff error 1070 | data_state_go_error(cd); 1071 | return; 1072 | } 1073 | 1074 | uint32_t stuffed_bits = unstuf_get_raw(&cd->unstuf); 1075 | uint32_t dom_bits = ~stuffed_bits; 1076 | if (!dom_bits) { 1077 | // Counter overflow in "sync" state machine - reset it 1078 | data_state_clear_bits(cd); 1079 | pio_sm_setup(cd); 1080 | data_state_go_discard(cd); 1081 | return; 1082 | } 1083 | 1084 | // Look for sof after 10 passive bits (most "PIO sync" will produce) 1085 | if (!(dom_bits & 0x3ff)) { 1086 | data_state_go_next(cd, MS_START, 1); 1087 | return; 1088 | } 1089 | 1090 | data_state_go_discard(cd); 1091 | } 1092 | 1093 | // Transition to MS_CRC state - await 16 bits of crc 1094 | static void 1095 | data_state_go_crc(struct can2040 *cd) 1096 | { 1097 | cd->parse_crc &= 0x7fff; 1098 | 1099 | // Calculate raw stuffed bits after crc and crc delimiter 1100 | uint32_t crcstart_bitpos = cd->raw_bit_count - cd->unstuf.count_stuff - 1; 1101 | uint32_t crc_bits = (unstuf_get_raw(&cd->unstuf) << 15) | cd->parse_crc; 1102 | uint32_t crc_bitcount = bitstuff(&crc_bits, 15 + 1) - 1; 1103 | cd->parse_crc_bits = (crc_bits << 1) | 0x01; // Add crc delimiter 1104 | cd->parse_crc_pos = crcstart_bitpos + crc_bitcount + 1; 1105 | 1106 | int ret = report_note_crc_start(cd); 1107 | if (ret) { 1108 | data_state_go_error(cd); 1109 | return; 1110 | } 1111 | data_state_go_next(cd, MS_CRC, 16); 1112 | } 1113 | 1114 | // Transition to MS_DATA0 state (if applicable) - await data bits 1115 | static void 1116 | data_state_go_data(struct can2040 *cd, uint32_t id, uint32_t data) 1117 | { 1118 | if (data & (0x03 << 4)) { 1119 | // Not a supported header 1120 | data_state_go_discard(cd); 1121 | return; 1122 | } 1123 | cd->parse_msg.data32[0] = cd->parse_msg.data32[1] = 0; 1124 | uint32_t dlc = data & 0x0f; 1125 | cd->parse_msg.dlc = dlc; 1126 | if (data & (1 << 6)) { 1127 | dlc = 0; 1128 | id |= CAN2040_ID_RTR; 1129 | } 1130 | cd->parse_msg.id = id; 1131 | if (dlc) 1132 | data_state_go_next(cd, MS_DATA0, dlc >= 4 ? 32 : dlc * 8); 1133 | else 1134 | data_state_go_crc(cd); 1135 | } 1136 | 1137 | // Handle reception of first bit of header (after start-of-frame (SOF)) 1138 | static void 1139 | data_state_update_start(struct can2040 *cd, uint32_t data) 1140 | { 1141 | cd->parse_msg.id = data; 1142 | report_note_message_start(cd); 1143 | data_state_go_next(cd, MS_HEADER, 17); 1144 | } 1145 | 1146 | // Handle reception of next 17 header bits 1147 | static void 1148 | data_state_update_header(struct can2040 *cd, uint32_t data) 1149 | { 1150 | data |= cd->parse_msg.id << 17; 1151 | if ((data & 0x60) == 0x60) { 1152 | // Extended header 1153 | cd->parse_msg.id = data; 1154 | data_state_go_next(cd, MS_EXT_HEADER, 20); 1155 | return; 1156 | } 1157 | cd->parse_crc = crc_bytes(0, data, 3); 1158 | data_state_go_data(cd, (data >> 7) & 0x7ff, data); 1159 | } 1160 | 1161 | // Handle reception of additional 20 bits of "extended header" 1162 | static void 1163 | data_state_update_ext_header(struct can2040 *cd, uint32_t data) 1164 | { 1165 | uint32_t hdr1 = cd->parse_msg.id; 1166 | uint32_t crc = crc_bytes(0, hdr1 >> 4, 2); 1167 | cd->parse_crc = crc_bytes(crc, ((hdr1 & 0x0f) << 20) | data, 3); 1168 | uint32_t id = (((hdr1 << 11) & 0x1ffc0000) | ((hdr1 << 13) & 0x3e000) 1169 | | (data >> 7) | CAN2040_ID_EFF); 1170 | data_state_go_data(cd, id, data); 1171 | } 1172 | 1173 | // Handle reception of first 1-4 bytes of data content 1174 | static void 1175 | data_state_update_data0(struct can2040 *cd, uint32_t data) 1176 | { 1177 | uint32_t dlc = cd->parse_msg.dlc, bits = dlc >= 4 ? 32 : dlc * 8; 1178 | cd->parse_crc = crc_bytes(cd->parse_crc, data, dlc); 1179 | cd->parse_msg.data32[0] = __builtin_bswap32(data << (32 - bits)); 1180 | if (dlc > 4) 1181 | data_state_go_next(cd, MS_DATA1, dlc >= 8 ? 32 : (dlc - 4) * 8); 1182 | else 1183 | data_state_go_crc(cd); 1184 | } 1185 | 1186 | // Handle reception of bytes 5-8 of data content 1187 | static void 1188 | data_state_update_data1(struct can2040 *cd, uint32_t data) 1189 | { 1190 | uint32_t dlc = cd->parse_msg.dlc, bits = dlc >= 8 ? 32 : (dlc - 4) * 8; 1191 | cd->parse_crc = crc_bytes(cd->parse_crc, data, dlc - 4); 1192 | cd->parse_msg.data32[1] = __builtin_bswap32(data << (32 - bits)); 1193 | data_state_go_crc(cd); 1194 | } 1195 | 1196 | // Handle reception of 16 bits of message CRC (15 crc bits + crc delimiter) 1197 | static void 1198 | data_state_update_crc(struct can2040 *cd, uint32_t data) 1199 | { 1200 | if (((cd->parse_crc << 1) | 1) != data) { 1201 | data_state_go_error(cd); 1202 | return; 1203 | } 1204 | 1205 | report_note_crc_success(cd); 1206 | unstuf_clear_state(&cd->unstuf); 1207 | data_state_go_next(cd, MS_ACK, 2); 1208 | } 1209 | 1210 | // Handle reception of 2 bits of ack phase (ack, ack delimiter) 1211 | static void 1212 | data_state_update_ack(struct can2040 *cd, uint32_t data) 1213 | { 1214 | if (data != 0x01) { 1215 | // Undo unstuf_clear_state() for correct SOF detection in 1216 | // data_state_line_passive() 1217 | unstuf_restore_state(&cd->unstuf, (cd->parse_crc_bits << 2) | data); 1218 | 1219 | data_state_go_error(cd); 1220 | return; 1221 | } 1222 | report_note_ack_success(cd); 1223 | data_state_go_next(cd, MS_EOF0, 4); 1224 | } 1225 | 1226 | // Handle reception of first four end-of-frame (EOF) bits 1227 | static void 1228 | data_state_update_eof0(struct can2040 *cd, uint32_t data) 1229 | { 1230 | if (data != 0x0f || pio_rx_check_stall(cd)) { 1231 | data_state_go_error(cd); 1232 | return; 1233 | } 1234 | unstuf_clear_state(&cd->unstuf); 1235 | data_state_go_next(cd, MS_EOF1, 5); 1236 | } 1237 | 1238 | // Handle reception of end-of-frame (EOF) bits 5-7 and first two IFS bits 1239 | static void 1240 | data_state_update_eof1(struct can2040 *cd, uint32_t data) 1241 | { 1242 | if (data == 0x1f) { 1243 | // Success 1244 | report_note_eof_success(cd); 1245 | data_state_go_next(cd, MS_START, 1); 1246 | } else if (data >= 0x1c || (data >= 0x18 && report_is_not_in_tx(cd))) { 1247 | // Message fully transmitted - followed by "overload frame" 1248 | report_note_eof_success(cd); 1249 | data_state_go_discard(cd); 1250 | } else { 1251 | data_state_go_error(cd); 1252 | } 1253 | } 1254 | 1255 | // Handle data received while in MS_DISCARD state 1256 | static void 1257 | data_state_update_discard(struct can2040 *cd, uint32_t data) 1258 | { 1259 | data_state_go_discard(cd); 1260 | } 1261 | 1262 | // Update parsing state after reading the bits of the current field 1263 | static void 1264 | data_state_update(struct can2040 *cd, uint32_t data) 1265 | { 1266 | switch (cd->parse_state) { 1267 | case MS_START: data_state_update_start(cd, data); break; 1268 | case MS_HEADER: data_state_update_header(cd, data); break; 1269 | case MS_EXT_HEADER: data_state_update_ext_header(cd, data); break; 1270 | case MS_DATA0: data_state_update_data0(cd, data); break; 1271 | case MS_DATA1: data_state_update_data1(cd, data); break; 1272 | case MS_CRC: data_state_update_crc(cd, data); break; 1273 | case MS_ACK: data_state_update_ack(cd, data); break; 1274 | case MS_EOF0: data_state_update_eof0(cd, data); break; 1275 | case MS_EOF1: data_state_update_eof1(cd, data); break; 1276 | case MS_DISCARD: data_state_update_discard(cd, data); break; 1277 | } 1278 | } 1279 | 1280 | 1281 | /**************************************************************** 1282 | * Input processing 1283 | ****************************************************************/ 1284 | 1285 | // Process incoming data from PIO "rx" state machine 1286 | static void 1287 | process_rx(struct can2040 *cd, uint32_t rx_data) 1288 | { 1289 | unstuf_add_bits(&cd->unstuf, rx_data, PIO_RX_WAKE_BITS); 1290 | cd->raw_bit_count += PIO_RX_WAKE_BITS; 1291 | 1292 | // undo bit stuffing 1293 | for (;;) { 1294 | int ret = unstuf_pull_bits(&cd->unstuf); 1295 | if (likely(ret > 0)) { 1296 | // Need more data 1297 | break; 1298 | } else if (likely(!ret)) { 1299 | // Pulled the next field - process it 1300 | data_state_update(cd, cd->unstuf.unstuffed_bits); 1301 | } else { 1302 | if (ret == -1) 1303 | // 6 consecutive high bits 1304 | data_state_line_passive(cd); 1305 | else 1306 | // 6 consecutive low bits 1307 | data_state_line_error(cd); 1308 | } 1309 | } 1310 | } 1311 | 1312 | // Main API irq notification function 1313 | void 1314 | can2040_pio_irq_handler(struct can2040 *cd) 1315 | { 1316 | pio_hw_t *pio_hw = cd->pio_hw; 1317 | uint32_t ints = pio_hw->ints0; 1318 | while (likely(ints & SI_RX_DATA)) { 1319 | uint32_t rx_data = pio_hw->rxf[SM_RX]; 1320 | process_rx(cd, rx_data); 1321 | ints = pio_hw->ints0; 1322 | if (likely(!ints)) 1323 | return; 1324 | } 1325 | 1326 | if (ints & SI_ACKDONE) 1327 | // Ack of received message completed successfully 1328 | report_line_ackdone(cd); 1329 | else if (ints & SI_MATCHED) 1330 | // Transmit message completed successfully 1331 | report_line_matched(cd); 1332 | else if (ints & SI_MAYTX) 1333 | // Bus is idle, but not all bits may have been flushed yet 1334 | report_line_maytx(cd); 1335 | else if (ints & SI_TXPENDING) 1336 | // Schedule a transmit 1337 | report_line_txpending(cd); 1338 | } 1339 | 1340 | 1341 | /**************************************************************** 1342 | * Transmit queuing 1343 | ****************************************************************/ 1344 | 1345 | // API function to check if transmit space available 1346 | int 1347 | can2040_check_transmit(struct can2040 *cd) 1348 | { 1349 | uint32_t tx_pull_pos = readl(&cd->tx_pull_pos); 1350 | uint32_t tx_push_pos = cd->tx_push_pos; 1351 | uint32_t pending = tx_push_pos - tx_pull_pos; 1352 | return pending < ARRAY_SIZE(cd->tx_queue); 1353 | } 1354 | 1355 | // API function to transmit a message 1356 | int 1357 | can2040_transmit(struct can2040 *cd, struct can2040_msg *msg) 1358 | { 1359 | uint32_t tx_pull_pos = readl(&cd->tx_pull_pos); 1360 | uint32_t tx_push_pos = cd->tx_push_pos; 1361 | uint32_t pending = tx_push_pos - tx_pull_pos; 1362 | if (pending >= ARRAY_SIZE(cd->tx_queue)) 1363 | // Tx queue full 1364 | return -1; 1365 | 1366 | // Copy msg into transmit queue 1367 | struct can2040_transmit *qt = &cd->tx_queue[tx_qpos(cd, tx_push_pos)]; 1368 | uint32_t id = msg->id; 1369 | if (id & CAN2040_ID_EFF) 1370 | qt->msg.id = id & ~0x20000000; 1371 | else 1372 | qt->msg.id = id & (CAN2040_ID_RTR | 0x7ff); 1373 | qt->msg.dlc = msg->dlc & 0x0f; 1374 | uint32_t data_len = qt->msg.dlc > 8 ? 8 : qt->msg.dlc; 1375 | if (qt->msg.id & CAN2040_ID_RTR) 1376 | data_len = 0; 1377 | qt->msg.data32[0] = qt->msg.data32[1] = 0; 1378 | memcpy(qt->msg.data, msg->data, data_len); 1379 | 1380 | // Calculate crc and stuff bits 1381 | uint32_t crc = 0; 1382 | memset(qt->stuffed_data, 0, sizeof(qt->stuffed_data)); 1383 | struct bitstuffer_s bs = { 1, 0, qt->stuffed_data }; 1384 | uint32_t edlc = qt->msg.dlc | (qt->msg.id & CAN2040_ID_RTR ? 0x40 : 0); 1385 | if (qt->msg.id & CAN2040_ID_EFF) { 1386 | // Extended header 1387 | uint32_t id = qt->msg.id; 1388 | uint32_t h1 = ((id & 0x1ffc0000) >> 11) | 0x60 | ((id & 0x3e000) >> 13); 1389 | uint32_t h2 = ((id & 0x1fff) << 7) | edlc; 1390 | crc = crc_bytes(crc, h1 >> 4, 2); 1391 | crc = crc_bytes(crc, ((h1 & 0x0f) << 20) | h2, 3); 1392 | bs_push(&bs, h1, 19); 1393 | bs_push(&bs, h2, 20); 1394 | } else { 1395 | // Standard header 1396 | uint32_t hdr = ((qt->msg.id & 0x7ff) << 7) | edlc; 1397 | crc = crc_bytes(crc, hdr, 3); 1398 | bs_push(&bs, hdr, 19); 1399 | } 1400 | uint32_t i; 1401 | for (i=0; imsg.data[i]; 1403 | crc = crc_byte(crc, v); 1404 | bs_push(&bs, v, 8); 1405 | } 1406 | qt->crc = crc & 0x7fff; 1407 | bs_push(&bs, qt->crc, 15); 1408 | bs_pushraw(&bs, 1, 1); 1409 | qt->stuffed_words = bs_finalize(&bs); 1410 | 1411 | // Submit 1412 | writel(&cd->tx_push_pos, tx_push_pos + 1); 1413 | 1414 | // Wakeup if in TS_IDLE state 1415 | __DMB(); 1416 | pio_signal_set_txpending(cd); 1417 | 1418 | return 0; 1419 | } 1420 | 1421 | 1422 | /**************************************************************** 1423 | * Setup 1424 | ****************************************************************/ 1425 | 1426 | // API function to initialize can2040 code 1427 | void 1428 | can2040_setup(struct can2040 *cd, uint32_t pio_num) 1429 | { 1430 | memset(cd, 0, sizeof(*cd)); 1431 | cd->pio_num = !!pio_num; 1432 | cd->pio_hw = cd->pio_num ? pio1_hw : pio0_hw; 1433 | #if IS_RP2350 1434 | if (pio_num == 2) { 1435 | cd->pio_num = pio_num; 1436 | cd->pio_hw = pio2_hw; 1437 | } 1438 | #endif 1439 | } 1440 | 1441 | // API function to configure callback 1442 | void 1443 | can2040_callback_config(struct can2040 *cd, can2040_rx_cb rx_cb) 1444 | { 1445 | cd->rx_cb = rx_cb; 1446 | } 1447 | 1448 | // API function to start CANbus interface 1449 | void 1450 | can2040_start(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate 1451 | , uint32_t gpio_rx, uint32_t gpio_tx) 1452 | { 1453 | cd->gpio_rx = gpio_rx; 1454 | cd->gpio_tx = gpio_tx; 1455 | data_state_clear_bits(cd); 1456 | pio_setup(cd, sys_clock, bitrate); 1457 | data_state_go_discard(cd); 1458 | } 1459 | 1460 | // API function to stop can2040 code 1461 | void 1462 | can2040_stop(struct can2040 *cd) 1463 | { 1464 | pio_irq_disable(cd); 1465 | pio_sm_setup(cd); 1466 | } 1467 | 1468 | // API function to access can2040 statistics 1469 | void 1470 | can2040_get_statistics(struct can2040 *cd, struct can2040_stats *stats) 1471 | { 1472 | for (;;) { 1473 | memcpy(stats, &cd->stats, sizeof(*stats)); 1474 | if (memcmp(stats, &cd->stats, sizeof(*stats)) == 0) 1475 | // Successfully copied data 1476 | return; 1477 | // Raced with irq handler update - retry copy 1478 | } 1479 | } 1480 | -------------------------------------------------------------------------------- /src/can2040.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAN2040_H 2 | #define _CAN2040_H 3 | 4 | #include // uint32_t 5 | 6 | struct can2040_msg { 7 | uint32_t id; 8 | uint32_t dlc; 9 | union { 10 | uint8_t data[8]; 11 | uint32_t data32[2]; 12 | }; 13 | }; 14 | 15 | enum { 16 | CAN2040_ID_RTR = 1<<30, 17 | CAN2040_ID_EFF = 1<<31, 18 | }; 19 | 20 | enum { 21 | CAN2040_NOTIFY_RX = 1<<20, 22 | CAN2040_NOTIFY_TX = 1<<21, 23 | CAN2040_NOTIFY_ERROR = 1<<23, 24 | }; 25 | struct can2040; 26 | typedef void (*can2040_rx_cb)(struct can2040 *cd, uint32_t notify 27 | , struct can2040_msg *msg); 28 | 29 | struct can2040_stats { 30 | uint32_t rx_total, tx_total; 31 | uint32_t tx_attempt; 32 | uint32_t parse_error; 33 | }; 34 | 35 | void can2040_setup(struct can2040 *cd, uint32_t pio_num); 36 | void can2040_callback_config(struct can2040 *cd, can2040_rx_cb rx_cb); 37 | void can2040_start(struct can2040 *cd, uint32_t sys_clock, uint32_t bitrate 38 | , uint32_t gpio_rx, uint32_t gpio_tx); 39 | void can2040_stop(struct can2040 *cd); 40 | void can2040_get_statistics(struct can2040 *cd, struct can2040_stats *stats); 41 | void can2040_pio_irq_handler(struct can2040 *cd); 42 | int can2040_check_transmit(struct can2040 *cd); 43 | int can2040_transmit(struct can2040 *cd, struct can2040_msg *msg); 44 | 45 | 46 | /**************************************************************** 47 | * Internal definitions 48 | ****************************************************************/ 49 | 50 | struct can2040_bitunstuffer { 51 | uint32_t stuffed_bits, count_stuff; 52 | uint32_t unstuffed_bits, count_unstuff; 53 | }; 54 | 55 | struct can2040_transmit { 56 | struct can2040_msg msg; 57 | uint32_t crc, stuffed_words, stuffed_data[5]; 58 | }; 59 | 60 | struct can2040 { 61 | // Setup 62 | uint32_t pio_num; 63 | void *pio_hw; 64 | uint32_t gpio_rx, gpio_tx; 65 | can2040_rx_cb rx_cb; 66 | struct can2040_stats stats; 67 | 68 | // Bit unstuffing 69 | struct can2040_bitunstuffer unstuf; 70 | uint32_t raw_bit_count; 71 | 72 | // Input data state 73 | uint32_t parse_state; 74 | uint32_t parse_crc, parse_crc_bits, parse_crc_pos; 75 | struct can2040_msg parse_msg; 76 | 77 | // Reporting 78 | uint32_t report_state; 79 | 80 | // Transmits 81 | uint32_t tx_state; 82 | uint32_t tx_pull_pos, tx_push_pos; 83 | struct can2040_transmit tx_queue[4]; 84 | }; 85 | 86 | #endif // can2040.h 87 | --------------------------------------------------------------------------------