├── .cproject ├── .gitignore ├── .gitmodules ├── .project ├── .settings ├── language.settings.xml └── org.eclipse.cdt.managedbuilder.core.prefs ├── LICENSE ├── Makefile ├── TODO ├── can.c ├── can.h ├── can_queue.c ├── can_queue.h ├── config.h ├── external ├── pcan_usbpro_fw.h ├── pcan_usbpro_sizeof_rec.c └── pcan_usbpro_sizeof_rec.h ├── main.c ├── pcan_stm32.cbp ├── ppro_protocol.c ├── ppro_protocol.h ├── ppro_usb.c ├── ppro_usb.h ├── ppro_usb_descr.c ├── ppro_usb_descr.h ├── stm32f4-discovery.ld ├── stm32f407ve.cfg ├── stm32f407vet6.ld ├── systime.c ├── systime.h └── tests ├── simple_pingpong.py └── socketcan ├── __init__.py ├── canmessage.py ├── canmessage.pyc └── cansocket.py /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | *.d 7 | 8 | # Generated files 9 | generated.*.ld 10 | 11 | # Codeblocks files 12 | *.depend 13 | *.layout 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | Release**/ 39 | Debug**/ 40 | 41 | # Debug files 42 | *.dSYM/ 43 | 44 | Debug 45 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libopencm3"] 2 | path = libopencm3 3 | url = https://github.com/libopencm3/libopencm3.git 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | candle2 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 24 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 25 | 26 | 27 | -------------------------------------------------------------------------------- /.settings/language.settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.managedbuilder.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/CPATH/delimiter=\: 3 | environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/CPATH/operation=remove 4 | environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/C_INCLUDE_PATH/delimiter=\: 5 | environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/C_INCLUDE_PATH/operation=remove 6 | environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/append=true 7 | environment/buildEnvironmentInclude/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/appendContributed=true 8 | environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/LIBRARY_PATH/delimiter=\: 9 | environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/LIBRARY_PATH/operation=remove 10 | environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/append=true 11 | environment/buildEnvironmentLibrary/ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.117086309/appendContributed=true 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #DEVICE = stm32f407vg 2 | DEVICE = stm32f407ve 3 | OPENCM3_DIR = ./libopencm3 4 | OBJS += main.o can.o can_queue.o ppro_protocol.o ppro_usb.o ppro_usb_descr.o systime.o external/pcan_usbpro_sizeof_rec.o 5 | 6 | CFLAGS += -Os -ggdb3 -DDISABLE_VBUS_SENSE 7 | CPPFLAGS += -MD 8 | LDFLAGS += -static -nostartfiles 9 | LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group 10 | 11 | include $(OPENCM3_DIR)/mk/genlink-config.mk 12 | include $(OPENCM3_DIR)/mk/gcc-config.mk 13 | 14 | .PHONY: clean all 15 | 16 | all: binary.elf binary.hex 17 | 18 | clean: 19 | $(Q)$(RM) -rf binary.* *.o 20 | 21 | include $(OPENCM3_DIR)/mk/genlink-rules.mk 22 | include $(OPENCM3_DIR)/mk/gcc-rules.mk 23 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - test timestamp handling 2 | - handle can messages in interrupt for better timestamp accuracy 3 | - validate windows drivers are installed automatically, at least when using USB_HS mode 4 | - use usb tx complete callback to allow for parallel message handling on both channels 5 | - do stress tests (real can traces, canoe) 6 | - write a README, document everything 7 | - make a linux test suite (connect can1 & can2 in hardware) 8 | - implement can error handling 9 | 10 | - implement error frame generation (how?) 11 | - add our own usb protocol -------------------------------------------------------------------------------- /can.c: -------------------------------------------------------------------------------- 1 | /* 2 | * can.c 3 | * 4 | * Created on: 25.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #include "can.h" 9 | #include "systime.h" 10 | #include "can_queue.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static can_rx_callback_t rx_callback = 0; 18 | 19 | typedef struct { 20 | led_mode_t mode; 21 | uint32_t t_next; 22 | uint8_t state; 23 | } led_status_t; 24 | 25 | static led_status_t led_status[2]; 26 | 27 | typedef struct { 28 | can_queue_item_t txqueue_items[TX_QUEUE_LENGTH]; 29 | can_queue_t tx_queue; 30 | can_queue_t tx_message_pool; 31 | } channel_data_t; 32 | 33 | static channel_data_t channel_data[2]; 34 | 35 | static void reset_can(uint32_t can) { 36 | // set reset bit in master control register 37 | CAN_MCR(can) |= CAN_MCR_RESET; 38 | // wait for reset bit to become zero again (reset complete?) 39 | while (CAN_MCR(can) & CAN_MCR_RESET); 40 | } 41 | 42 | static int candle_can_goto_init_mode(uint32_t can) { 43 | // set initialization request bit in MCR (must also clear SLEEP bit) 44 | CAN_MCR(can) &= ~CAN_MCR_SLEEP; 45 | CAN_MCR(can) |= CAN_MCR_INRQ; 46 | 47 | // wait for initialization mode confirmation 48 | for (int i=0; i<0xFFFF; i++) { 49 | if ((CAN_MSR(can) & CAN_MSR_INAK) == CAN_MSR_INAK) { 50 | return 0; // controller is in initialization mode 51 | } 52 | } 53 | 54 | return -1; // timeout waiting for INAK flag 55 | } 56 | 57 | static int candle_is_in_init_mode(uint32_t can) { 58 | return (CAN_MCR(can) & CAN_MCR_INRQ) && (CAN_MSR(can) & CAN_MSR_INAK); 59 | } 60 | 61 | static int init_can(uint32_t can) { 62 | 63 | if (candle_can_goto_init_mode(can)<0) { 64 | return -1; 65 | } 66 | 67 | // use automatic bus-off management 68 | // (leave bus-off state automatically if can status seems to be okay) 69 | CAN_MCR(can) |= CAN_MCR_ABOM; 70 | 71 | // lock full rx fifo (throw away newer messages) 72 | CAN_MCR(can) |= CAN_MCR_RFLM; 73 | 74 | // use tx mailboxes in fifo mode 75 | CAN_MCR(can) |= CAN_MCR_TXFP; 76 | 77 | return 0; 78 | } 79 | 80 | static int candle_can_goto_normal_mode(uint32_t can) { 81 | // clear initialization request bit 82 | CAN_MCR(can) &= ~CAN_MCR_INRQ; 83 | 84 | for (int i=0; i<0x0FFFFF; i++) { 85 | if ((CAN_MSR(can) & CAN_MSR_INAK) == 0) { 86 | return 0; // controller is not in initialization mode any more 87 | } 88 | } 89 | 90 | return -1; // timeout waiting for INAK flag to become zero 91 | } 92 | 93 | static void clear_tx_queue(uint8_t channel) { 94 | assert((channel==0) || (channel==1)); 95 | channel_data_t *data = &channel_data[channel]; 96 | 97 | can_queue_init(&data->tx_queue); 98 | can_queue_init(&data->tx_message_pool); 99 | memset(data->txqueue_items, 0, sizeof(data->txqueue_items)); 100 | for (int i=0; itx_message_pool, &data->txqueue_items[i]); 102 | } 103 | } 104 | 105 | void candle_can_init(void) { 106 | rx_callback = 0; 107 | memset(led_status, 0, sizeof(led_status)); 108 | 109 | clear_tx_queue(0); 110 | clear_tx_queue(1); 111 | 112 | // enable led outputs 113 | rcc_periph_clock_enable(RCC_GPIOD); 114 | gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15); 115 | 116 | // enable can1 peripheral 117 | rcc_periph_clock_enable(RCC_GPIOD); 118 | rcc_periph_clock_enable(RCC_CAN1); 119 | gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO0 | GPIO1); 120 | gpio_set_output_options(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO0 | GPIO1); 121 | gpio_set_af(GPIOD, GPIO_AF9, GPIO0 | GPIO1); 122 | reset_can(CAN1); 123 | init_can(CAN1); 124 | 125 | // enable can1 transceiver 126 | rcc_periph_clock_enable(RCC_GPIOC); 127 | gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6); 128 | gpio_clear(GPIOC, GPIO6); 129 | 130 | // enable can2 peripheral 131 | rcc_periph_clock_enable(RCC_GPIOB); 132 | rcc_periph_clock_enable(RCC_CAN2); 133 | gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12 | GPIO13); 134 | gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO12 | GPIO13); 135 | gpio_set_af(GPIOB, GPIO_AF9, GPIO12 | GPIO13); 136 | reset_can(CAN2); 137 | init_can(CAN2); 138 | 139 | // enable can2 transceiver 140 | rcc_periph_clock_enable(RCC_GPIOD); 141 | gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO11); 142 | gpio_clear(GPIOD, GPIO11); 143 | 144 | // init filter banks 145 | CAN_FMR(CAN1) |= CAN_FMR_FINIT; // switch filter banks to init mode 146 | 147 | // configure usage of 14 filter banks for can1 and 14 banks for can2 148 | CAN_FMR(CAN1) &= ~CAN_FMR_CAN2SB_MASK; 149 | CAN_FMR(CAN1) |= (14<channel==0) || (msg->channel==1) ); 196 | channel_data_t *data = &channel_data[msg->channel]; 197 | can_queue_item_t *item; 198 | 199 | if (data->tx_message_pool.count==0) { 200 | // no free slot in tx queue, try sending out messages 201 | candle_can_handle_tx_queue(msg->channel); 202 | } 203 | 204 | if (can_queue_pop_front(&data->tx_message_pool, &item)) { 205 | item->msg = *msg; 206 | can_queue_push_back(&data->tx_queue, item); 207 | 208 | // try to send message immediately, if possible 209 | candle_can_handle_tx_queue(msg->channel); 210 | } else { 211 | // still no free slot in tx queue 212 | } 213 | } 214 | 215 | static uint32_t find_empty_mailbox(uint32_t can) { 216 | if ((CAN_TSR(can) & CAN_TSR_TME0) == CAN_TSR_TME0) { 217 | return CAN_MBOX0; 218 | } else if ((CAN_TSR(can) & CAN_TSR_TME1) == CAN_TSR_TME1) { 219 | return CAN_MBOX1; 220 | } else if ((CAN_TSR(can) & CAN_TSR_TME2) == CAN_TSR_TME2) { 221 | return CAN_MBOX2; 222 | } else { 223 | return 0; 224 | } 225 | } 226 | 227 | static void send_can_message(uint32_t can, uint32_t mailbox, can_message_t *msg) { 228 | uint32_t id_and_flags = msg->id_and_flags; 229 | 230 | if (id_and_flags & can_flag_extid) { 231 | CAN_TIxR(can, mailbox) = CAN_TIxR_IDE | ((id_and_flags & 0x1FFFFFFF) << CAN_TIxR_EXID_SHIFT); 232 | } else { 233 | CAN_TIxR(can, mailbox) = (id_and_flags & 0x7FF) << CAN_TIxR_STID_SHIFT; 234 | } 235 | 236 | if (id_and_flags & can_flag_rtr) { 237 | CAN_TIxR(can, mailbox) |= CAN_TIxR_RTR; 238 | } 239 | 240 | CAN_TDTxR(can, mailbox) &= ~CAN_TDTxR_DLC_MASK; 241 | CAN_TDTxR(can, mailbox) |= (msg->dlc & CAN_TDTxR_DLC_MASK); 242 | CAN_TDHxR(can, mailbox) = msg->data32[1]; 243 | CAN_TDLxR(can, mailbox) = msg->data32[0]; 244 | CAN_TIxR(can, mailbox) |= CAN_TIxR_TXRQ; 245 | } 246 | 247 | static void candle_can_handle_tx_queue(uint8_t channel) { 248 | assert( (channel==0) || (channel==1) ); 249 | uint32_t can = (channel==0) ? CAN1 : CAN2; 250 | channel_data_t *data = &channel_data[channel]; 251 | 252 | if (data->tx_queue.count>0) { 253 | uint32_t mailbox = find_empty_mailbox(can); 254 | if (mailbox) { 255 | can_queue_item_t *item; 256 | if (can_queue_pop_front(&data->tx_queue, &item)) { 257 | send_can_message(can, mailbox, &item->msg); 258 | 259 | // return message buffer to pool queue 260 | can_queue_push_back(&data->tx_message_pool, item); 261 | } 262 | } 263 | } 264 | } 265 | 266 | static void candle_can_handle_fifo(uint8_t channel, uint32_t fifo) { 267 | assert( (channel==0) || (channel==1) ); 268 | uint32_t can = (channel==0) ? CAN1 : CAN2; 269 | 270 | can_message_t msg; 271 | msg.channel = channel; 272 | msg.timestamp = get_time_us32(); 273 | 274 | uint32_t RIR = CAN_RIxR(can, fifo); 275 | 276 | if (RIR & CAN_RIxR_IDE) { 277 | msg.id_and_flags = can_flag_extid | ((RIR >> CAN_RIxR_EXID_SHIFT) & CAN_RIxR_EXID_MASK); 278 | } else { 279 | msg.id_and_flags = (RIR >> CAN_RIxR_STID_SHIFT) & CAN_RIxR_STID_MASK; 280 | } 281 | 282 | if (RIR & CAN_RIxR_RTR) { 283 | msg.id_and_flags |= can_flag_rtr; 284 | } 285 | 286 | msg.dlc = CAN_RDTxR(can, fifo) & CAN_RDTxR_DLC_MASK; 287 | msg.data32[0] = CAN_RDLxR(can, fifo); 288 | msg.data32[1] = CAN_RDHxR(can, fifo); 289 | 290 | can_notify_message(&msg); 291 | } 292 | 293 | static void candle_can_poll_rx(uint8_t channel) { 294 | assert( (channel==0) || (channel==1) ); 295 | uint32_t can = (channel==0) ? CAN1 : CAN2; 296 | 297 | while (CAN_RF0R(can) & CAN_RF0R_FMP0_MASK) { // there are messages waiting in FIFO0 298 | candle_can_handle_fifo(channel, CAN_FIFO0); 299 | CAN_RF0R(can) |= CAN_RF1R_RFOM1; // release fifo message 300 | } 301 | } 302 | 303 | void candle_can_set_bitrate(uint8_t channel, uint16_t brp, uint8_t tseg1, uint8_t tseg2, uint8_t sjw) { 304 | uint32_t can = (channel==0) ? CAN1 : CAN2; 305 | 306 | int was_in_init_mode = candle_is_in_init_mode(can); 307 | if (!was_in_init_mode) { 308 | candle_can_goto_init_mode(can); 309 | } 310 | 311 | uint32_t cfg = CAN_BTR(can); 312 | 313 | if (sjw>4) { sjw = 4; } 314 | cfg &= ~CAN_BTR_SJW_MASK; 315 | cfg |= ((sjw-1)<8) { tseg2 = 8; } 318 | cfg &= ~CAN_BTR_TS2_MASK; 319 | cfg |= ((tseg2-1)<16) { tseg1 = 16; } 322 | cfg &= ~CAN_BTR_TS1_MASK; 323 | cfg |= ((tseg1-1)<1024) { brp = 1024; } 326 | cfg &= ~CAN_BTR_BRP_MASK; 327 | cfg |= (brp-1); 328 | 329 | CAN_BTR(can) = cfg; 330 | 331 | if (!was_in_init_mode) { 332 | candle_can_goto_normal_mode(can); 333 | } 334 | } 335 | 336 | void candle_can_set_silent(uint8_t channel, uint8_t silent_mode) { 337 | uint32_t can = (channel==0) ? CAN1 : CAN2; 338 | 339 | int was_in_init_mode = candle_is_in_init_mode(can); 340 | if (!was_in_init_mode) { 341 | candle_can_goto_init_mode(can); 342 | } 343 | 344 | if (silent_mode) { 345 | CAN_BTR(can) = CAN_BTR(can) | 0x80000000; // set SILM bit 346 | } else { 347 | CAN_BTR(can) = CAN_BTR(can) & 0x7FFFFFFF; // clear SILM bit 348 | } 349 | 350 | if (!was_in_init_mode) { 351 | candle_can_goto_normal_mode(can); 352 | } 353 | } 354 | 355 | void candle_can_set_bus_active(uint8_t channel, uint16_t mode) { 356 | uint32_t can = (channel==0) ? CAN1 : CAN2; 357 | if (mode) { 358 | candle_can_goto_normal_mode(can); 359 | } else { 360 | candle_can_goto_init_mode(can); 361 | } 362 | } 363 | 364 | uint8_t candle_can_calc_message_len(const can_message_t *msg) { 365 | // NOTICE this ignores stuff bits and is therefore incorrect 366 | // to calculate the number of stuff bits, we would have to construct 367 | // the whole can frame which would probably be a lot of overhead 368 | if (msg->id_and_flags & can_flag_extid) { 369 | return 64 + 8*msg->dlc + 3; 370 | } else { 371 | return 44 + 8*msg->dlc + 3; 372 | } 373 | } 374 | 375 | 376 | void candle_can_set_led_mode(uint8_t channel, led_mode_t mode, uint32_t timeout) { 377 | (void)timeout; 378 | if (channel < 2) { 379 | led_status[channel].mode = mode; 380 | led_status[channel].t_next = get_time_ms(); 381 | } 382 | } 383 | 384 | static void set_led_state(uint8_t channel, uint8_t state) { 385 | uint16_t pin = (channel==0) ? GPIO12 : GPIO14; 386 | if (state) { 387 | gpio_set(GPIOD, pin); 388 | } else { 389 | gpio_clear(GPIOD, pin); 390 | } 391 | } 392 | 393 | void can_poll_leds(void) { 394 | 395 | uint32_t now = get_time_ms(); 396 | 397 | for (uint8_t i=0; i<2; i++) { 398 | led_status_t *status = &led_status[i]; 399 | 400 | if ( status->t_next && (status->t_next <= now)) { 401 | 402 | switch (status->mode) { 403 | case can_led_mode_auto: 404 | case can_led_mode_off: 405 | status->state = 0; 406 | status->t_next = 0; 407 | break; 408 | case can_led_mode_on: 409 | status->state = 1; 410 | status->t_next = 0; 411 | break; 412 | case can_led_mode_blink_fast: 413 | status->state = !status->state; 414 | status->t_next += 100; 415 | break; 416 | case can_led_mode_blink_slow: 417 | status->state = !status->state; 418 | status->t_next += 500; 419 | break; 420 | } 421 | } 422 | 423 | set_led_state(i, status->state); 424 | } 425 | } 426 | -------------------------------------------------------------------------------- /can.h: -------------------------------------------------------------------------------- 1 | /* 2 | * can.h 3 | * 4 | * Created on: 25.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #ifndef CAN_H_ 9 | #define CAN_H_ 10 | 11 | #include 12 | #include "config.h" 13 | 14 | typedef struct __attribute__ ((packed)) { 15 | 16 | uint8_t channel; 17 | uint8_t dlc; 18 | uint16_t dummy; 19 | 20 | uint32_t timestamp; 21 | uint32_t id_and_flags; 22 | 23 | union { 24 | uint8_t data[8]; 25 | uint32_t data16[4]; 26 | uint32_t data32[2]; 27 | uint64_t data64; 28 | }; 29 | 30 | } can_message_t; 31 | 32 | typedef void (*can_rx_callback_t)(const can_message_t *msg); 33 | 34 | typedef enum { 35 | can_flag_rtr = 0x40000000, 36 | can_flag_extid = 0x80000000 37 | } can_flags_t; 38 | 39 | typedef enum { 40 | can_led_mode_auto, 41 | can_led_mode_blink_fast, 42 | can_led_mode_blink_slow, 43 | can_led_mode_on, 44 | can_led_mode_off 45 | } led_mode_t; 46 | 47 | void candle_can_init(void); 48 | void candle_can_poll(void); 49 | 50 | void candle_can_set_bitrate(uint8_t channel, uint16_t brp, uint8_t tseg1, uint8_t tseg2, uint8_t sjw); 51 | void candle_can_send_message(const can_message_t *msg); 52 | void candle_can_register_rx_callback(can_rx_callback_t callback); 53 | 54 | void candle_can_set_bus_active(uint8_t channel, uint16_t mode); 55 | void candle_can_set_silent(uint8_t channel, uint8_t silent_mode); 56 | 57 | void candle_can_set_led_mode(uint8_t channel, led_mode_t mode, uint32_t timeout); 58 | uint8_t candle_can_calc_message_len(const can_message_t *msg); 59 | 60 | #endif /* CAN_H_ */ 61 | -------------------------------------------------------------------------------- /can_queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * can_queue.c 3 | * 4 | * Created on: 03.08.2015 5 | * Author: hd 6 | */ 7 | 8 | #include "can_queue.h" 9 | 10 | void can_queue_init(can_queue_t *queue) { 11 | queue->first = 0; 12 | queue->last = 0; 13 | queue->count = 0; 14 | } 15 | 16 | void can_queue_push_back(can_queue_t *queue, can_queue_item_t *item) { 17 | if (queue->count==0) { 18 | queue->first = item; 19 | queue->last = item; 20 | item->prev = 0; 21 | item->next = 0; 22 | } else { 23 | item->prev = queue->last; 24 | item->next = 0; 25 | if (queue->last) { 26 | queue->last->next = item; 27 | } 28 | queue->last = item; 29 | } 30 | queue->count++; 31 | } 32 | 33 | int can_queue_pop_front(can_queue_t *queue, can_queue_item_t **item) { 34 | 35 | if (queue->count==0) { 36 | return 0; 37 | } else { 38 | *item = queue->first; 39 | queue->first = (*item)->next; 40 | queue->count--; 41 | return 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /can_queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * can_queue.h 3 | * 4 | * Created on: 03.08.2015 5 | * Author: hd 6 | */ 7 | 8 | #ifndef CAN_QUEUE_H_ 9 | #define CAN_QUEUE_H_ 10 | 11 | #include "config.h" 12 | #include "can.h" 13 | 14 | typedef struct { 15 | void *next; 16 | void *prev; 17 | can_message_t msg; 18 | } can_queue_item_t; 19 | 20 | typedef struct { 21 | can_queue_item_t *first; 22 | can_queue_item_t *last; 23 | unsigned count; 24 | } can_queue_t; 25 | 26 | void can_queue_init(can_queue_t *queue); 27 | void can_queue_push_back(can_queue_t *queue, can_queue_item_t *item); 28 | int can_queue_pop_front(can_queue_t *queue, can_queue_item_t **item); 29 | 30 | #endif /* CAN_QUEUE_H_ */ 31 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * config.h 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #ifndef CONFIG_H_ 9 | #define CONFIG_H_ 10 | 11 | //#define USE_USB_HS 12 | #define TX_QUEUE_LENGTH 32 13 | 14 | #endif /* CONFIG_H_ */ 15 | -------------------------------------------------------------------------------- /external/pcan_usbpro_fw.h: -------------------------------------------------------------------------------- 1 | //**************************************************************************** 2 | // Copyright (C) 2003-2010 PEAK System-Technik GmbH 3 | // 4 | // linux@peak-system.com 5 | // www.peak-system.com 6 | // 7 | // This program is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation; either version 2 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program; if not, write to the Free Software 19 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | // 21 | // Maintainer(s): Stephane Grosjean (s.grosjean@peak-system.com) 22 | // 23 | //**************************************************************************** 24 | 25 | //**************************************************************************** 26 | // 27 | // pcan_usbpro_fw.h - the PCAN-USB-PRO firmware internal structures 28 | // 29 | // $Id: pcan_usbpro_fw.h 615 2010-02-14 22:38:55Z khitschler $ 30 | // 31 | //**************************************************************************** 32 | 33 | #ifndef __pcan_usbpro_fw_h 34 | #define __pcan_usbpro_fw_h 35 | 36 | /* 37 | * USB Vendor Request Data Types 38 | */ 39 | 40 | /* Vendor (other) request */ 41 | #define USB_VENDOR_REQUEST_INFO 0 42 | #define USB_VENDOR_REQUEST_ZERO 1 43 | #define USB_VENDOR_REQUEST_FKT 2 44 | 45 | /* Vendor Request wValue for XXX_INFO */ 46 | #define USB_VENDOR_REQUEST_wVALUE_INFO_BOOTLOADER 0 47 | #define USB_VENDOR_REQUEST_wVALUE_INFO_FIRMWARE 1 48 | #define USB_VENDOR_REQUEST_wVALUE_INFO_uC_CHIPID 2 49 | #define USB_VENDOR_REQUEST_wVALUE_INFO_USB_CHIPID 3 50 | #define USB_VENDOR_REQUEST_wVALUE_INFO_DEVICENR 4 51 | #define USB_VENDOR_REQUEST_wVALUE_INFO_CPLD 5 52 | #define USB_VENDOR_REQUEST_wVALUE_INFO_MODE 6 53 | #define USB_VENDOR_REQUEST_wVALUE_INFO_TIMEMODE 7 54 | 55 | /* Vendor Request wValue for XXX_ZERO */ 56 | /* Value is Endpoint Number 0-7 */ 57 | 58 | /* Vendor Request wValue for XXX_FKT */ 59 | #define USB_VENDOR_REQUEST_wVALUE_SETFKT_BOOT 0 // set Bootloader Mode 60 | #define USB_VENDOR_REQUEST_wVALUE_SETFKT_DEBUG_CAN 1 // not used 61 | #define USB_VENDOR_REQUEST_wVALUE_SETFKT_DEBUG_LIN 2 // not used 62 | #define USB_VENDOR_REQUEST_wVALUE_SETFKT_DEBUG1 3 // not used 63 | #define USB_VENDOR_REQUEST_wVALUE_SETFKT_DEBUG2 4 // not used 64 | #define USB_VENDOR_REQUEST_wVALUE_SETFKT_INTERFACE_DRIVER_LOADED 5 65 | 66 | /* ctrl_type value */ 67 | #define INTERN_FIRMWARE_INFO_STRUCT_TYPE 0x11223322 68 | #define EXT_FIRMWARE_INFO_STRUCT_TYPE 0x11223344 69 | 70 | #define BOOTLOADER_INFO_STRUCT_TYPE 0x11112222 71 | #define uC_CHIPID_STRUCT_TYPE 0 72 | #define USB_CHIPID_STRUCT_TYPE 0 73 | #define DEVICE_NR_STRUCT_TYPE 0x3738393A 74 | #define CPLD_INFO_STRUCT_TYPE 0x1A1A2277 75 | 76 | /* USB_VENDOR_REQUEST_wVALUE_INFO_BOOTLOADER vendor request record type */ 77 | struct pcan_usbpro_bootloader_info_t 78 | { 79 | uint32_t ctrl_type; 80 | uint8_t version[4]; //[0] -> main [1]-> sub [2]-> debug 81 | uint8_t day; 82 | uint8_t month; 83 | uint8_t year; 84 | uint8_t dummy; 85 | uint32_t serial_num_high; 86 | uint32_t serial_num_low; 87 | uint32_t hw_type; 88 | uint32_t hw_rev; 89 | 90 | } __attribute__ ((packed)); 91 | 92 | struct pcan_usbpro_crc_block_t 93 | { 94 | uint32_t address; 95 | uint32_t len; 96 | uint32_t crc; 97 | 98 | } __attribute__ ((packed)); 99 | 100 | /* USB_VENDOR_REQUEST_wVALUE_INFO_FIRMWARE vendor request record type */ 101 | struct pcan_usbpro_ext_firmware_info_t 102 | { 103 | uint32_t ctrl_type; 104 | uint8_t version[4]; //[0] -> main [1]-> sub [2]-> debug 105 | uint8_t day; 106 | uint8_t month; 107 | uint8_t year; 108 | uint8_t dummy; 109 | uint32_t fw_type; 110 | 111 | } __attribute__ ((packed)); 112 | 113 | /* USB_VENDOR_REQUEST_wVALUE_INFO_uC_CHIPID vendor request record type */ 114 | struct pcan_usbpro_uc_chipid_t 115 | { 116 | uint32_t ctrl_type; 117 | uint32_t chip_id; 118 | 119 | } __attribute__ ((packed)); 120 | 121 | /* USB_VENDOR_REQUEST_wVALUE_INFO_USB_CHIPID vendor request record type */ 122 | struct pcan_usbpro_usb_chipid_t 123 | { 124 | uint32_t ctrl_type; 125 | uint32_t chip_id; 126 | 127 | } __attribute__ ((packed)); 128 | 129 | /* USB_VENDOR_REQUEST_wVALUE_INFO_DEVICENR vendor request record type */ 130 | struct pcan_usbpro_device_nr_t 131 | { 132 | uint32_t ctrl_type; 133 | uint32_t device_nr; 134 | 135 | } __attribute__ ((packed)); 136 | 137 | /* USB_VENDOR_REQUEST_wVALUE_INFO_CPLD vendor request record type */ 138 | struct pcan_usbpro_cpld_info_t 139 | { 140 | uint32_t ctrl_type; 141 | uint32_t cpld_nr; 142 | 143 | } __attribute__ ((packed)); 144 | 145 | /* USB_VENDOR_REQUEST_wVALUE_INFO_MODE vendor request record type */ 146 | struct pcan_usbpro_info_mode_t 147 | { 148 | uint32_t ctrl_type; 149 | uint8_t mode[16]; 150 | uint8_t flags[16]; 151 | 152 | } __attribute__ ((packed)); 153 | 154 | /* USB_VENDOR_REQUEST_wVALUE_INFO_TIMEMODE vendor request record type */ 155 | struct pcan_usbpro_time_mode_t 156 | { 157 | uint32_t ctrl_type; 158 | uint16_t time_mode; 159 | uint16_t flags; 160 | 161 | } __attribute__ ((packed)); 162 | 163 | /* 164 | * USB Command Record types 165 | */ 166 | 167 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_RX_8 0x80 168 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_RX_4 0x81 169 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_RX_0 0x82 170 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_RTR_RX 0x83 171 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_STATUS_ERROR_RX 0x84 172 | #define DATA_TYPE_USB2CAN_STRUCT_CALIBRATION_TIMESTAMP_RX 0x85 173 | #define DATA_TYPE_USB2CAN_STRUCT_BUSLAST_RX 0x86 174 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_8 0x41 175 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_4 0x42 176 | #define DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_0 0x43 177 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_GETBAUDRATE 0x01 178 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETBAUDRATE 0x02 179 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_GETCANBUSACTIVATE 0x03 180 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETCANBUSACTIVATE 0x04 181 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETSILENTMODE 0x05 182 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETDEVICENR 0x06 183 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETWARNINGLIMIT 0x07 184 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETLOOKUP_EXPLICIT 0x08 185 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETLOOKUP_GROUP 0x09 186 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETFILTERMODE 0x0a 187 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETRESET_MODE 0x0b 188 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETERRORFRAME 0x0c 189 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_GETCANBUS_ERROR_STATUS 0x0D 190 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETREGISTER 0x0e 191 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_GETREGISTER 0x0f 192 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETGET_CALIBRATION_MSG 0x10 193 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETGET_BUSLAST_MSG 0x11 194 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_GETDEVICENR 0x12 195 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SETSTRING 0x13 196 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_GETSTRING 0x14 197 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_STRING 0x15 198 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SAVEEEPROM 0x16 199 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_USB_IN_PACKET_DELAY 0x17 200 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_TIMESTAMP_PARAM 0x18 201 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_ERROR_GEN_ID 0x19 202 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_ERROR_GEN_NOW 0x1A 203 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SET_SOFTFILER 0x1B 204 | #define DATA_TYPE_USB2CAN_STRUCT_FKT_SET_CANLED 0x1C 205 | 206 | /* Record structures */ 207 | struct pcan_usbpro_canmsg_rx_t 208 | { 209 | uint8_t data_type; 210 | uint8_t client; 211 | uint8_t flags; 212 | unsigned dlc:4; 213 | unsigned channel:4; 214 | uint32_t timestamp32; 215 | uint32_t id; 216 | 217 | uint8_t data[8]; 218 | 219 | } __attribute__ ((packed)); 220 | 221 | /* Defines for status */ 222 | #define FW_USBPRO_STATUS_MASK_ERROR_S 0x0001 223 | #define FW_USBPRO_STATUS_MASK_BUS_S 0x0002 224 | #define FW_USBPRO_STATUS_MASK_OVERRUN_S 0x0004 225 | #define FW_USBPRO_STATUS_MASK_QOVERRUN_S 0x0008 226 | 227 | struct pcan_usbpro_canmsg_status_error_rx_t 228 | { 229 | uint8_t data_type; 230 | uint8_t channel; 231 | uint16_t status; 232 | uint32_t timestamp32; 233 | uint32_t error_frame; 234 | 235 | } __attribute__ ((packed)); 236 | 237 | struct pcan_usbpro_calibration_ts_rx_t 238 | { 239 | uint8_t data_type; 240 | uint8_t dummy[3]; 241 | uint32_t timestamp64[2]; 242 | 243 | } __attribute__ ((packed)); 244 | 245 | struct pcan_usbpro_buslast_rx_t 246 | { 247 | uint8_t data_type; 248 | uint8_t channel; /* Bit(3..0)-> can channel */ 249 | uint16_t buslast_val; 250 | uint32_t timestamp32; 251 | 252 | } __attribute__ ((packed)); 253 | 254 | struct pcan_usbpro_canmsg_tx_t 255 | { 256 | uint8_t data_type; 257 | uint8_t client; 258 | uint8_t flags; 259 | unsigned dlc:4; 260 | unsigned channel:4; 261 | uint32_t id; 262 | 263 | uint8_t data[8]; 264 | 265 | } __attribute__ ((packed)); 266 | 267 | struct pcan_usbpro_baudrate_t 268 | { 269 | uint8_t data_type; 270 | uint8_t channel; /* Bit(3..0)-> can channel */ 271 | uint16_t dummy; 272 | uint32_t CCBT; 273 | 274 | } __attribute__ ((packed)); 275 | 276 | struct pcan_usbpro_bus_activity_t 277 | { 278 | uint8_t data_type; 279 | uint8_t channel; /* Bit(3..0)-> can channel */ 280 | uint16_t onoff; /* 0->off 1->on */ 281 | 282 | } __attribute__ ((packed)); 283 | 284 | struct pcan_usbpro_silent_mode_t 285 | { 286 | uint8_t data_type; 287 | uint8_t channel; /* Bit(3..0)-> can channel */ 288 | uint16_t onoff; /* 0->off 1->on */ 289 | 290 | } __attribute__ ((packed)); 291 | 292 | struct pcan_usbpro_dev_nr_t 293 | { 294 | uint8_t data_type; 295 | uint8_t channel; /* Bit(3..0)-> can channel */ 296 | uint16_t dummy; 297 | uint32_t serial_num; 298 | 299 | } __attribute__ ((packed)); 300 | 301 | struct pcan_usbpro_warning_limit_t 302 | { 303 | uint8_t data_type; 304 | uint8_t channel; /* Bit(3..0)-> can channel */ 305 | uint16_t warning_limit; 306 | 307 | } __attribute__ ((packed)); 308 | 309 | struct pcan_usbpro_lookup_explicit_t 310 | { 311 | uint8_t data_type; 312 | uint8_t channel; /* Bit(3..0)-> can channel */ 313 | uint16_t id_type; 314 | uint32_t id; 315 | 316 | } __attribute__ ((packed)); 317 | 318 | struct pcan_usbpro_lookup_group_t 319 | { 320 | uint8_t data_type; 321 | uint8_t channel; /* Bit(3..0)-> can channel */ 322 | uint16_t id_type; 323 | uint32_t id_start; 324 | uint32_t id_end; 325 | 326 | } __attribute__ ((packed)); 327 | 328 | struct pcan_usbpro_filter_mode_t 329 | { 330 | uint8_t data_type; 331 | uint8_t dummy; 332 | uint16_t filter_mode; 333 | 334 | } __attribute__ ((packed)); 335 | 336 | struct pcan_usbpro_reset_mode_t 337 | { 338 | uint8_t data_type; 339 | uint8_t channel; /* Bit(3..0)-> can channel */ 340 | uint16_t reset; 341 | 342 | } __attribute__ ((packed)); 343 | 344 | struct pcan_usbpro_error_frame_t 345 | { 346 | uint8_t data_type; 347 | uint8_t channel; /* Bit(3..0)-> can channel */ 348 | uint16_t mode; 349 | 350 | } __attribute__ ((packed)); 351 | 352 | struct pcan_usbpro_error_status_t 353 | { 354 | uint8_t data_type; 355 | uint8_t channel; /* Bit(3..0)-> can channel */ 356 | uint16_t status; 357 | 358 | } __attribute__ ((packed)); 359 | 360 | struct pcan_usbpro_set_register_t 361 | { 362 | uint8_t data_type; 363 | uint8_t irq_off; 364 | uint16_t dummy; 365 | uint32_t address; 366 | uint32_t value; 367 | uint32_t mask; 368 | 369 | } __attribute__ ((packed)); 370 | 371 | struct pcan_usbpro_get_register_t 372 | { 373 | uint8_t data_type; 374 | uint8_t irq_off; 375 | uint16_t dummy; 376 | uint32_t address; 377 | uint32_t value; 378 | 379 | } __attribute__ ((packed)); 380 | 381 | struct pcan_usbpro_calibration_t 382 | { 383 | uint8_t data_type; 384 | uint8_t dummy; 385 | uint16_t mode; 386 | 387 | } __attribute__ ((packed)); 388 | 389 | struct pcan_usbpro_buslast_t 390 | { 391 | uint8_t data_type; 392 | uint8_t channel; /* Bit(3..0)-> can channel */ 393 | uint8_t dummy; 394 | uint8_t mode; 395 | uint16_t prescaler; 396 | uint16_t sampletimequanta; 397 | 398 | } __attribute__ ((packed)); 399 | 400 | struct pcan_usbpro_set_string_t 401 | { 402 | uint8_t data_type; 403 | uint8_t channel; /* Bit(3..0)-> can channel */ 404 | uint8_t offset; 405 | uint8_t len; 406 | uint8_t data[60]; 407 | 408 | } __attribute__ ((packed)); 409 | 410 | struct pcan_usbpro_get_string_t 411 | { 412 | uint8_t data_type; 413 | uint8_t channel; /* Bit(3..0)-> can channel */ 414 | uint16_t dummy; 415 | 416 | } __attribute__ ((packed)); 417 | 418 | struct pcan_usbpro_string_t 419 | { 420 | uint8_t data_type; 421 | uint8_t channel; /* Bit(3..0)-> can channel */ 422 | uint16_t dummy; 423 | uint8_t data[250]; 424 | 425 | } __attribute__ ((packed)); 426 | 427 | struct pcan_usbpro_save_eeprom_t 428 | { 429 | uint8_t data_type; 430 | uint8_t channel; /* Bit(3..0)-> can channel */ 431 | uint16_t dummy; 432 | 433 | } __attribute__ ((packed)); 434 | 435 | struct pcan_usbpro_packet_delay_t 436 | { 437 | uint8_t data_type; 438 | uint8_t dummy; 439 | uint16_t delay; 440 | 441 | } __attribute__ ((packed)); 442 | 443 | struct pcan_usbpro_timestamp_param_t 444 | { 445 | uint8_t data_type; 446 | uint8_t channel; /* Bit(3..0)-> can channel */ 447 | uint16_t start_or_end; 448 | 449 | } __attribute__ ((packed)); 450 | 451 | struct pcan_usbpro_error_gen_id_t 452 | { 453 | uint8_t data_type; 454 | uint8_t channel; /* Bit(3..0)-> can channel */ 455 | uint16_t bit_pos; 456 | uint32_t id; 457 | uint16_t ok_counter; 458 | uint16_t error_counter; 459 | 460 | } __attribute__ ((packed)); 461 | 462 | struct pcan_usbpro_error_gen_now_t 463 | { 464 | uint8_t data_type; 465 | uint8_t channel; /* Bit(3..0)-> can channel */ 466 | uint16_t bit_pos; 467 | 468 | } __attribute__ ((packed)); 469 | 470 | struct pcan_usbpro_softfiler_t 471 | { 472 | uint8_t data_type; 473 | uint8_t channel; /* Bit(3..0)-> can channel */ 474 | uint16_t dummy; 475 | uint32_t accmask; 476 | uint32_t acccode; 477 | 478 | } __attribute__ ((packed)); 479 | 480 | struct pcan_usbpro_set_can_led_t 481 | { 482 | uint8_t data_type; 483 | uint8_t channel; /* Bit(3..0)-> can channel */ 484 | uint16_t mode; 485 | uint32_t timeout; 486 | 487 | } __attribute__ ((packed)); 488 | 489 | union pcan_usbpro_rec_t 490 | { 491 | uint8_t data_type; 492 | struct pcan_usbpro_canmsg_rx_t canmsg_rx; 493 | struct pcan_usbpro_canmsg_status_error_rx_t canmsg_status_error_rx; 494 | struct pcan_usbpro_calibration_ts_rx_t calibration_ts_rx; 495 | struct pcan_usbpro_buslast_rx_t buslast_rx; 496 | struct pcan_usbpro_canmsg_tx_t canmsg_tx; 497 | struct pcan_usbpro_baudrate_t baudrate; 498 | struct pcan_usbpro_bus_activity_t bus_activity; 499 | struct pcan_usbpro_silent_mode_t silent_mode; 500 | struct pcan_usbpro_dev_nr_t dev_nr; 501 | struct pcan_usbpro_warning_limit_t warning_limit; 502 | struct pcan_usbpro_lookup_explicit_t lookup_explicit; 503 | struct pcan_usbpro_lookup_group_t lookup_group; 504 | struct pcan_usbpro_filter_mode_t filer_mode; 505 | struct pcan_usbpro_reset_mode_t reset_mode; 506 | struct pcan_usbpro_error_frame_t error_frame; 507 | struct pcan_usbpro_error_status_t error_status; 508 | struct pcan_usbpro_set_register_t set_register; 509 | struct pcan_usbpro_get_register_t get_register; 510 | struct pcan_usbpro_calibration_t calibration; 511 | struct pcan_usbpro_buslast_t buslast; 512 | struct pcan_usbpro_set_string_t set_string; 513 | struct pcan_usbpro_get_string_t get_string; 514 | struct pcan_usbpro_string_t string; 515 | struct pcan_usbpro_save_eeprom_t save_eeprom; 516 | struct pcan_usbpro_packet_delay_t packet_delay; 517 | struct pcan_usbpro_timestamp_param_t timestamp_param; 518 | struct pcan_usbpro_error_gen_id_t error_gen_id; 519 | struct pcan_usbpro_error_gen_now_t error_gen_now; 520 | struct pcan_usbpro_softfiler_t softfiler; 521 | struct pcan_usbpro_set_can_led_t set_can_led; 522 | 523 | } __attribute__ ((packed)); 524 | 525 | #endif /* __pcan_usbpro_fw_h */ 526 | -------------------------------------------------------------------------------- /external/pcan_usbpro_sizeof_rec.c: -------------------------------------------------------------------------------- 1 | //**************************************************************************** 2 | // Copyright (C) 2003-2011 PEAK System-Technik GmbH 3 | // 4 | // linux@peak-system.com 5 | // www.peak-system.com 6 | // 7 | // This program is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation; either version 2 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program; if not, write to the Free Software 19 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | // 21 | // Maintainer(s): Stephane Grosjean (s.grosjean@peak-system.com) 22 | // 23 | // Major contributions by: 24 | // Klaus Hitschler (klaus.hitschler@gmx.de) 25 | // Oliver Hartkopp (oliver.hartkopp@volkswagen.de) socketCAN 26 | // 27 | //**************************************************************************** 28 | #include "pcan_usbpro_sizeof_rec.h" 29 | #include "pcan_usbpro_fw.h" 30 | 31 | int pcan_usbpro_sizeof_rec(uint8_t data_type) 32 | { 33 | switch (data_type) 34 | { 35 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_RX_8: 36 | return sizeof(struct pcan_usbpro_canmsg_rx_t); 37 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_RX_4: 38 | return sizeof(struct pcan_usbpro_canmsg_rx_t) - 4; 39 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_RX_0: 40 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_RTR_RX: 41 | return sizeof(struct pcan_usbpro_canmsg_rx_t) - 8; 42 | 43 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_STATUS_ERROR_RX: 44 | return sizeof(struct pcan_usbpro_canmsg_status_error_rx_t); 45 | 46 | case DATA_TYPE_USB2CAN_STRUCT_CALIBRATION_TIMESTAMP_RX: 47 | return sizeof(struct pcan_usbpro_calibration_ts_rx_t); 48 | 49 | case DATA_TYPE_USB2CAN_STRUCT_BUSLAST_RX: 50 | return sizeof(struct pcan_usbpro_buslast_rx_t); 51 | 52 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_8: 53 | return sizeof(struct pcan_usbpro_canmsg_tx_t); 54 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_4: 55 | return sizeof(struct pcan_usbpro_canmsg_tx_t) - 4; 56 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_0: 57 | return sizeof(struct pcan_usbpro_canmsg_tx_t) - 8; 58 | 59 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETBAUDRATE: 60 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETBAUDRATE: 61 | return sizeof(struct pcan_usbpro_baudrate_t); 62 | 63 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETCANBUSACTIVATE: 64 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETCANBUSACTIVATE: 65 | return sizeof(struct pcan_usbpro_bus_activity_t); 66 | 67 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETSILENTMODE: 68 | return sizeof(struct pcan_usbpro_silent_mode_t); 69 | 70 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETDEVICENR: 71 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETDEVICENR: 72 | return sizeof(struct pcan_usbpro_dev_nr_t); 73 | 74 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETWARNINGLIMIT: 75 | return sizeof(struct pcan_usbpro_warning_limit_t); 76 | 77 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETLOOKUP_EXPLICIT: 78 | return sizeof(struct pcan_usbpro_lookup_explicit_t); 79 | 80 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETLOOKUP_GROUP: 81 | return sizeof(struct pcan_usbpro_lookup_group_t); 82 | 83 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETFILTERMODE: 84 | return sizeof(struct pcan_usbpro_filter_mode_t); 85 | 86 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETRESET_MODE: 87 | return sizeof(struct pcan_usbpro_reset_mode_t); 88 | 89 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETERRORFRAME: 90 | return sizeof(struct pcan_usbpro_error_frame_t); 91 | 92 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETCANBUS_ERROR_STATUS: 93 | return sizeof(struct pcan_usbpro_error_status_t); 94 | 95 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETREGISTER: 96 | return sizeof(struct pcan_usbpro_set_register_t); 97 | 98 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETREGISTER: 99 | return sizeof(struct pcan_usbpro_get_register_t); 100 | 101 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETGET_CALIBRATION_MSG: 102 | return sizeof(struct pcan_usbpro_calibration_t); 103 | 104 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETGET_BUSLAST_MSG: 105 | return sizeof(struct pcan_usbpro_buslast_t); 106 | 107 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETSTRING: 108 | return sizeof(struct pcan_usbpro_set_string_t); 109 | 110 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETSTRING: 111 | return sizeof(struct pcan_usbpro_get_string_t); 112 | 113 | case DATA_TYPE_USB2CAN_STRUCT_FKT_STRING: 114 | return sizeof(struct pcan_usbpro_string_t); 115 | 116 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SAVEEEPROM: 117 | return sizeof(struct pcan_usbpro_save_eeprom_t); 118 | 119 | case DATA_TYPE_USB2CAN_STRUCT_FKT_USB_IN_PACKET_DELAY: 120 | return sizeof(struct pcan_usbpro_packet_delay_t); 121 | 122 | case DATA_TYPE_USB2CAN_STRUCT_FKT_TIMESTAMP_PARAM: 123 | return sizeof(struct pcan_usbpro_timestamp_param_t); 124 | 125 | case DATA_TYPE_USB2CAN_STRUCT_FKT_ERROR_GEN_ID: 126 | return sizeof(struct pcan_usbpro_error_gen_id_t); 127 | 128 | case DATA_TYPE_USB2CAN_STRUCT_FKT_ERROR_GEN_NOW: 129 | return sizeof(struct pcan_usbpro_error_gen_now_t); 130 | 131 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SET_SOFTFILER: 132 | return sizeof(struct pcan_usbpro_softfiler_t); 133 | 134 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SET_CANLED: 135 | return sizeof(struct pcan_usbpro_set_can_led_t); 136 | 137 | } 138 | 139 | return -1; 140 | } 141 | 142 | -------------------------------------------------------------------------------- /external/pcan_usbpro_sizeof_rec.h: -------------------------------------------------------------------------------- 1 | //**************************************************************************** 2 | // Copyright (C) 2003-2011 PEAK System-Technik GmbH 3 | // 4 | // linux@peak-system.com 5 | // www.peak-system.com 6 | // 7 | // This program is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation; either version 2 of the License, or 10 | // (at your option) any later version. 11 | // 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program; if not, write to the Free Software 19 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | // 21 | // Maintainer(s): Stephane Grosjean (s.grosjean@peak-system.com) 22 | // 23 | // Major contributions by: 24 | // Klaus Hitschler (klaus.hitschler@gmx.de) 25 | // Oliver Hartkopp (oliver.hartkopp@volkswagen.de) socketCAN 26 | // 27 | //**************************************************************************** 28 | 29 | #ifndef PCAN_USBPRO_SIZEOF_REC_H_ 30 | #define PCAN_USBPRO_SIZEOF_REC_H_ 31 | 32 | #include 33 | 34 | int pcan_usbpro_sizeof_rec(uint8_t data_type); 35 | 36 | #endif /* PCAN_USBPRO_SIZEOF_REC_H_ */ 37 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "config.h" 12 | #include "can.h" 13 | #include "ppro_protocol.h" 14 | #include "ppro_usb.h" 15 | #include "systime.h" 16 | 17 | int main(void) { 18 | 19 | struct rcc_clock_scale clkcfg_96mhz = { 20 | .pllm = 4, 21 | .plln = 192, 22 | .pllp = 4, 23 | .pllq = 8, 24 | .flash_config = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS, // TODO check if this is sane (seems to work for 48MHz as well as 120MHz) 25 | .hpre = RCC_CFGR_HPRE_DIV_NONE, 26 | .ppre1 = RCC_CFGR_PPRE_DIV_4, 27 | .ppre2 = RCC_CFGR_PPRE_DIV_2, 28 | .power_save = 1, 29 | .ahb_frequency = 96000000, 30 | .apb1_frequency = 24000000, 31 | .apb2_frequency = 48000000 32 | }; 33 | 34 | rcc_clock_setup_hse_3v3(&clkcfg_96mhz); 35 | //rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_120MHZ]); 36 | systime_setup(96000); 37 | 38 | candle_can_init(); 39 | ppro_usb_init(); 40 | candle_can_register_rx_callback(ppro_rx_message); 41 | 42 | while (1) { 43 | ppro_usb_poll(); 44 | candle_can_poll(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /pcan_stm32.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 27 | 28 | 29 | 47 | 48 | 69 | 70 | 92 | 93 | 113 | 114 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 185 | 186 | 187 | 188 | 189 | 191 | 192 | 193 | 195 | 196 | 198 | 199 | 200 | 202 | 203 | 204 | 206 | 207 | 208 | 209 | 210 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /ppro_protocol.c: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_pcan_protocol.c 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "systime.h" 13 | #include "external/pcan_usbpro_fw.h" 14 | #include "external/pcan_usbpro_sizeof_rec.h" 15 | #include "can.h" 16 | #include "ppro_protocol.h" 17 | #include "ppro_usb.h" 18 | 19 | 20 | typedef struct { 21 | uint16_t record_count; 22 | uint16_t message_counter; 23 | union pcan_usbpro_rec_t first_record; 24 | } candle_usb_packet_t; 25 | 26 | 27 | typedef struct { 28 | struct { 29 | uint16_t record_count; 30 | uint16_t message_counter; 31 | uint8_t data[120]; 32 | } output_buffer; 33 | unsigned output_buffer_pos; 34 | uint32_t bits_transferred; 35 | } channel_data_t; 36 | 37 | 38 | static usbd_device *dev = 0; 39 | static channel_data_t channel_data[2]; 40 | 41 | 42 | void ppro_usb_protocol_init(usbd_device *usbd_dev) { 43 | dev = usbd_dev; 44 | memset(channel_data, 0, sizeof(channel_data)); 45 | } 46 | 47 | static int ppro_usb_flush(uint8_t ep) { 48 | assert((ep==1)||(ep==2)); 49 | channel_data_t *data = &channel_data[ep-1]; 50 | if (data->output_buffer.record_count > 0) { 51 | int bytes_written = usbd_ep_write_packet(dev, 0x80|ep, &data->output_buffer, 4+data->output_buffer_pos); 52 | if (bytes_written != 0) { 53 | data->output_buffer.record_count = 0; 54 | data->output_buffer_pos = 0; 55 | data->output_buffer.message_counter++; 56 | return bytes_written; 57 | } 58 | } 59 | return 0; 60 | } 61 | 62 | void ppro_usb_flush_all(void) { 63 | ppro_usb_flush(1); 64 | ppro_usb_flush(2); 65 | } 66 | 67 | static int ppro_usb_buffer_space_left(channel_data_t *data) { 68 | return sizeof(data->output_buffer.data) - data->output_buffer_pos; 69 | } 70 | 71 | static int ppro_usb_enqueue_record(uint8_t ep, union pcan_usbpro_rec_t *record) { 72 | assert((ep==1)||(ep==2)); 73 | channel_data_t *data = &channel_data[ep-1]; 74 | 75 | int space_left = ppro_usb_buffer_space_left(data); 76 | 77 | int record_length = pcan_usbpro_sizeof_rec(record->data_type); 78 | assert(record_length>0); // record_length<=0 means that we don't know the record type. but we should know all messages that we are sending! 79 | 80 | if (space_left < record_length) { 81 | // buffer full? try to send now. 82 | if (ppro_usb_flush(ep)>0) { 83 | space_left = ppro_usb_buffer_space_left(data); 84 | } 85 | } 86 | 87 | if (space_left >= record_length) { 88 | data->output_buffer.record_count++; 89 | memcpy(&data->output_buffer.data[data->output_buffer_pos], record, record_length); 90 | data->output_buffer_pos += record_length; 91 | return 0; 92 | } else { 93 | return -1; 94 | } 95 | 96 | } 97 | 98 | static void ppro_set_bitrate(uint8_t channel, uint32_t ccbt) { 99 | //uint8_t tripple_sample_mode = ccbt>>23 & 0x01; 100 | uint8_t tseg2 = ((ccbt >> 20) & 0x07) + 1; 101 | uint8_t tseg1 = ((ccbt >> 16) & 0x0F) + 1; 102 | uint8_t sjw = ((ccbt >> 24) & 0x03) + 1; 103 | uint16_t brp_ppro = (ccbt & 0x3fff) + 1; 104 | 105 | uint16_t brp_stm = (24 * brp_ppro) / 56; 106 | candle_can_set_bitrate(channel, brp_stm, tseg1, tseg2, sjw); 107 | } 108 | 109 | static void ppro_tx_message(uint8_t channel, uint32_t id_and_flags, uint8_t dlc, void *data) { 110 | can_message_t msg; 111 | 112 | assert((channel==0)||(channel==1)); 113 | 114 | if (dlc>8) { dlc = 8; } 115 | msg.channel = channel; 116 | msg.dlc = dlc; 117 | msg.timestamp = 0; 118 | msg.id_and_flags = id_and_flags; 119 | memcpy(msg.data, data, dlc); 120 | 121 | channel_data[channel].bits_transferred += candle_can_calc_message_len(&msg); 122 | candle_can_send_message(&msg); 123 | } 124 | 125 | static void ppro_tx(union pcan_usbpro_rec_t *request) { 126 | uint32_t id = request->canmsg_tx.id; 127 | if (request->canmsg_tx.flags & 0x01) { id |= can_flag_rtr; } 128 | if (request->canmsg_tx.flags & 0x02) { id |= can_flag_extid; } 129 | ppro_tx_message(request->canmsg_tx.channel, id, request->canmsg_tx.dlc, request->canmsg_tx.data); 130 | } 131 | 132 | static void ppro_set_timestamp_mode(uint16_t timestamp_mode) { 133 | (void)timestamp_mode; 134 | ppro_status.timestamp_active = (timestamp_mode==1); 135 | ppro_status.t_next_timestamp = 0; 136 | } 137 | 138 | static uint32_t ppro_get_device_id(uint8_t channel) { 139 | // TODO implement device id handling 140 | return channel; 141 | } 142 | 143 | static uint16_t ppro_get_error_status(uint8_t channel) { 144 | // TODO implement me 145 | (void)channel; 146 | return 0; 147 | } 148 | 149 | static void ppro_request_busload(uint8_t channel, uint8_t mode, uint16_t prescaler, uint16_t quanta) { 150 | (void)prescaler; 151 | (void)quanta; 152 | ppro_status.busload_mode[channel] = mode; 153 | } 154 | 155 | void ppro_rx_message(const can_message_t *msg) { 156 | union pcan_usbpro_rec_t record; 157 | record.canmsg_rx.data_type = DATA_TYPE_USB2CAN_STRUCT_CANMSG_RX_8; 158 | record.canmsg_rx.client = 0; 159 | record.canmsg_rx.timestamp32 = msg->timestamp; 160 | record.canmsg_rx.channel = msg->channel; 161 | record.canmsg_rx.id = msg->id_and_flags & 0x1FFFFFFF; 162 | record.canmsg_rx.flags = msg->id_and_flags >> 30; 163 | record.canmsg_rx.dlc = msg->dlc; 164 | memcpy(record.canmsg_rx.data, msg->data, 8); 165 | 166 | ppro_usb_enqueue_record(2, &record); 167 | 168 | if (msg->channel<2) { 169 | channel_data[msg->channel].bits_transferred += candle_can_calc_message_len(msg); 170 | } 171 | } 172 | 173 | void ppro_usb_send_timestamp(uint8_t ep) { 174 | union pcan_usbpro_rec_t record; 175 | record.calibration_ts_rx.data_type = DATA_TYPE_USB2CAN_STRUCT_CALIBRATION_TIMESTAMP_RX; 176 | record.calibration_ts_rx.dummy[0] = 0; 177 | record.calibration_ts_rx.dummy[1] = 0; 178 | record.calibration_ts_rx.dummy[2] = 0; 179 | record.calibration_ts_rx.timestamp64[0] = 0; 180 | record.calibration_ts_rx.timestamp64[1] = get_time_us64(); 181 | ppro_usb_enqueue_record(ep, &record); 182 | } 183 | 184 | void ppro_usb_send_busload(uint8_t ep, uint8_t channel) { 185 | assert((channel==0)||(channel==1)); 186 | union pcan_usbpro_rec_t record; 187 | record.buslast_rx.data_type = DATA_TYPE_USB2CAN_STRUCT_BUSLAST_RX; 188 | record.buslast_rx.channel = channel; 189 | record.buslast_rx.buslast_val = channel_data[0].bits_transferred; 190 | channel_data[0].bits_transferred = 0; 191 | record.buslast_rx.timestamp32 = get_time_us32(); 192 | ppro_usb_enqueue_record(ep, &record); 193 | } 194 | 195 | 196 | void ppro_usb_protocol_handle_data(uint8_t ep, uint8_t *buf, int len) { 197 | union pcan_usbpro_rec_t record; 198 | 199 | if (len>=4) { 200 | candle_usb_packet_t *packet = (candle_usb_packet_t*)buf; 201 | 202 | int pos = 4; 203 | int num_records = 0; 204 | 205 | while ((++num_records <= packet->record_count) && (posdata_type) { 210 | 211 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SET_CANLED: 212 | candle_can_set_led_mode(request->set_can_led.channel, request->set_can_led.mode, request->set_can_led.timeout); 213 | break; 214 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETCANBUSACTIVATE: 215 | candle_can_set_bus_active(request->bus_activity.channel, request->bus_activity.onoff); 216 | break; 217 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETDEVICENR: 218 | record.dev_nr.data_type = DATA_TYPE_USB2CAN_STRUCT_FKT_GETDEVICENR; 219 | record.dev_nr.channel = request->dev_nr.channel; 220 | record.dev_nr.serial_num = ppro_get_device_id(request->dev_nr.channel); 221 | ppro_usb_enqueue_record(ep, &record); 222 | break; 223 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETBAUDRATE: 224 | ppro_set_bitrate(request->baudrate.channel, request->baudrate.CCBT); 225 | break; 226 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETSILENTMODE: 227 | candle_can_set_silent(request->silent_mode.channel, request->silent_mode.onoff); 228 | break; 229 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETFILTERMODE: 230 | // ignored 231 | //ppro_set_filter_mode(request->filer_mode.filter_mode); 232 | break; 233 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETGET_CALIBRATION_MSG: 234 | ppro_set_timestamp_mode(request->calibration.mode); 235 | ppro_usb_send_timestamp(2); 236 | break; 237 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_0: 238 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_4: 239 | case DATA_TYPE_USB2CAN_STRUCT_CANMSG_TX_8: 240 | ppro_tx(request); 241 | break; 242 | case DATA_TYPE_USB2CAN_STRUCT_FKT_GETCANBUS_ERROR_STATUS: 243 | record.error_status.data_type = DATA_TYPE_USB2CAN_STRUCT_FKT_GETCANBUS_ERROR_STATUS; 244 | record.error_status.channel = request->error_status.channel; 245 | record.error_status.status = ppro_get_error_status(request->error_status.channel); 246 | ppro_usb_enqueue_record(ep, &record); 247 | break; 248 | case DATA_TYPE_USB2CAN_STRUCT_FKT_SETGET_BUSLAST_MSG: 249 | ppro_request_busload( 250 | request->buslast.channel, 251 | request->buslast.mode, 252 | request->buslast.prescaler, 253 | request->buslast.sampletimequanta 254 | ); 255 | break; 256 | default: 257 | // unknown request type 258 | break; 259 | } 260 | 261 | pos += pcan_usbpro_sizeof_rec(request->data_type); 262 | } 263 | } 264 | } 265 | 266 | -------------------------------------------------------------------------------- /ppro_protocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_pcan_protocol.h 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #ifndef PPRO_PROTOCOL_H_ 9 | #define PPRO_PROTOCOL_H_ 10 | 11 | #include 12 | #include 13 | #include "can.h" 14 | 15 | void ppro_usb_protocol_init(usbd_device *usbd_dev); 16 | void ppro_usb_protocol_handle_data(uint8_t ep, uint8_t *buf, int len); 17 | void ppro_usb_send_timestamp(uint8_t ep); 18 | void ppro_usb_send_busload(uint8_t ep, uint8_t channel); 19 | void ppro_rx_message(const can_message_t *msg); 20 | void ppro_usb_flush_all(void); 21 | 22 | #endif /* PPRO_PROTOCOL_H_ */ 23 | -------------------------------------------------------------------------------- /ppro_usb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_pcan.c 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #include "ppro_usb.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "systime.h" 16 | #include "external/pcan_usbpro_fw.h" 17 | #include "ppro_protocol.h" 18 | #include "ppro_usb_descr.h" 19 | 20 | ppro_status_t ppro_status; 21 | 22 | static usbd_device *usbdev; 23 | static uint8_t usbd_control_buffer[512]; 24 | 25 | static struct pcan_usbpro_bootloader_info_t bootloader_info = { 26 | .ctrl_type = 0x11112222, 27 | .version = {1, 8, 3, 0}, 28 | .day = 26, 29 | .month = 5, 30 | .year = 9, 31 | .dummy = 0, 32 | .serial_num_high = 0xFFFFFFFF, 33 | .serial_num_low = 0x00000001, 34 | .hw_type = 0x00000100, 35 | .hw_rev = 0x00000000 36 | }; 37 | 38 | static struct pcan_usbpro_ext_firmware_info_t firmware_info = { 39 | .ctrl_type = 0x11223344, 40 | .version = {1, 3, 3, 0 }, 41 | .day = 18, 42 | .month = 6, 43 | .year = 10, 44 | .dummy = 0x40, 45 | .fw_type = 0x00000100 46 | }; 47 | 48 | static struct pcan_usbpro_uc_chipid_t uc_chip_id = { 49 | .ctrl_type = 0, // TODO find valid values 50 | .chip_id = 0 51 | }; 52 | 53 | static struct pcan_usbpro_usb_chipid_t usb_chip_id = { 54 | .ctrl_type = 0, // TODO find valid values 55 | .chip_id = 0 56 | }; 57 | 58 | static struct pcan_usbpro_device_nr_t device_nr = { 59 | .ctrl_type = 0x3738393a, 60 | .device_nr = 1 61 | }; 62 | 63 | static struct pcan_usbpro_cpld_info_t cpld_info = { 64 | .ctrl_type = 0x1a1a2277, 65 | .cpld_nr = 7 66 | }; 67 | 68 | static struct pcan_usbpro_info_mode_t info_mode = { 69 | .ctrl_type = 0, // TODO find valid values 70 | .mode = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 71 | .flags = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } 72 | }; 73 | 74 | static struct pcan_usbpro_time_mode_t time_mode = { 75 | .ctrl_type = 0, 76 | .time_mode = 0, 77 | .flags = 0 78 | }; 79 | 80 | static void ppro_usb_rx_handler(usbd_device *usbd_dev, uint8_t ep) 81 | { 82 | uint8_t buf[128]; 83 | int len = usbd_ep_read_packet(usbd_dev, ep, buf, sizeof(buf)); 84 | ppro_usb_protocol_handle_data(ep, buf, len); 85 | } 86 | 87 | static int ppro_usb_control_request(usbd_device *usbd_dev, 88 | struct usb_setup_data *req, uint8_t **buf, uint16_t *len, 89 | void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req)) 90 | { 91 | (void)complete; 92 | (void)buf; 93 | (void)usbd_dev; 94 | 95 | static uint8_t buffer[128]; 96 | 97 | if (req->bRequest == 0) { // get information 98 | 99 | switch (req->wValue) { 100 | 101 | case USB_VENDOR_REQUEST_wVALUE_INFO_BOOTLOADER: 102 | memcpy(*buf, &bootloader_info, sizeof(bootloader_info)); 103 | *len = sizeof(bootloader_info); 104 | break; 105 | 106 | case USB_VENDOR_REQUEST_wVALUE_INFO_FIRMWARE: 107 | memcpy(*buf, &firmware_info, sizeof(firmware_info)); 108 | *len = sizeof(firmware_info); 109 | break; 110 | 111 | case USB_VENDOR_REQUEST_wVALUE_INFO_uC_CHIPID: 112 | memcpy(*buf, &uc_chip_id, sizeof(uc_chip_id)); 113 | *len = sizeof(uc_chip_id); 114 | break; 115 | 116 | case USB_VENDOR_REQUEST_wVALUE_INFO_USB_CHIPID: 117 | memcpy(*buf, &usb_chip_id, sizeof(usb_chip_id)); 118 | *len = sizeof(usb_chip_id); 119 | break; 120 | 121 | case USB_VENDOR_REQUEST_wVALUE_INFO_DEVICENR: 122 | memcpy(*buf, &device_nr, sizeof(device_nr)); 123 | *len = sizeof(device_nr); 124 | break; 125 | 126 | case USB_VENDOR_REQUEST_wVALUE_INFO_CPLD: 127 | memcpy(*buf, &cpld_info, sizeof(cpld_info)); 128 | *len = sizeof(cpld_info); 129 | break; 130 | 131 | case USB_VENDOR_REQUEST_wVALUE_INFO_MODE: 132 | memcpy(*buf, &info_mode, sizeof(info_mode)); 133 | *len = sizeof(info_mode); 134 | break; 135 | 136 | case USB_VENDOR_REQUEST_wVALUE_INFO_TIMEMODE: 137 | memcpy(*buf, &time_mode, sizeof(time_mode)); 138 | *len = sizeof(time_mode); 139 | break; 140 | 141 | } 142 | 143 | return 1; 144 | 145 | } else if (req->bRequest == 2) { // config ? 146 | if (req->wValue==USB_VENDOR_REQUEST_wVALUE_SETFKT_INTERFACE_DRIVER_LOADED) { 147 | usbd_ep_read_packet(usbd_dev, 0, buffer, 16); 148 | // data is 16 bytes, of which only 2 are used: 149 | // data[0] == driver (CAN=0, LIN=1) 150 | // data[1] == driver loaded (0/1) 151 | return USBD_REQ_HANDLED; 152 | } 153 | 154 | } 155 | 156 | return 0; 157 | } 158 | 159 | static void ppro_usb_set_config(usbd_device *usbd_dev, uint16_t wValue) 160 | { 161 | (void)wValue; 162 | 163 | usbd_register_control_callback(usbd_dev, 0x43, 0x7F, ppro_usb_control_request); 164 | 165 | usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 128, ppro_usb_rx_handler); 166 | usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_BULK, 128, NULL); 167 | 168 | usbd_ep_setup(usbd_dev, 0x02, USB_ENDPOINT_ATTR_BULK, 128, ppro_usb_rx_handler); 169 | usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 128, NULL); 170 | 171 | usbd_ep_setup(usbd_dev, 0x03, USB_ENDPOINT_ATTR_BULK, 128, ppro_usb_rx_handler); 172 | usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_BULK, 128, NULL); 173 | 174 | #ifdef USE_USB_HS 175 | usbd_ep_setup(usbd_dev, 0x04, USB_ENDPOINT_ATTR_BULK, 128, ppro_usb_rx_handler); 176 | usbd_ep_setup(usbd_dev, 0x84, USB_ENDPOINT_ATTR_BULK, 128, candle_usb_tx_handler); 177 | 178 | usbd_ep_setup(usbd_dev, 0x05, USB_ENDPOINT_ATTR_BULK, 128, ppro_usb_rx_handler); 179 | usbd_ep_setup(usbd_dev, 0x85, USB_ENDPOINT_ATTR_BULK, 128, candle_usb_tx_handler); 180 | #endif 181 | 182 | //candle_usb_send_timestamp(usbd_dev, 2); 183 | } 184 | 185 | 186 | void ppro_usb_init(void) { 187 | memset(&ppro_status, 0, sizeof(ppro_status)); 188 | 189 | #ifdef USE_USB_HS 190 | rcc_periph_clock_enable(RCC_GPIOB); 191 | rcc_periph_clock_enable(RCC_OTGHS); 192 | gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO13 | GPIO14 | GPIO15); 193 | gpio_set_af(GPIOB, GPIO_AF12, GPIO13 | GPIO14 | GPIO15); 194 | 195 | usbdev = usbd_init(&otghs_usb_driver, &device_descriptor, &config, 196 | usb_strings, 10, 197 | usbd_control_buffer, sizeof(usbd_control_buffer)); 198 | #else 199 | rcc_periph_clock_enable(RCC_GPIOA); 200 | rcc_periph_clock_enable(RCC_OTGFS); 201 | gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO11 | GPIO12); 202 | gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); 203 | 204 | usbdev = usbd_init(&otgfs_usb_driver, &device_descriptor, &config_descriptor, 205 | usb_strings, 10, 206 | usbd_control_buffer, sizeof(usbd_control_buffer)); 207 | 208 | #ifdef DISABLE_VBUS_SENSE 209 | // Disable VBUS sense 210 | #include 211 | OTG_FS_GCCFG |= OTG_GCCFG_NOVBUSSENS; 212 | #endif 213 | #endif 214 | 215 | 216 | ppro_usb_protocol_init(usbdev); 217 | usbd_register_set_config_callback(usbdev, ppro_usb_set_config); 218 | } 219 | 220 | void ppro_usb_poll(void) { 221 | usbd_poll(usbdev); 222 | ppro_usb_flush_all(); 223 | 224 | uint32_t now = get_time_ms(); 225 | 226 | if (ppro_status.timestamp_active && (ppro_status.t_next_timestamp <= now)) { 227 | ppro_usb_send_timestamp(2); 228 | ppro_status.t_next_timestamp = now + 1000; 229 | } 230 | 231 | for (uint8_t i=0; i<2; i++) { 232 | if (ppro_status.busload_mode[i] && (ppro_status.t_next_busload[i] <= now)) { 233 | ppro_usb_send_busload(2, i); 234 | ppro_status.t_next_busload[i] = now + 8; 235 | } 236 | } 237 | 238 | } 239 | -------------------------------------------------------------------------------- /ppro_usb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_pcan.h 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #ifndef PPRO_USB_H_ 9 | #define PPRO_USB_H_ 10 | 11 | #include 12 | 13 | typedef struct { 14 | uint8_t timestamp_active; 15 | uint32_t t_next_timestamp; 16 | uint8_t busload_mode[2]; 17 | uint32_t t_next_busload[2]; 18 | } ppro_status_t; 19 | 20 | extern ppro_status_t ppro_status; 21 | 22 | 23 | void ppro_usb_init(void); 24 | void ppro_usb_poll(void); 25 | 26 | #endif /* PPRO_USB_H_ */ 27 | -------------------------------------------------------------------------------- /ppro_usb_descr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_descriptor.c 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #include "ppro_usb_descr.h" 9 | 10 | const struct usb_device_descriptor device_descriptor = { 11 | .bLength = USB_DT_DEVICE_SIZE, 12 | .bDescriptorType = USB_DT_DEVICE, 13 | .bcdUSB = 0x0110, // 0x200 with peak, use 0110 to indicate a usb1.1 device (which we are) 14 | .bDeviceClass = 0x00, // Device 15 | .bDeviceSubClass = 0, 16 | .bDeviceProtocol = 0, 17 | .bMaxPacketSize0 = 64, 18 | .idVendor = 0x0c72, 19 | .idProduct = 0x000d, 20 | .bcdDevice = 0x0000, 21 | .iManufacturer = 1, 22 | .iProduct = 2, 23 | .iSerialNumber = 0, 24 | .bNumConfigurations = 1, 25 | }; 26 | 27 | const struct usb_endpoint_descriptor can_endp[] = { 28 | { 29 | .bLength = USB_DT_ENDPOINT_SIZE, 30 | .bDescriptorType = USB_DT_ENDPOINT, 31 | .bEndpointAddress = 0x81, 32 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 33 | .wMaxPacketSize = 64, // PCAN: 512 34 | .bInterval = 0, 35 | }, 36 | { 37 | .bLength = USB_DT_ENDPOINT_SIZE, 38 | .bDescriptorType = USB_DT_ENDPOINT, 39 | .bEndpointAddress = 0x01, 40 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 41 | .wMaxPacketSize = 64, // PCAN: 512 42 | .bInterval = 0, 43 | }, 44 | { 45 | .bLength = USB_DT_ENDPOINT_SIZE, 46 | .bDescriptorType = USB_DT_ENDPOINT, 47 | .bEndpointAddress = 0x82, 48 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 49 | .wMaxPacketSize = 64, // PCAN: 512 50 | .bInterval = 0, 51 | }, 52 | { 53 | .bLength = USB_DT_ENDPOINT_SIZE, 54 | .bDescriptorType = USB_DT_ENDPOINT, 55 | .bEndpointAddress = 0x02, 56 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 57 | .wMaxPacketSize = 64, // PCAN: 512 58 | .bInterval = 0, 59 | }, 60 | { 61 | .bLength = USB_DT_ENDPOINT_SIZE, 62 | .bDescriptorType = USB_DT_ENDPOINT, 63 | .bEndpointAddress = 0x83, 64 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 65 | .wMaxPacketSize = 64, 66 | .bInterval = 0, 67 | }, 68 | { 69 | .bLength = USB_DT_ENDPOINT_SIZE, 70 | .bDescriptorType = USB_DT_ENDPOINT, 71 | .bEndpointAddress = 0x03, 72 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 73 | .wMaxPacketSize = 64, // PCAN: 512 74 | .bInterval = 0, 75 | }, 76 | }; 77 | 78 | const struct usb_endpoint_descriptor lin_endp[] = { 79 | { 80 | .bLength = USB_DT_ENDPOINT_SIZE, 81 | .bDescriptorType = USB_DT_ENDPOINT, 82 | .bEndpointAddress = 0x84, 83 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 84 | .wMaxPacketSize = 64, // PCAN: 512 85 | .bInterval = 0, 86 | }, 87 | { 88 | .bLength = USB_DT_ENDPOINT_SIZE, 89 | .bDescriptorType = USB_DT_ENDPOINT, 90 | .bEndpointAddress = 0x04, 91 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 92 | .wMaxPacketSize = 64, // PCAN: 512 93 | .bInterval = 0, 94 | }, 95 | { 96 | .bLength = USB_DT_ENDPOINT_SIZE, 97 | .bDescriptorType = USB_DT_ENDPOINT, 98 | .bEndpointAddress = 0x85, 99 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 100 | .wMaxPacketSize = 64, // PCAN: 512 101 | .bInterval = 0, 102 | }, 103 | { 104 | .bLength = USB_DT_ENDPOINT_SIZE, 105 | .bDescriptorType = USB_DT_ENDPOINT, 106 | .bEndpointAddress = 0x05, 107 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 108 | .wMaxPacketSize = 64, // PCAN: 512 109 | .bInterval = 0, 110 | }, 111 | { 112 | .bLength = USB_DT_ENDPOINT_SIZE, 113 | .bDescriptorType = USB_DT_ENDPOINT, 114 | .bEndpointAddress = 0x86, 115 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 116 | .wMaxPacketSize = 64, 117 | .bInterval = 0, 118 | }, 119 | { 120 | .bLength = USB_DT_ENDPOINT_SIZE, 121 | .bDescriptorType = USB_DT_ENDPOINT, 122 | .bEndpointAddress = 0x06, 123 | .bmAttributes = USB_ENDPOINT_ATTR_BULK, 124 | .wMaxPacketSize = 64, // PCAN: 512 125 | .bInterval = 0, 126 | }, 127 | }; 128 | 129 | static const struct usb_interface_descriptor can_iface[] = {{ 130 | .bLength = USB_DT_INTERFACE_SIZE, 131 | .bDescriptorType = USB_DT_INTERFACE, 132 | .bInterfaceNumber = 0, 133 | .bAlternateSetting = 0, 134 | .bNumEndpoints = 6, 135 | .bInterfaceClass = 0x00, 136 | .bInterfaceSubClass = 0x00, 137 | .bInterfaceProtocol = 0x00, 138 | .iInterface = 5, 139 | 140 | .endpoint = can_endp, 141 | } }; 142 | 143 | static const struct usb_interface_descriptor lin_iface[] = {{ 144 | .bLength = USB_DT_INTERFACE_SIZE, 145 | .bDescriptorType = USB_DT_INTERFACE, 146 | .bInterfaceNumber = 1, 147 | .bAlternateSetting = 0, 148 | .bNumEndpoints = 6, 149 | .bInterfaceClass = 0x00, 150 | .bInterfaceSubClass = 0, 151 | .bInterfaceProtocol = 0, 152 | .iInterface = 6, 153 | 154 | .endpoint = lin_endp, 155 | } }; 156 | 157 | static const struct usb_interface ifaces[] = {{ 158 | .num_altsetting = 1, 159 | .altsetting = can_iface, 160 | }, { 161 | .num_altsetting = 1, 162 | .altsetting = lin_iface, 163 | } }; 164 | 165 | const struct usb_config_descriptor config_descriptor = { 166 | .bLength = USB_DT_CONFIGURATION_SIZE, 167 | .bDescriptorType = USB_DT_CONFIGURATION, 168 | .wTotalLength = 0, // peak: 111 169 | .bNumInterfaces = 1, // peak: 2 170 | .bConfigurationValue = 1, 171 | .iConfiguration = 4, 172 | .bmAttributes = 0x80, 173 | .bMaxPower = 0x5A, // 180mA 174 | 175 | .interface = ifaces, 176 | }; 177 | 178 | const char * usb_strings[6] = { 179 | "PEAK-System Technik GmbH", 180 | "PCAN-USB-PRO DEVICE", 181 | "string2", 182 | "Config00", 183 | "PCAN-USB-PRO-CAN Device", 184 | "PCAN-USB-PRO-LIN Device", 185 | }; 186 | -------------------------------------------------------------------------------- /ppro_usb_descr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * usb_descriptor.h 3 | * 4 | * Created on: 24.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #ifndef PPRO_USB_DESCR_H_ 9 | #define PPRO_USB_DESCR_H_ 10 | 11 | #include 12 | 13 | extern const struct usb_device_descriptor device_descriptor; 14 | extern const struct usb_config_descriptor config_descriptor; 15 | extern const char *usb_strings[6]; 16 | 17 | 18 | #endif /* PPRO_USB_DESCR_H_ */ 19 | -------------------------------------------------------------------------------- /stm32f4-discovery.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * Copyright (C) 2011 Stephen Caudle 6 | * 7 | * This library is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | */ 20 | 21 | /* Linker script for ST STM32F4DISCOVERY (STM32F407VG, 1024K flash, 128K RAM). */ 22 | 23 | /* Define memory regions. */ 24 | MEMORY 25 | { 26 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K 27 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 28 | } 29 | 30 | /* Include the common ld script. */ 31 | INCLUDE libopencm3_stm32f4.ld 32 | 33 | -------------------------------------------------------------------------------- /stm32f407ve.cfg: -------------------------------------------------------------------------------- 1 | # This is an STM32F4 discovery board with a single STM32F407VGT6 chip. 2 | # http://www.st.com/internet/evalboard/product/252419.jsp 3 | 4 | source [find interface/stlink-v2.cfg] 5 | 6 | transport select hla_swd 7 | 8 | source [find target/stm32f4x.cfg] 9 | 10 | #reset_config srst_only 11 | reset_config none separate 12 | -------------------------------------------------------------------------------- /stm32f407vet6.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * Copyright (C) 2011 Stephen Caudle 6 | * 7 | * This library is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | */ 20 | 21 | /* Linker script for ST STM32F4DISCOVERY (STM32F407VG, 1024K flash, 128K RAM). */ 22 | 23 | /* Define memory regions. */ 24 | MEMORY 25 | { 26 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K 27 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 28 | } 29 | 30 | /* Include the common ld script. */ 31 | INCLUDE libopencm3_stm32f4.ld 32 | 33 | -------------------------------------------------------------------------------- /systime.c: -------------------------------------------------------------------------------- 1 | #include "systime.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | volatile uint32_t systick_ms; 9 | static uint32_t cpufreq = 1; 10 | 11 | void sys_tick_handler(void) { 12 | systick_ms++; 13 | } 14 | 15 | void systime_setup(uint32_t cpufreq_kHz) { 16 | cpufreq = cpufreq_kHz; 17 | systick_set_reload(cpufreq_kHz-1); 18 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); 19 | systick_counter_enable(); 20 | systick_interrupt_enable(); 21 | } 22 | 23 | uint32_t get_time_ms(void) { 24 | return systick_ms; 25 | } 26 | 27 | uint32_t get_time_us32(void) { 28 | uint32_t us = 1000ul*systick_ms; 29 | uint32_t ticks = systick_get_value(); 30 | return us + (1000ul*ticks)/cpufreq; 31 | } 32 | 33 | uint64_t get_time_us64(void) { 34 | uint64_t us = 1000ull*systick_ms; 35 | uint32_t ticks = systick_get_value(); 36 | return us + (1000ull*ticks)/cpufreq; 37 | } 38 | 39 | void delay_ms(uint32_t delay) { 40 | uint32_t wake = systick_ms + delay; 41 | while (wake > systick_ms); 42 | } 43 | -------------------------------------------------------------------------------- /systime.h: -------------------------------------------------------------------------------- 1 | /* 2 | * systime.h 3 | * 4 | * Created on: 21.07.2015 5 | * Author: hd 6 | */ 7 | 8 | #ifndef SYSTIME_H_ 9 | #define SYSTIME_H_ 10 | 11 | #include 12 | 13 | void systime_setup(uint32_t cpufreq_kHz); 14 | 15 | uint32_t get_time_ms(void); 16 | uint32_t get_time_us32(void); 17 | uint64_t get_time_us64(void); 18 | 19 | void delay_ms(uint32_t delay); 20 | 21 | #endif /* SYSTIME_H_ */ 22 | -------------------------------------------------------------------------------- /tests/simple_pingpong.py: -------------------------------------------------------------------------------- 1 | __author__ = 'hd' 2 | 3 | import sys 4 | import time 5 | import threading 6 | from socketcan import CanMessage, CanSocket 7 | 8 | do_quit = False 9 | 10 | def can_echo_thread(interface): 11 | echo_sock = CanSocket() 12 | echo_sock.open(interface) 13 | while not do_quit: 14 | msg = echo_sock.read(0.1) 15 | if msg is not None: 16 | echo_sock.send(msg) 17 | 18 | 19 | if_master = sys.argv[1] 20 | if_slave = sys.argv[2] 21 | iterations = int(sys.argv[3]) 22 | 23 | echo_thread = threading.Thread(target=can_echo_thread, args=(if_slave,)) 24 | echo_thread.start() 25 | 26 | sock = CanSocket() 27 | sock.open(if_master) 28 | msg = CanMessage(0x13371010, [0,0,0,0,0,0,0,0]) 29 | 30 | t_start = time.time() 31 | 32 | for i in range(0, iterations): 33 | sock.send(msg) 34 | msg = sock.read() 35 | x = msg.data[0] 36 | msg.data[0] = (x+1) % 256 37 | 38 | t_finish = time.time() 39 | do_quit = True 40 | 41 | print("\n\nsent and received %d messages in %f seconds." % (iterations, t_finish-t_start)) 42 | -------------------------------------------------------------------------------- /tests/socketcan/__init__.py: -------------------------------------------------------------------------------- 1 | from socketcan.canmessage import CanMessage 2 | from socketcan.cansocket import CanSocket 3 | -------------------------------------------------------------------------------- /tests/socketcan/canmessage.py: -------------------------------------------------------------------------------- 1 | __author__ = 'hd' 2 | 3 | import struct 4 | 5 | class CanMessage: 6 | # CAN frame packing/unpacking (see `struct can_frame` in ) 7 | frame_fmt = "=IB3x8s" 8 | 9 | def __init__(self, id, data=[], is_extended=False, is_rtr=False): 10 | self.id = id & 0x1FFFFFFF 11 | self.is_extended = is_extended or ((id & 0x80000000) != 0) 12 | self.is_rtr = is_rtr or ((id & 0x40000000) != 0) 13 | self.data = data 14 | 15 | def from_raw(frame): 16 | id, dlc, data = struct.unpack(CanMessage.frame_fmt, frame) 17 | data_arr = [] 18 | for x in data[:dlc]: 19 | data_arr.append(x) 20 | return CanMessage(id, data_arr) 21 | 22 | def to_raw(self): 23 | id = self.id 24 | if self.is_extended: 25 | id |= 0x80000000 26 | if self.is_rtr: 27 | id |= 0x40000000 28 | dlc = len(self.data) 29 | bdata = bytearray() 30 | for x in self.data: 31 | bdata.append(x) 32 | return struct.pack(CanMessage.frame_fmt, id, dlc, bdata.ljust(8, b'\x00')) 33 | -------------------------------------------------------------------------------- /tests/socketcan/canmessage.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bytewerk/pcan_stm32/60ef93c9c1515898eef3dd98b04c39be6cd2da18/tests/socketcan/canmessage.pyc -------------------------------------------------------------------------------- /tests/socketcan/cansocket.py: -------------------------------------------------------------------------------- 1 | __author__ = 'hd' 2 | 3 | import socket 4 | from socketcan import CanMessage 5 | 6 | class CanSocket: 7 | 8 | def __init__(self): 9 | self.sock = None 10 | 11 | def open(self, interface): 12 | self.sock = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW) 13 | self.sock.bind((interface,)) 14 | 15 | def close(self): 16 | self.sock.close() 17 | 18 | def read(self, timeout=None): 19 | self.sock.settimeout(timeout) 20 | try: 21 | frame, addr = self.sock.recvfrom(16) 22 | return CanMessage.from_raw(frame) 23 | except socket.timeout: 24 | return None 25 | 26 | def send(self, msg): 27 | self.sock.send(msg.to_raw()) 28 | --------------------------------------------------------------------------------