├── .gitignore ├── LICENSE ├── README.md ├── XBOX.md ├── firmware ├── README.md ├── xenium.ucf ├── xeniumflash.v └── xeniumflash.xise ├── hardware └── RaspberryPIZero │ ├── LICENSE │ ├── images │ ├── rpi-bottom.png │ ├── rpi-top-scaled.png │ └── rpi-top.png │ ├── xenium-programmer-rpi.brd │ ├── xenium-programmer-rpi.sch │ └── xenium-programmer-rpi_2021-01-20_Gerbers_Rev_B.zip ├── images ├── bitbus.png ├── bitbus2flash.png ├── boot.png ├── connections-omega.png ├── connections-pi.png ├── five-bucks.png ├── lpc-bus.png ├── mcpx-lpc.png ├── openxenium.jpg ├── openxenium2.jpg ├── pi-spi.jpg ├── pi-wifi.png ├── pinout-omega.png ├── pinout-pi.png ├── sshot.png ├── xenium-flash.jpg ├── xenium-os.jpg ├── xenium-programmer-wiring.xcf └── xilinx-programmer.jpg ├── install ├── pi-remote-access ├── README.md ├── ssh └── wpa_supplicant.conf ├── xenium-bin ├── openxenium.jed ├── xenium_blue.bin ├── xenium_gold.bin ├── xenium_ice.bin └── xeniumflash.jed ├── xenium-flash ├── Makefile ├── README.md └── src │ ├── XeniumDefines.h │ ├── flash │ ├── BitBus.cpp │ ├── BitBus.hpp │ ├── BitBusOmega2.cpp │ ├── BitBusOmega2.hpp │ ├── BitBusPI.cpp │ ├── BitBusPI.hpp │ ├── Flash.cpp │ └── Flash.hpp │ ├── jtag │ ├── IOBase.cpp │ ├── IOBase.h │ ├── IOOmega2.cpp │ ├── IOOmega2.h │ ├── IOWiringPi.cpp │ ├── IOWiringPi.h │ ├── IOXenium.h │ ├── JedecFile.cpp │ ├── JedecFile.h │ ├── Jtag.cpp │ ├── Jtag.h │ ├── ProgAlgXC95X.cpp │ ├── ProgAlgXC95X.h │ └── io_exception.h │ ├── omega2-gpio │ ├── FastGpioOmega2.cpp │ ├── FastGpioOmega2.hpp │ ├── Module.cpp │ └── Module.hpp │ ├── xenium-flash.cpp │ └── xenium-jtag.cpp ├── xenium-programmer └── xenium-programmer-pi /.gitignore: -------------------------------------------------------------------------------- 1 | *.lso 2 | *.cmd_log 3 | *.spl 4 | *.xreport 5 | *.jhd 6 | *.prj 7 | *.stx 8 | *.gise 9 | *.html 10 | *.schlog 11 | *.xst 12 | *.vho 13 | *.xmsgs 14 | *.ref 15 | *.bld 16 | *.chk 17 | *.cxt 18 | *.gyd 19 | *.log 20 | *.mfd 21 | *.nga 22 | *.ngc 23 | *.ngd 24 | *.ngr 25 | *.pad 26 | *.pnx 27 | *.rpt 28 | *.syr 29 | *.tim 30 | *.tspec 31 | *.vhf 32 | *.vm6 33 | *.xml 34 | *.js 35 | *.htm 36 | *.tmp 37 | *.gif 38 | *.css 39 | *.xrpt 40 | *.csv 41 | *.dat 42 | *.phd 43 | *.err 44 | *.xbcd 45 | *.lst 46 | *.projectmgr 47 | *.cmd 48 | *.symlog 49 | *.txt 50 | *.ipf 51 | *.cmd_log 52 | *_xdb 53 | *.mod 54 | *.data 55 | *.blx 56 | sch2HdlBatchFile 57 | main_html 58 | _xmsgs 59 | _ngo 60 | xst 61 | iseconfig 62 | xc3sprog 63 | .vscode 64 | xenium-flash/bin 65 | 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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 | 294 | Copyright (C) 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 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenXenium JTAG and Flash Memory programmer 2 | 3 | ## * Read: ["Home Brew" on ORIGINAL XBOX](XBOX.md) - a detailed article on why and how * 4 | 5 | ![xenium-programmer](images/xenium-flash.jpg) 6 | 7 | The tools in this repo will allow you to use a Raspberry PI or an Onion Omega2+ to program an OpenXenium chip with the Xilinx CPLD Firmware via JTAG and will also upload XeniumOS images into the OpenXenium Flash memory via a custom 4-bit bus NOR Flash programming protocol. 8 | 9 | 10 | ### Raspberry PI [UPDATED to support latest Raspberry PI OS (Bullseye)] : 11 | - This has only been tested on PI Zero W and PI 3B+ model, but should work for all. 12 | 13 | https://www.pishop.us/product/raspberry-pi-zero-w 14 | 15 | https://www.pishop.us/product/raspberry-pi-zero-2-w 16 | 17 | ### Onion Omega2+: 18 | - This has been tested and works on the Onion Omega2+. 19 | 20 | https://Onion.io/store/omega2p 21 | 22 | ------------- 23 | ## INSTALLING THE XENIUM PROGRAMMER 24 | 25 | - Connect to the PI or Omega via SSH or Serial terminal 26 | - Clone this repo by running: `git clone https://github.com/kooscode/xenium-programmer.git` 27 | - Change Dir to cloned repo: `cd xenium-programmer` 28 | - Then run: `./install` 29 | 30 | ## UPDATING XENIUM PROGRAMMER 31 | 32 | - Connect to the PI or Omega via SSH or Serial terminal 33 | - Change dir to xenium-programmer and pull the latest code with: `git pull` 34 | - Then run: `./install` 35 | 36 | ------------- 37 | ## PROGRAMMING A XENIUM CPLD AND FLASH MEMORY 38 | 39 | - Connect to the PI or Omega via SSH or Serial terminal 40 | - You can program XeniumOS and OpenXenium Firmware in one single step. 41 | - Run: `./xenium-programmer` 42 | 43 | ![jtag-pinout](images/sshot.png) 44 | 45 | ------------- 46 | ## HOOKING UP THE HARDWARE 47 | 48 | - The JTAG and FLASH pins are configurable by editing the `XeniumDefines.h` file 49 | - If you edited the `XeniumDefines.h` file, make sure to run `./install` again 50 | 51 | -------------- 52 | ## [ RASPBERRY PI ] 53 | 54 | ![jtag-pinout](images/connections-pi.png) 55 | 56 | ![bitbus-pinout](images/pinout-pi.png) 57 | 58 | ### PC BOARD 59 | 60 | Huge thanks to James Bolding for the Eagle PCB hardware design. He made a kick-ass Schematic and PCB that you can make for the Raspberry PI Zero based programmer! 61 | 62 | - You can use the FREE Eagle PCB to load this up or just use the gerber files to have the PCB made at OSH Park! 63 | 64 | ![RPI PXB](hardware/RaspberryPIZero/images/rpi-top-scaled.png) 65 | 66 | -------------- 67 | ## [ ONION OMEGA2+ ] 68 | 69 | ![jtag-pinout](images/connections-omega.png) 70 | 71 | ![bitbus-pinout](images/pinout-omega.png) 72 | 73 | ------------- 74 | ## CREDITS 75 | 76 | - Koos du Preez - Creator (kdupreez@hotmail.com - Comments, improvements, critique, etc. is welcome!) 77 | - James Bolding - Kick ass awesome hardware design and PCB! 78 | - Ryzee119 - OpenXenium Firmware and hardware and all round awesomeness! 79 | - XC3SPROG - Not sure who to thank here, but the source code was pivotal in making this work! 80 | -------------------------------------------------------------------------------- /XBOX.md: -------------------------------------------------------------------------------- 1 | # "Home Brew" on ORIGINAL XBOX 2 | 3 | I have always wanted to run old extinct arcade games and home-brew on my original xbox systems and in order to do that, you need to "unlock" its potential via a external chip that allows for 3rd party home-brew software like the Arcade Emulator I want to run to show my kiddos how the old man played games when he was 9yrs old.. I was very curious how these mod chips work and how you can program them and build them from scratch.. so here follows my journey to understand the resurect my old original 20 year old XBOX and use a home build a chip so I can run my Arcade Emulators to kick my 9yr old's ass in at least some games. 4 | 5 | ## How does an "Original XBOX Mod" chip work? 6 | Running unsigned code on the Original XBOX has been around for almost the entire 20 years of the console's existence. Here is a very high level explanation of how modern mod chips force an external BIOS to load on Original XBOX. 7 | 8 | - The Original Xbox (OGX) is a plain vanilla Intel CPU and NVidia GPU system and runs a watered down Windows-based Kernel. So for all practical purposes was modeled after a Windows PC. 9 | 10 | - The Kernel, along with boot loaders, are encrypted and stored onboard a Flash chip, termed the "TSOP" chip. 11 | 12 | - When the System starts up, the South Bridge (MCPX) has hard coded instructions to load the BIOS from the TSOP chip, validate signatures and start boot loader execution. If your BIOS is not signed by MS and does not match the hardware embedded signature, the MCPX will abort. 13 | 14 | - One small (but very important) detail is that the MCPX will check the value of bit 0 at address 0 of the TSOP and if it has the value 0, it will abandon loading the BIOS from TSOP and will instead revert to loading a BIOS from the onboard Low Pin Count (LPC) bus! 15 | 16 | - So, by grounding the TSOP chip Data 0 line (D0) you can force a 0 value on bit 0 at address 0 and the MCPX will load a BIOS externally! This works on all OGX motherboard revisions 1.0 - 1.4 17 | 18 | - Microsoft finally this loophole with the OGX 1.6 motherboard and completely removed the TSOP chip and embedded a BIOS in their own custom silicon that ONLY loads via LPC bus. But they were also nice enough to honor the LPC Abort signals, so you can easily abort the onboard LPC BIOS on startup and again inject your own via the LPC bus.. 19 | 20 | - So - What does a mod chip do? Well, its pretty easy, it simply asserts D0 to ground on motherboard revision 1.0-1.4 boards or it aborts the onboard LPC BIOS on 1.6 boards and makes its own BIOS available on the LPC bus for the MCPX to load! 21 | 22 | ## How do you inject a BIOS on the LPC bus? 23 | 24 | 25 | The OGX BIOS is only 256kb in size and although the MCPX loads the top 16MB via the LPC bus, its really the same 256kb repeated x64 times. Some of the very first LPC mod chips were simply just SST-49LF040A LPC based 256kb flash memory chips that you connected directly to the motherboard LPC bus and grounded TSOP pin D0 to force the MCPX to load the BIOS from your external chip! The 1.6 version board requires a Quick Solder Board (QSB) to re-instate some removed LPC bus wires Microsoft removed, but you can still do this on 1.6 boards with some wiring tricks. 26 | 27 | More modern mod chips however does a very clever trick where they store a larger or even multuple BIOS images in a large NOR parallel flash chip that requires 21-Address + 8-Data + 2-Control pins to read data. These clever mod chips then employ a Complex Programmable Logic Device (CPLD) in the between the parallel NOR flash and the LPC bus to act as a bridge between the two!! Essentially the CPLD takes incoming LPC protocol requests and translates them to parallel NOR flash requests and vice versa.. The MCPX all the while thinks it is speaking to a LPC chip and doesnt know the difference!! 28 | 29 | ![mcpx-lpc](images/mcpx-lpc.png) 30 | 31 | ## OpenXenium by Ryzee119 32 | 33 | One such "modern" mod chip was the Xenium that sported a 1MB parallel flash (enough for 4x256kb BIOS or 2x512kb or 1x1mb or any combaniation of these) and a Xilinx CPLD in the middle to do the LPC translation. Unfortunately after 20 years it became extinct and is no longer available. But, thanks to the VERY clever work by the super talented Ryzee119 (who reverse engineered this mod chip entirely from scratch), we today have the "Open Xenium" that is a 100% complete version of the original Xenium mod chip! And to top it all, its completely free Open Source!! 34 | 35 | ![Open Xenium Installed](https://github.com/Ryzee119/OpenXenium/blob/master/Images/20191018_212705.jpg?raw=true) 36 | 37 | THANKS RYZEE119!!!! 38 | 39 | See: https://github.com/kooscode/OpenXenium 40 | 41 | 42 | ------------- 43 | ## Programming the OpenXenium 44 | 45 | ![xilinx-programmer](images/xilinx-programmer.jpg) 46 | 47 | Ryzee119 provides the Xilinx CPLD's source code for LPC translation, but you still need to implement/compile the VHDL source code into a bitsream for the CPLD and then program that into the CPLD via a JTAG programmer (Think of it as compiling and uploading the CPLD firmware) And on top of that, once the Xilinx CPLD is programmed, you need to also upload the BIOS image into the paralel NOR Flash chip. 48 | 49 | - Uploading the CPLD firmware can be done using a a select few JTAG programmers, but the official Xilinx programmers are expensive (about $250) and hard to use and most people do not have access to them. 50 | 51 | - Uploading the BIOS to Flash memory can be done prior to installing the chip on the Xenium board via NOR Flash programmer, but that is also expensive (about $60), cumbersome and most people do not have access to programmers or the bare Flash chip prior to it being soldered onto the Xenium board.. 52 | 53 | - You can also upload the BIOS via an already modded XBOX by hot swapping an existing LPC mod chip with a blank OpenXenium chip and using Ryzee119's xenium-tools, but that kinda defeats the purpose of using an already modded XBOX. 54 | 55 | ------------- 56 | ## The $5 JTAG and Parallel NOR Flash programmer!! 57 | 58 | ![xilinx-programmer](images/five-bucks.png) 59 | 60 | I recently ran across a web article that showed JTAG programming a Xilinx FPGA via a Raspberry PI using a tool called XC3SPROG and I thought that would be a great platform to program a Xenium's CPLD !! 61 | 62 | I extracted pieces from XC3SPROG source code that will allow JTAG programming of just the Xenium CPLD and it worked fantastic! I can JTAG program the Xilinx CPLD in 12 seconds flat!! 63 | 64 | So, I set about looking at how to bit-bang LPC through the Raspberry PI's GPIO ports and program Xenium Flash memory. 65 | 66 | This turned out to be a little harder and very slow.. I could not get less than about 10 minutes of programming time and finally abandoned that idea.. 67 | 68 | So, then I tried implementing a SPI Slave in Verilog HDL, so instead of OGX's LPC bus, I can turn the Xenium CPLD into the more common SPI to NOR Flash bridge/translator. The Xenium Already had a nifty SPI connector that I could re-use too! 69 | 70 | ![pi-programmer](images/pi-spi.jpg) 71 | 72 | This worked really great, except it was SLOOOOW... The problem is that the Xenium CPLD does not have an onboard oscillator and relies on the XBOX LPC 33Mhz Clock and i tried feeding it a clock from the PI's GPIO ports, but could never get above 8Mhz clock and 1Mhz SPI bus.. And since SPI is essentially a 1-bit bus, it took about 8 minutes to program the 1MB of flash via SPI. So sad.. 73 | 74 | Back to the drawing board!!... 75 | 76 | ## A Fast 4-bit parallel "BitBus" 77 | 78 | ![pi-programmer](images/bitbus2flash.png) 79 | 80 | I decided to re-purpose the LPC bus header and write Verilog HDL code that will stream 4-bits at a time and translate that directly into the parallel flash programming/reading sequences. Think of it as a shift register, but instead of shifting 1-bit at a time for the 21-bit address and 8-bit data (29-bits), i would just bang 4-bits in/out at a time and can clock the 4-bit data in/out manually and control direction via seperate GPIO pins.. The LPC header exposes 7 pins in the CPLD, so I should have plently of re-usable pins! 81 | 82 | I dubbed thee "BitBus" and was able to move data in and out of the flash pretty speedily.. I then wrote an app (xenium-flash) in C++ for the PI to control and upload data using GPIO pins to the Xenium Flash via the "BitBus" CPLD translator in the middle and a decent speed. 83 | 84 | ### Woohoo!! Now I can program the Xenium CPLD and the Flash Memory!! 85 | 86 | ![pi-programmer](images/bitbus.png) 87 | 88 | - I used the `XC3SPROG` tool to program the CPLD with my "BitBus CPLD" firmware 89 | - Then I used my `xenium-flash` tool to upload the flash image to the Xenium Flash memory via my custom fast 4-bit "BitBus" 90 | - And finally, I used the `XC3SPROG` tool again to program the Xilinx CPLD with Ryzee119's OpenXenium Firmware!! 91 | 92 | ### BOOM! We have lift off!!! 93 | 94 | ![Xenium-OS](images/xenium-os.jpg) 95 | 96 | -------------------------------------------------------------------------------- /firmware/README.md: -------------------------------------------------------------------------------- 1 | # Xenium Flash Firmware 2 | 3 | ### This is the Verilog source code for the Xenium Flash Memory programming. 4 | 5 | - Its fairly straight forward, the CPLD acts as a bridge between the Raspberry PI (or any other device) and the OpenXenium Flash memory and translates writing and reading instructions from a single 4-bit bus to a 21-bit Address + 8-bit bus. 6 | -------------------------------------------------------------------------------- /firmware/xenium.ucf: -------------------------------------------------------------------------------- 1 | #OPENXENIUM - XC9572XL-VQ64-10 2 | 3 | # ************* LED ************** 4 | NET "led<0>" LOC="P10"; 5 | NET "led<1>" LOC="P11"; 6 | NET "led<2>" LOC="P12"; 7 | 8 | # ********** bitbus ************** 9 | NET "bitbus_data<0>" LOC="P22"; 10 | NET "bitbus_data<1>" LOC="P24"; 11 | NET "bitbus_data<2>" LOC="P25"; 12 | NET "bitbus_data<3>" LOC="P23"; 13 | NET "bitbus_mode" LOC="P19"; 14 | NET "bitbus_clk" LOC="P17" | BUFG=DATA_GATE; #Repurpose GCLK 15 | #NET "not_connected" LOC="P20: #LFRAME goes to D0 on 1.6 16 | 17 | # ************* FLASH ************ 18 | # Address 19 | NET "flash_addr<0>" LOC="P47"; 20 | NET "flash_addr<1>" LOC="P35"; 21 | NET "flash_addr<2>" LOC="P1"; 22 | NET "flash_addr<3>" LOC="P2"; 23 | NET "flash_addr<4>" LOC="P4"; 24 | NET "flash_addr<5>" LOC="P5"; 25 | NET "flash_addr<6>" LOC="P64"; 26 | NET "flash_addr<7>" LOC="P63"; 27 | NET "flash_addr<8>" LOC="P62"; 28 | NET "flash_addr<9>" LOC="P59"; 29 | NET "flash_addr<10>" LOC="P58"; 30 | NET "flash_addr<11>" LOC="P57"; 31 | NET "flash_addr<12>" LOC="P56"; 32 | NET "flash_addr<13>" LOC="P52"; 33 | NET "flash_addr<14>" LOC="P51"; 34 | NET "flash_addr<15>" LOC="P50"; 35 | NET "flash_addr<16>" LOC="P49"; 36 | NET "flash_addr<17>" LOC="P48"; 37 | NET "flash_addr<18>" LOC="P61"; 38 | NET "flash_addr<19>" LOC="P60"; 39 | NET "flash_addr<20>" LOC="P9"; 40 | 41 | # Data 42 | NET "flash_data<0>" LOC="P38"; 43 | NET "flash_data<1>" LOC="P39"; 44 | NET "flash_data<2>" LOC="P40"; 45 | NET "flash_data<3>" LOC="P42"; 46 | NET "flash_data<4>" LOC="P43"; 47 | NET "flash_data<5>" LOC="P44"; 48 | NET "flash_data<6>" LOC="P45"; 49 | NET "flash_data<7>" LOC="P46"; 50 | 51 | # Control 52 | NET "flash_oe" LOC="P36"; 53 | NET "flash_we" LOC="P7"; 54 | 55 | 56 | -------------------------------------------------------------------------------- /firmware/xeniumflash.v: -------------------------------------------------------------------------------- 1 | /* 4-bit "BitBus" to Flash translator for OpenXenium 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | 21 | module xeniumflash( 22 | // led 23 | output reg [2:0] led, 24 | 25 | //bitbus in/out 26 | inout [3:0] bitbus_data, 27 | input bitbus_clk, 28 | input bitbus_mode, 29 | 30 | //flash in/out 31 | output [20:0] flash_addr, 32 | inout [7:0] flash_data, 33 | output reg flash_oe, 34 | output reg flash_we 35 | ); 36 | 37 | // state machine 38 | `define flash_addr_3_0 0 39 | `define flash_addr_7_4 1 40 | `define flash_addr_11_8 2 41 | `define flash_addr_15_12 3 42 | `define flash_addr_19_16 4 43 | `define flash_addr_23_20 5 44 | `define flash_addr_end 6 45 | `define flash_data_3_0 7 46 | `define flash_data_7_4 8 47 | `define flash_data_end 9 48 | reg [4:0] flash_state; 49 | // bitbus 50 | reg [3:0] bitbus_data_d; 51 | reg bitbus_mode_q; 52 | // flash 53 | reg [20:0] flash_addr_d; 54 | reg [7:0] flash_data_d; 55 | 56 | //initialization 57 | initial begin 58 | //internal state 59 | flash_state = 5'b`flash_addr_3_0; 60 | led = 3'b001; //led[R|G|B] 61 | //flash 62 | flash_addr_d = 21'b0; 63 | flash_data_d = 8'b0; 64 | flash_oe = 1'b1; 65 | flash_we = 1'b1; 66 | //bitbus 67 | bitbus_data_d = 4'b0; 68 | bitbus_mode_q = 1'b0; 69 | end 70 | 71 | // flash assigns 72 | assign flash_addr = flash_addr_d; 73 | assign flash_data[7:0] = (flash_we == 0) ? flash_data_d[7:0] : 8'bZ; 74 | //bitbus assigns 75 | assign bitbus_data = (flash_oe == 0) ? bitbus_data_d[3:0] : 4'bZ; 76 | 77 | // process bitbus clock 78 | always @(posedge bitbus_clk) 79 | begin 80 | // change in modes = reset 81 | if (bitbus_mode_q != bitbus_mode) 82 | begin 83 | // state reset 84 | flash_state <= `flash_addr_3_0; 85 | led <= 3'b001; 86 | //bitbus reset 87 | bitbus_mode_q <= bitbus_mode; 88 | //flash reset 89 | flash_oe <= 1; 90 | flash_we <= 1; 91 | end 92 | // if not reset traverse through state machine 93 | // once per bitbus clock to set address and data. 94 | else 95 | begin 96 | // green = read, red = write 97 | led[0] <= 0; 98 | led[1] <= bitbus_mode; 99 | led[2] <= ~bitbus_mode; 100 | case (flash_state) 101 | // clock lower nibble of address byte 1 102 | `flash_addr_3_0: begin 103 | flash_addr_d[3:0] <= bitbus_data[3:0]; 104 | flash_state <= `flash_addr_7_4; 105 | end 106 | // clock upper nibble of address byte 1 107 | `flash_addr_7_4: begin 108 | flash_addr_d[7:4] <= bitbus_data[3:0]; 109 | flash_state <= `flash_addr_11_8; 110 | end 111 | // clock lower nibble of address byte 2 112 | `flash_addr_11_8: begin 113 | flash_addr_d[11:8] <= bitbus_data[3:0]; 114 | flash_state <= `flash_addr_15_12; 115 | end 116 | // clock upper nibble of address byte 2 117 | `flash_addr_15_12: begin 118 | flash_addr_d[15:12] <= bitbus_data[3:0]; 119 | flash_state <= `flash_addr_19_16; 120 | end 121 | // clock lower nibble of address byte 3 122 | `flash_addr_19_16: begin 123 | flash_addr_d[19:16] <= bitbus_data[3:0]; 124 | flash_state <= `flash_addr_23_20; 125 | end 126 | // clock upper nibble of address byte 3 127 | `flash_addr_23_20: begin 128 | flash_addr_d[20] <= bitbus_data[0]; 129 | flash_state <= `flash_addr_end; 130 | end 131 | //clock WE and OE 132 | `flash_addr_end: begin 133 | flash_we <= bitbus_mode; 134 | flash_oe <= ~bitbus_mode; 135 | flash_state <= `flash_data_3_0; 136 | end 137 | // clock lower nibble of data byte 138 | `flash_data_3_0: begin 139 | if (bitbus_mode==0) 140 | flash_data_d[3:0] <= bitbus_data[3:0]; //WRITE 141 | else 142 | bitbus_data_d[3:0] <= flash_data[3:0]; //READ 143 | flash_state <= `flash_data_7_4; 144 | end 145 | // clock upper nibble of data byte 146 | `flash_data_7_4: begin 147 | if (bitbus_mode==0) 148 | flash_data_d[7:4] <= bitbus_data[3:0]; //WRITE 149 | else 150 | bitbus_data_d[3:0] <= flash_data[7:4]; //READ 151 | flash_state <= `flash_data_end; 152 | end 153 | //clock WE and OE 154 | `flash_data_end: begin 155 | flash_oe <= 1; 156 | flash_we <= 1; 157 | flash_state <= `flash_addr_3_0; 158 | end 159 | endcase 160 | end //end else change in dir 161 | end // and always bitbus clock 162 | 163 | endmodule 164 | -------------------------------------------------------------------------------- /firmware/xeniumflash.xise: -------------------------------------------------------------------------------- 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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 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 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 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 |
240 | -------------------------------------------------------------------------------- /hardware/RaspberryPIZero/LICENSE: -------------------------------------------------------------------------------- 1 | CERN Open Hardware Licence v1.2 2 | 3 | Preamble 4 | 5 | Through this CERN Open Hardware Licence ("CERN OHL") version 1.2, CERN 6 | wishes to provide a tool to foster collaboration and sharing among 7 | hardware designers. The CERN OHL is copyright CERN. Anyone is welcome 8 | to use the CERN OHL, in unmodified form only, for the distribution of 9 | their own Open Hardware designs. Any other right is reserved. Release 10 | of hardware designs under the CERN OHL does not constitute an 11 | endorsement of the licensor or its designs nor does it imply any 12 | involvement by CERN in the development of such designs. 13 | 14 | 1. Definitions 15 | 16 | In this Licence, the following terms have the following meanings: 17 | 18 | “Licence” means this CERN OHL. 19 | 20 | “Documentation” means schematic diagrams, designs, circuit or circuit 21 | board layouts, mechanical drawings, flow charts and descriptive text, 22 | and other explanatory material that is explicitly stated as being made 23 | available under the conditions of this Licence. The Documentation may 24 | be in any medium, including but not limited to computer files and 25 | representations on paper, film, or any other media. 26 | 27 | “Documentation Location” means a location where the Licensor has 28 | placed Documentation, and which he believes will be publicly 29 | accessible for at least three years from the first communication to 30 | the public or distribution of Documentation. 31 | 32 | “Product” means either an entire, or any part of a, device built using 33 | the Documentation or the modified Documentation. 34 | 35 | “Licensee” means any natural or legal person exercising rights under 36 | this Licence. 37 | 38 | “Licensor” means any natural or legal person that creates or modifies 39 | Documentation and subsequently communicates to the public and/ or 40 | distributes the resulting Documentation under the terms and conditions 41 | of this Licence. 42 | 43 | A Licensee may at the same time be a Licensor, and vice versa. 44 | 45 | Use of the masculine gender includes the feminine and neuter genders 46 | and is employed solely to facilitate reading. 47 | 48 | 2. Applicability 49 | 50 | 2.1. This Licence governs the use, copying, modification, 51 | communication to the public and distribution of the Documentation, and 52 | the manufacture and distribution of Products. By exercising any right 53 | granted under this Licence, the Licensee irrevocably accepts these 54 | terms and conditions. 55 | 56 | 2.2. This Licence is granted by the Licensor directly to the Licensee, 57 | and shall apply worldwide and without limitation in time. The Licensee 58 | may assign his licence rights or grant sub-licences. 59 | 60 | 2.3. This Licence does not extend to software, firmware, or code 61 | loaded into programmable devices which may be used in conjunction with 62 | the Documentation, the modified Documentation or with Products, unless 63 | such software, firmware, or code is explicitly expressed to be subject 64 | to this Licence. The use of such software, firmware, or code is 65 | otherwise subject to the applicable licence terms and conditions. 66 | 67 | 3. Copying, modification, communication to the public and distribution 68 | of the Documentation 69 | 70 | 3.1. The Licensee shall keep intact all copyright and trademarks 71 | notices, all notices referring to Documentation Location, and all 72 | notices that refer to this Licence and to the disclaimer of warranties 73 | that are included in the Documentation. He shall include a copy 74 | thereof in every copy of the Documentation or, as the case may be, 75 | modified Documentation, that he communicates to the public or 76 | distributes. 77 | 78 | 3.2. The Licensee may copy, communicate to the public and distribute 79 | verbatim copies of the Documentation, in any medium, subject to the 80 | requirements specified in section 3.1. 81 | 82 | 3.3. The Licensee may modify the Documentation or any portion thereof 83 | provided that upon modification of the Documentation, the Licensee 84 | shall make the modified Documentation available from a Documentation 85 | Location such that it can be easily located by an original Licensor 86 | once the Licensee communicates to the public or distributes the 87 | modified Documentation under section 3.4, and, where required by 88 | section 4.1, by a recipient of a Product. However, the Licensor shall 89 | not assert his rights under the foregoing proviso unless or until a 90 | Product is distributed. 91 | 92 | 3.4. The Licensee may communicate to the public and distribute the 93 | modified Documentation (thereby in addition to being a Licensee also 94 | becoming a Licensor), always provided that he shall: 95 | 96 | a) comply with section 3.1; 97 | 98 | b) cause the modified Documentation to carry prominent notices stating 99 | that the Licensee has modified the Documentation, with the date and 100 | description of the modifications; 101 | 102 | c) cause the modified Documentation to carry a new Documentation 103 | Location notice if the original Documentation provided for one; 104 | 105 | d) make available the modified Documentation at the same level of 106 | abstraction as that of the Documentation, in the preferred format for 107 | making modifications to it (e.g. the native format of the CAD tool as 108 | applicable), and in the event that format is proprietary, in a format 109 | viewable with a tool licensed under an OSI-approved license if the 110 | proprietary tool can create it; and 111 | 112 | e) license the modified Documentation under the terms and conditions 113 | of this Licence or, where applicable, a later version of this Licence 114 | as may be issued by CERN. 115 | 116 | 3.5. The Licence includes a non-exclusive licence to those patents or 117 | registered designs that are held by, under the control of, or 118 | sub-licensable by the Licensor, to the extent necessary to make use of 119 | the rights granted under this Licence. The scope of this section 3.5 120 | shall be strictly limited to the parts of the Documentation or 121 | modified Documentation created by the Licensor. 122 | 123 | 4. Manufacture and distribution of Products 124 | 125 | 4.1. The Licensee may manufacture or distribute Products always 126 | provided that, where such manufacture or distribution requires a 127 | licence under this Licence the Licensee provides to each recipient of 128 | such Products an easy means of accessing a copy of the Documentation 129 | or modified Documentation, as applicable, as set out in section 3. 130 | 131 | 4.2. The Licensee is invited to inform any Licensor who has indicated 132 | his wish to receive this information about the type, quantity and 133 | dates of production of Products the Licensee has (had) manufactured 134 | 135 | 5. Warranty and liability 136 | 137 | 5.1. DISCLAIMER – The Documentation and any modified Documentation are 138 | provided "as is" and any express or implied warranties, including, but 139 | not limited to, implied warranties of merchantability, of satisfactory 140 | quality, non-infringement of third party rights, and fitness for a 141 | particular purpose or use are disclaimed in respect of the 142 | Documentation, the modified Documentation or any Product. The Licensor 143 | makes no representation that the Documentation, modified 144 | Documentation, or any Product, does or will not infringe any patent, 145 | copyright, trade secret or other proprietary right. The entire risk as 146 | to the use, quality, and performance of a Product shall be with the 147 | Licensee and not the Licensor. This disclaimer of warranty is an 148 | essential part of this Licence and a condition for the grant of any 149 | rights granted under this Licence. The Licensee warrants that it does 150 | not act in a consumer capacity. 151 | 152 | 5.2. LIMITATION OF LIABILITY – The Licensor shall have no liability 153 | for direct, indirect, special, incidental, consequential, exemplary, 154 | punitive or other damages of any character including, without 155 | limitation, procurement of substitute goods or services, loss of use, 156 | data or profits, or business interruption, however caused and on any 157 | theory of contract, warranty, tort (including negligence), product 158 | liability or otherwise, arising in any way in relation to the 159 | Documentation, modified Documentation and/or the use, manufacture or 160 | distribution of a Product, even if advised of the possibility of such 161 | damages, and the Licensee shall hold the Licensor(s) free and harmless 162 | from any liability, costs, damages, fees and expenses, including 163 | claims by third parties, in relation to such use. 164 | 165 | 6. General 166 | 167 | 6.1. Except for the rights explicitly granted hereunder, this Licence 168 | does not imply or represent any transfer or assignment of intellectual 169 | property rights to the Licensee. 170 | 171 | 6.2. The Licensee shall not use or make reference to any of the names 172 | (including acronyms and abbreviations), images, or logos under which 173 | the Licensor is known, save in so far as required to comply with 174 | section 3. Any such permitted use or reference shall be factual and 175 | shall in no event suggest any kind of endorsement by the Licensor or 176 | its personnel of the modified Documentation or any Product, or any 177 | kind of implication by the Licensor or its personnel in the 178 | preparation of the modified Documentation or Product. 179 | 180 | 6.3. CERN may publish updated versions of this Licence which retain 181 | the same general provisions as this version, but differ in detail so 182 | far this is required and reasonable. New versions will be published 183 | with a unique version number. 184 | 185 | 6.4. This Licence shall terminate with immediate effect, upon written 186 | notice and without involvement of a court if the Licensee fails to 187 | comply with any of its terms and conditions, or if the Licensee 188 | initiates legal action against Licensor in relation to this 189 | Licence. Section 5 shall continue to apply. -------------------------------------------------------------------------------- /hardware/RaspberryPIZero/images/rpi-bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/hardware/RaspberryPIZero/images/rpi-bottom.png -------------------------------------------------------------------------------- /hardware/RaspberryPIZero/images/rpi-top-scaled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/hardware/RaspberryPIZero/images/rpi-top-scaled.png -------------------------------------------------------------------------------- /hardware/RaspberryPIZero/images/rpi-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/hardware/RaspberryPIZero/images/rpi-top.png -------------------------------------------------------------------------------- /hardware/RaspberryPIZero/xenium-programmer-rpi_2021-01-20_Gerbers_Rev_B.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/hardware/RaspberryPIZero/xenium-programmer-rpi_2021-01-20_Gerbers_Rev_B.zip -------------------------------------------------------------------------------- /images/bitbus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/bitbus.png -------------------------------------------------------------------------------- /images/bitbus2flash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/bitbus2flash.png -------------------------------------------------------------------------------- /images/boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/boot.png -------------------------------------------------------------------------------- /images/connections-omega.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/connections-omega.png -------------------------------------------------------------------------------- /images/connections-pi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/connections-pi.png -------------------------------------------------------------------------------- /images/five-bucks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/five-bucks.png -------------------------------------------------------------------------------- /images/lpc-bus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/lpc-bus.png -------------------------------------------------------------------------------- /images/mcpx-lpc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/mcpx-lpc.png -------------------------------------------------------------------------------- /images/openxenium.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/openxenium.jpg -------------------------------------------------------------------------------- /images/openxenium2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/openxenium2.jpg -------------------------------------------------------------------------------- /images/pi-spi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/pi-spi.jpg -------------------------------------------------------------------------------- /images/pi-wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/pi-wifi.png -------------------------------------------------------------------------------- /images/pinout-omega.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/pinout-omega.png -------------------------------------------------------------------------------- /images/pinout-pi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/pinout-pi.png -------------------------------------------------------------------------------- /images/sshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/sshot.png -------------------------------------------------------------------------------- /images/xenium-flash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/xenium-flash.jpg -------------------------------------------------------------------------------- /images/xenium-os.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/xenium-os.jpg -------------------------------------------------------------------------------- /images/xenium-programmer-wiring.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/xenium-programmer-wiring.xcf -------------------------------------------------------------------------------- /images/xilinx-programmer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/images/xilinx-programmer.jpg -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | echo -e '\n▒██ ██▒▓█████ ███▄ █ ██▓ █ ██ ███▄ ▄███▓' 4 | echo -e '▒▒ █ █ ▒░▓█ ▀ ██ ▀█ █ ▓██▒ ██ ▓██▒▓██▒▀█▀ ██▒' 5 | echo -e '░░ █ ░▒███ ▓██ ▀█ ██▒▒██▒▓██ ▒██░▓██ ▓██░' 6 | echo -e ' ░ █ █ ▒ ▒▓█ ▄ ▓██▒ ▐▌██▒░██░▓▓█ ░██░▒██ ▒██ ' 7 | echo -e '▒██▒ ▒██▒░▒████▒▒██░ ▓██░░██░▒▒█████▓ ▒██▒ ░██▒' 8 | echo -e '▒▒ ░ ░▓ ░░░ ▒░ ░░ ▒░ ▒ ▒ ░▓ ░▒▓▒ ▒ ▒ ░ ▒░ ░ ░' 9 | echo -e '░░ ░▒ ░ ░ ░ ░░ ░░ ░ ▒░ ▒ ░░░▒Programmer░ ░' 10 | echo -e ' ░ ░ ░ ░ ░ ░ ▒kooscode@github ░ ' 11 | echo -e ' ░ ░ ░ ░ ░ ░ ░ ░ \n' 12 | 13 | while [ "$#" -gt 0 ]; do 14 | case $1 in 15 | #wifi|--wifi|-w) wifi=1 ;; 16 | expert|--expert|-e) expert=1 ;; 17 | *) echo "Unknown parameter passed: $1"; exit 1 ;; 18 | esac 19 | shift 20 | done 21 | 22 | # Set platform 23 | DEV_FILE=/sys/firmware/devicetree/base/model 24 | if [ -e $DEV_FILE ]; then 25 | if grep -q "Onion Omega2+" "$DEV_FILE"; then 26 | export PLATFORM=OMEGA2 27 | echo ' !! ONION OMEGA2+ DETECTED !!\n' 28 | elif grep -q "Raspberry Pi" "$DEV_FILE"; then 29 | export PLATFORM=PI 30 | echo '--------------------------------------------' 31 | echo -e '\n INSTALLING PI UPDATES AND REQUIREMENTS\n' 32 | echo '--------------------------------------------' 33 | sudo apt -y update 34 | sudo apt -y install build-essential git cmake 35 | # Installing latest wiringpi compatible with RPI-OS 36 | wget https://project-downloads.drogon.net/wiringpi-latest.deb -O /tmp/wiringpi-latest.deb 37 | sudo dpkg -i /tmp/wiringpi-latest.deb 38 | fi 39 | elif [ $expert ]; then 40 | echo -e 'Expert mode enabled.' 41 | else 42 | echo -e "You do not appear to be using a supported" 43 | echo -e "platform. If you know what you''re doing and" 44 | echo -e "want to proceed anyway, run this install" 45 | echo -e "script again with the 'expert' flag, and" 46 | echo -e "we'll attempt to build xenium-flash " 47 | echo -e "on your platform.\n" 48 | echo -e "Bye." 49 | exit 0 50 | fi 51 | 52 | # make and install xenium-flash to bin 53 | echo -e '------------------------------------------' 54 | echo -e '\n BUILDING XENIUM JTAG AND FLASH TOOLS\n' 55 | echo -e '------------------------------------------' 56 | if (which g++ || grep -q "g++" ); then 57 | cd xenium-flash 58 | make 59 | cd .. 60 | 61 | # ensure script is executable 62 | chmod +x xenium-programmer 63 | 64 | echo -e '\n** INSTALL COMPLETE **\n' 65 | 66 | echo -e '\nProgram your Xenium by running:\n\t ./xenium-programmer\n' 67 | else 68 | echo -e '\n*** ERROR: No C++ Compiler found!!!!\n' 69 | fi 70 | -------------------------------------------------------------------------------- /pi-remote-access/README.md: -------------------------------------------------------------------------------- 1 | # Raspberry PI Scripts and Remote Access 2 | 3 | ![boot-partition](../images/pi-wifi.png) 4 | 5 | If you dont have access to or dont want to use a keyboard, mouse and screen with your PI, you can use these scripts to get your PI to automatically boot with WIFI or USB Netowrk support and enable SSH, then you can access everything remotely via SSH. 6 | 7 | There are of course many ways to access your PI, this is a headless and remote way of doing it via wireless/USB Network and info provided here are purely for convenience. 8 | 9 | ![boot-partition](../images/boot.png) 10 | 11 | - All files mentioned below must be copied to and edited in the `boot` partition on the SD card. 12 | - Insert the PI's SD card into your computer and EDIT/COPY these files in the 'boot' partition. 13 | 14 | # OPTION A - Setup WIFI (Wireless Access) 15 | 16 | You can setup the PI to join your wirelesss network and then access it via wireless. 17 | 18 | - Copy the `wpa_supplicant.conf` to the boto partition 19 | - Edit this file and fill in your WIFI SSID and Password to automatically connect to WIFI on boot. 20 | - NOTE: This file will be automatically applied and removed by the PI system after startup. 21 | - IF this does not work, try the Wired Access below.. 22 | 23 | # OPTION B - Setup USB Network Adapter (Wired Access) 24 | 25 | If you dont have WIFI access to the PI or struggle to get it working, you can also enable the PI to become a USB Network adapter and then access it directly that way. 26 | 27 | - Edit the `config.txt` file and place this line at the bottom of the file: `dtoverlay=dwc2` 28 | - Edit the `cmdline.txt` file and place this text at the end of the first line: `modules-load=dwc2,g_ether` 29 | - Plug the USB into you computer and you will now have a USB Network adapter show up 30 | 31 | # Connecting via SSH (Wireless OR Wired) 32 | 33 | ## Enable SSH 34 | - Copy the `ssh` file to the boot partition as well to enable SSH 35 | - This will enable SSH access to the PI 36 | - NOTE: This file will be automatically applied and removed by the PI system after startup. 37 | 38 | ## Connecting via SSH 39 | 40 | - For a default or new PI setup, use any SSH tool and connect to `raspberrypi.local` with user `pi` and password `raspberry` 41 | - If the MDNS name doesnt resolve, you might need to find your IP Address instead. Use Google for more details on that :) 42 | - NOTE: It might take 5min for the initial load, wifi setup and mdns registration.. be patient.. 43 | 44 | ### You should now be able to access your PI remotely via SSH and run the Xenium Flash tools 45 | -------------------------------------------------------------------------------- /pi-remote-access/ssh: -------------------------------------------------------------------------------- 1 | # to enable SSH, place this file in SD Card root folder 2 | -------------------------------------------------------------------------------- /pi-remote-access/wpa_supplicant.conf: -------------------------------------------------------------------------------- 1 | # To Configure Wireless, edit this file and place in SD card root folder 2 | ctrl_interface=/var/run/wpa_supplicant 3 | update_config=1 4 | country=US 5 | 6 | network={ 7 | ssid="YOUR_SSID" 8 | psk="YOUR_PASSWORD" 9 | } 10 | 11 | -------------------------------------------------------------------------------- /xenium-bin/xenium_blue.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/xenium-bin/xenium_blue.bin -------------------------------------------------------------------------------- /xenium-bin/xenium_gold.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/xenium-bin/xenium_gold.bin -------------------------------------------------------------------------------- /xenium-bin/xenium_ice.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kooscode/xenium-programmer/75db23aba89c884e25eab2fb6528e65a2257b9dc/xenium-bin/xenium_ice.bin -------------------------------------------------------------------------------- /xenium-flash/Makefile: -------------------------------------------------------------------------------- 1 | APP_FLASH=xenium-flash 2 | APP_JTAG=xenium-jtag 3 | SRC_MAIN=src 4 | OUT_DIR=bin 5 | 6 | # Default build is PI, override with ENV variable PLATFORM 7 | # Or just manually set it here: 8 | #PLATFORM=OMEGA2 9 | #PLATFORM=PI 10 | 11 | ifndef PLATFORM 12 | PLATFORM=PI 13 | endif 14 | 15 | #extra paths 16 | FLASH=$(SRC_MAIN)/flash 17 | JTAG=$(SRC_MAIN)/jtag 18 | OMEGA=$(SRC_MAIN)/omega2-gpio 19 | 20 | CXX=g++ 21 | #G++ options 22 | # To Make Debug Build set: -g 23 | # To Debug with GDB run: gdb -ex=r --args APP ARG1 ARG2 24 | CFLAGS=-Wall -ansi 25 | CPP_STD=c++17 26 | 27 | #include paths 28 | I1=$(SRC_MAIN) 29 | I2=$(FLASH) 30 | I3=$(JTAG) 31 | ifeq ($(PLATFORM),OMEGA2) 32 | I4=$(OMEGA) 33 | endif 34 | 35 | #sources files 36 | S1=$(FLASH)/BitBus.cpp 37 | S2=$(FLASH)/Flash.cpp 38 | S3=$(JTAG)/IOBase.cpp 39 | S4=$(JTAG)/Jtag.cpp 40 | S5=$(JTAG)/JedecFile.cpp 41 | S6=$(JTAG)/ProgAlgXC95X.cpp 42 | 43 | ifeq ($(PLATFORM),OMEGA2) 44 | S7=$(OMEGA)/Module.cpp 45 | S8=$(OMEGA)/FastGpioOmega2.cpp 46 | S9=$(JTAG)/IOOmega2.cpp 47 | S10=$(FLASH)/BitBusOmega2.cpp 48 | else 49 | S7=$(JTAG)/IOWiringPi.cpp 50 | S8=$(FLASH)/BitBusPI.cpp 51 | endif 52 | 53 | #lib paths 54 | LP1= 55 | LP2= 56 | LP3= 57 | LP4= 58 | 59 | #linked libs 60 | L1= 61 | L2= 62 | L3= 63 | L4= 64 | ifeq ($(PLATFORM),OMEGA2) 65 | L5= 66 | else 67 | L5=wiringPi 68 | endif 69 | 70 | #pkg-configs 71 | PKG1= 72 | PKG2= 73 | PKG3= 74 | PKG4= 75 | 76 | #defines 77 | D1=$(PLATFORM) 78 | D2= 79 | D3= 80 | D4= 81 | 82 | #expand all options 83 | INC=$(I1) $(I2) $(I3) $(I4) 84 | INCLUDES=$(foreach d, $(INC), -I$d) 85 | SOURCES=$(S1) $(S2) $(S3) $(S4) $(S5) $(S6) $(S7) $(S8) $(S9) $(S10) 86 | LIB_PATH=$(LP1) $(LP2) $(LP3) $(LP4) 87 | LIB_PATHS=$(foreach d, $(LIB_PATH), -L$d) 88 | LIB=$(L1) $(L2) $(L3) $(L4) $(L5) 89 | LIBS=$(foreach d, $(LIB), -l$d) 90 | PKGS=$(PKG1) $(PKG2) $(PKG3) $(PKG4) 91 | ifneq ($(strip $(PKGS)),) 92 | PKG_INCS=$(shell pkg-config --cflags $(PKGS)) 93 | PKG_LIBS=$(shell pkg-config --libs $(PKGS)) 94 | endif 95 | DEF=$(D1) $(D2) $(D3) $(D4) 96 | DEFS=$(foreach d, $(DEF), -D$d) 97 | 98 | #compile 99 | MAKE_FLASH = $(CXX) $(CFLAGS) -std=$(CPP_STD) $(DEFS) $(SRC_MAIN)/$(APP_FLASH).cpp $(SOURCES) -o $(OUT_DIR)/$(APP_FLASH) $(INCLUDES) $(PKG_INCS) $(LIB_PATHS) $(LIBS) $(PKG_LIBS) 100 | MAKE_JTAG = $(CXX) $(CFLAGS) -std=$(CPP_STD) $(DEFS) $(SRC_MAIN)/$(APP_JTAG).cpp $(SOURCES) -o $(OUT_DIR)/$(APP_JTAG) $(INCLUDES) $(PKG_INCS) $(LIB_PATHS) $(LIBS) $(PKG_LIBS) 101 | 102 | all: 103 | test -d bin || mkdir -p bin 104 | $(MAKE_JTAG) 105 | $(MAKE_FLASH) 106 | 107 | $(APP_FLASH): $(SRC_MAIN)/$(APP_FLASH).cpp 108 | test -d bin || mkdir -p bin 109 | $(MAKE_FLASH) 110 | 111 | $(APP_JTAG): $(SRC_MAIN)/$(APP_JTAG).cpp 112 | test -d bin || mkdir -p bin 113 | $(MAKE_JTAG) 114 | 115 | clean: 116 | rm bin -fr 117 | 118 | -------------------------------------------------------------------------------- /xenium-flash/README.md: -------------------------------------------------------------------------------- 1 | # xenium-jtag 2 | 3 | This is the app that programs the OpenXenium Flash memory CPLD. See the main README for more details 4 | 5 | - This app will be built and installed automatically via the main `install` script. 6 | 7 | 8 | # xenium-flash 9 | 10 | This is the main app that uploads XeniumOS images into the OpenXenium Flash memory. See the main README for more details 11 | 12 | - This app will be built and installed automatically via the main `install` script. 13 | 14 | - NOTE - the `xeniumflash.jed` MUST be loaded into the Xilinx CPLD first BEFORE you can upload any Flash memory images. (the `xenium-programmer` script in the main folder will automatically do this for you) 15 | 16 | # Building 17 | - just run `make` or run the `install` script in root of this repo to make and install 18 | 19 | -------------------------------------------------------------------------------- /xenium-flash/src/XeniumDefines.h: -------------------------------------------------------------------------------- 1 | /* #defines for Xenium JTAG and FLASH GPIO pinouts 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | // BITBUS TO XENIUM PIN MAP 21 | // ------------------------ 22 | // BITBUS D0 => LPC LAD0 23 | // BITBUS D1 => LPC LAD1 24 | // BITBUS D2 => LPC LAD2 25 | // BITBUS D3 => LPC LAD3 26 | // BITBUS CLK => LPC LCLK 27 | // BITBUS DIR => LPC RST 28 | 29 | #ifdef OMEGA2 30 | // OmegaS2+ JTAG Pins 31 | #define XENIUM_TMS 11 32 | #define XENIUM_TCK 3 33 | #define XENIUM_TDI 2 34 | #define XENIUM_TDO 17 35 | 36 | // OmegaS2+ BitBus pins connected to LPC Header 37 | #define BITBUS_D0 1 38 | #define BITBUS_D1 15 39 | #define BITBUS_D2 16 40 | #define BITBUS_D3 18 41 | #define BITBUS_CLK 0 42 | #define BITBUS_DIR 19 43 | #else 44 | // default is PI build 45 | // Raspberry PI JTAG Pins 46 | #define XENIUM_TMS 4 47 | #define XENIUM_TCK 17 48 | #define XENIUM_TDI 22 49 | #define XENIUM_TDO 27 50 | 51 | // Raspberry PI BitBus pins connected to LPC Header 52 | #define BITBUS_D0 16 53 | #define BITBUS_D1 21 54 | #define BITBUS_D2 18 55 | #define BITBUS_D3 20 56 | #define BITBUS_CLK 8 57 | #define BITBUS_DIR 23 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /xenium-flash/src/flash/BitBus.cpp: -------------------------------------------------------------------------------- 1 | /* Custom 4-bit "BitBus" 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "BitBus.hpp" 21 | 22 | #include 23 | #include 24 | 25 | #include "XeniumDefines.h" 26 | 27 | namespace XK 28 | { 29 | BitBus::BitBus() 30 | { } 31 | 32 | void BitBus::SetPlatformDelay(bool delay_enabled) 33 | { 34 | platform_delay_ = delay_enabled; 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /xenium-flash/src/flash/BitBus.hpp: -------------------------------------------------------------------------------- 1 | /* Custom 4-bit "BitBus" 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef XK_BITBUS_ 21 | #define XK_BITBUS_ 22 | 23 | #include 24 | #include 25 | 26 | namespace XK 27 | { 28 | enum BusMode 29 | { 30 | BITBUS_WRITE = 0, 31 | BITBUS_READ = 1 32 | }; 33 | 34 | enum GPIOMode 35 | { 36 | GPIO_IN = 0, 37 | GPIO_OUT = 1 38 | }; 39 | 40 | class BitBus 41 | { 42 | public: 43 | BitBus(); 44 | void SetPlatformDelay(bool delay_enabled); 45 | 46 | virtual void DelayMicroseconds(uint64_t usec) = 0; 47 | virtual std::string GetHardwareString() = 0; 48 | virtual void SetGPIOMode(GPIOMode gpiomode) = 0; 49 | virtual void Clock() = 0;; 50 | virtual void SetBusMode(BusMode busmode) = 0; 51 | virtual void WriteByte(const uint8_t& data) = 0; 52 | virtual uint8_t ReadByte() = 0; 53 | 54 | protected: 55 | bool platform_delay_; 56 | virtual void InitGPIO() = 0; 57 | }; 58 | } 59 | 60 | #endif -------------------------------------------------------------------------------- /xenium-flash/src/flash/BitBusOmega2.cpp: -------------------------------------------------------------------------------- 1 | /* Onion Omega2+ implementation of Custom 4-bit "BitBus" 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "BitBusOmega2.hpp" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "XeniumDefines.h" 27 | 28 | namespace XK 29 | { 30 | BitBusOmega2::BitBusOmega2() : BitBus() 31 | { 32 | InitGPIO(); 33 | } 34 | 35 | void BitBusOmega2::DelayMicroseconds(uint64_t usec) 36 | { 37 | // No sleep needed for Omega :) 38 | } 39 | 40 | std::string BitBusOmega2::GetHardwareString() 41 | { 42 | std::ifstream vfile("/sys/firmware/devicetree/base/model"); 43 | std::string vstr; 44 | 45 | if (vfile.is_open()) 46 | std::getline(vfile, vstr); 47 | else 48 | vstr = "UNKNOWN"; 49 | 50 | vfile.close(); 51 | 52 | return vstr; 53 | } 54 | 55 | void BitBusOmega2::SetGPIOMode(GPIOMode gpiomode) 56 | { 57 | omega_.pinMode(BITBUS_D0, (int)gpiomode); 58 | omega_.pinMode(BITBUS_D1, (int)gpiomode); 59 | omega_.pinMode(BITBUS_D2, (int)gpiomode); 60 | omega_.pinMode(BITBUS_D3, (int)gpiomode); 61 | } 62 | 63 | void BitBusOmega2::Clock() 64 | { 65 | 66 | omega_.digitalWrite(BITBUS_CLK, OMEGA_HIGH); 67 | omega_.digitalWrite(BITBUS_CLK, OMEGA_LOW); 68 | } 69 | 70 | void BitBusOmega2::SetBusMode(BusMode busmode) 71 | { 72 | omega_.digitalWrite(BITBUS_DIR, busmode); 73 | Clock(); 74 | } 75 | 76 | void BitBusOmega2::WriteByte(const uint8_t& data) 77 | { 78 | // Send lower nibble 79 | omega_.digitalWrite(BITBUS_D0, (data & 0x01)); 80 | omega_.digitalWrite(BITBUS_D1, (data >> 1 & 0x01)); 81 | omega_.digitalWrite(BITBUS_D2, (data >> 2 & 0x01)); 82 | omega_.digitalWrite(BITBUS_D3, (data >> 3 & 0x01)); 83 | Clock(); 84 | 85 | // Send upper nibble 86 | omega_.digitalWrite(BITBUS_D0, (data >> 4 & 0x01)); 87 | omega_.digitalWrite(BITBUS_D1, (data >> 5 & 0x01)); 88 | omega_.digitalWrite(BITBUS_D2, (data >> 6 & 0x01)); 89 | omega_.digitalWrite(BITBUS_D3, (data >> 7 & 0x01)); 90 | Clock(); 91 | } 92 | 93 | uint8_t BitBusOmega2::ReadByte() 94 | { 95 | uint8_t inbyte = 0x00; 96 | 97 | // receive lower nibble 98 | Clock(); 99 | inbyte = omega_.digitalRead(BITBUS_D0); 100 | inbyte |= omega_.digitalRead(BITBUS_D1) << 1; 101 | inbyte |= omega_.digitalRead(BITBUS_D2) << 2; 102 | inbyte |= omega_.digitalRead(BITBUS_D3) << 3; 103 | 104 | // receive upper nibble 105 | Clock(); 106 | inbyte |= omega_.digitalRead(BITBUS_D0) << 4; 107 | inbyte |= omega_.digitalRead(BITBUS_D1) << 5; 108 | inbyte |= omega_.digitalRead(BITBUS_D2) << 6; 109 | inbyte |= omega_.digitalRead(BITBUS_D3) << 7; 110 | 111 | return inbyte; 112 | } 113 | 114 | void BitBusOmega2::InitGPIO() 115 | { 116 | //setup BitBusOmega2 control pins 117 | omega_.pinMode(BITBUS_CLK, OMEGA_GPIO_OUT); 118 | omega_.pinMode(BITBUS_DIR, OMEGA_GPIO_OUT); 119 | } 120 | 121 | } 122 | 123 | -------------------------------------------------------------------------------- /xenium-flash/src/flash/BitBusOmega2.hpp: -------------------------------------------------------------------------------- 1 | /* Onion Omega2+ implementation of Custom 4-bit "BitBus" 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef XK_BITBUS_OMEGA2_ 21 | #define XK_BITBUS_OMEGA2_ 22 | 23 | #include 24 | 25 | #include "BitBus.hpp" 26 | #include "FastGpioOmega2.hpp" 27 | 28 | namespace XK 29 | { 30 | class BitBusOmega2 : public BitBus 31 | { 32 | public: 33 | BitBusOmega2(); 34 | void DelayMicroseconds(uint64_t usec); 35 | std::string GetHardwareString(); 36 | void SetGPIOMode(GPIOMode gpiomode); 37 | void Clock(); 38 | void SetBusMode(BusMode busmode); 39 | void WriteByte(const uint8_t& data); 40 | uint8_t ReadByte(); 41 | 42 | private: 43 | void InitGPIO(); 44 | FastGpioOmega2 omega_; 45 | }; 46 | } 47 | 48 | #endif -------------------------------------------------------------------------------- /xenium-flash/src/flash/BitBusPI.cpp: -------------------------------------------------------------------------------- 1 | /* RaspberryPI implementation of Custom 4-bit "BitBus" 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "BitBusPI.hpp" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "wiringPi.h" 27 | #include "XeniumDefines.h" 28 | 29 | namespace XK 30 | { 31 | BitBusPI::BitBusPI() : BitBus() 32 | { 33 | InitGPIO(); 34 | } 35 | 36 | void BitBusPI::DelayMicroseconds(uint64_t usec) 37 | { 38 | delayMicroseconds(usec); 39 | } 40 | 41 | std::string BitBusPI::GetHardwareString() 42 | { 43 | std::ifstream vfile("/sys/firmware/devicetree/base/model"); 44 | std::string vstr; 45 | 46 | if (vfile.is_open()) 47 | std::getline(vfile, vstr); 48 | else 49 | vstr = "UNKNOWN"; 50 | 51 | vfile.close(); 52 | 53 | return vstr; 54 | } 55 | 56 | void BitBusPI::SetGPIOMode(GPIOMode gpiomode) 57 | { 58 | pinMode(BITBUS_D0, gpiomode); 59 | pinMode(BITBUS_D1, gpiomode); 60 | pinMode(BITBUS_D2, gpiomode); 61 | pinMode(BITBUS_D3, gpiomode); 62 | } 63 | 64 | void BitBusPI::Clock() 65 | { 66 | 67 | digitalWrite(BITBUS_CLK, HIGH); 68 | if (platform_delay_) 69 | { 70 | //ugly way to delay for 3B+.. cause normal thread_this:wait_until aint working! 71 | auto waituntil = std::chrono::high_resolution_clock::now() + std::chrono::nanoseconds(1); 72 | while(true) if (std::chrono::high_resolution_clock::now() >= waituntil) break; 73 | } 74 | else 75 | { 76 | // TODO - TEST double clock with 3B+ and remove above ugglyness... 77 | digitalWrite(BITBUS_CLK, HIGH); 78 | digitalWrite(BITBUS_CLK, LOW); 79 | } 80 | digitalWrite(BITBUS_CLK, LOW); 81 | } 82 | 83 | void BitBusPI::SetBusMode(BusMode busmode) 84 | { 85 | digitalWrite(BITBUS_DIR, busmode); 86 | Clock(); 87 | } 88 | 89 | void BitBusPI::WriteByte(const uint8_t& data) 90 | { 91 | // Send lower nibble 92 | digitalWrite(BITBUS_D0, (data & 0x01)); 93 | digitalWrite(BITBUS_D1, (data >> 1 & 0x01)); 94 | digitalWrite(BITBUS_D2, (data >> 2 & 0x01)); 95 | digitalWrite(BITBUS_D3, (data >> 3 & 0x01)); 96 | Clock(); 97 | 98 | // Send upper nibble 99 | digitalWrite(BITBUS_D0, (data >> 4 & 0x01)); 100 | digitalWrite(BITBUS_D1, (data >> 5 & 0x01)); 101 | digitalWrite(BITBUS_D2, (data >> 6 & 0x01)); 102 | digitalWrite(BITBUS_D3, (data >> 7 & 0x01)); 103 | 104 | Clock(); 105 | } 106 | 107 | uint8_t BitBusPI::ReadByte() 108 | { 109 | uint8_t inbyte = 0x00; 110 | 111 | // receive lower nibble 112 | Clock(); 113 | inbyte = digitalRead(BITBUS_D0); 114 | inbyte |= digitalRead(BITBUS_D1) << 1; 115 | inbyte |= digitalRead(BITBUS_D2) << 2; 116 | inbyte |= digitalRead(BITBUS_D3) << 3; 117 | 118 | // receive upper nibble 119 | Clock(); 120 | inbyte |= digitalRead(BITBUS_D0) << 4; 121 | inbyte |= digitalRead(BITBUS_D1) << 5; 122 | inbyte |= digitalRead(BITBUS_D2) << 6; 123 | inbyte |= digitalRead(BITBUS_D3) << 7; 124 | 125 | return inbyte; 126 | } 127 | 128 | void BitBusPI::InitGPIO() 129 | { 130 | //setup wiringPi 131 | wiringPiSetupGpio(); 132 | 133 | //setup BitBusPI control pins 134 | pinMode(BITBUS_CLK, OUTPUT); 135 | pinMode(BITBUS_DIR, OUTPUT); 136 | } 137 | 138 | } 139 | 140 | -------------------------------------------------------------------------------- /xenium-flash/src/flash/BitBusPI.hpp: -------------------------------------------------------------------------------- 1 | /* RaspberryPI implementation of Custom 4-bit "BitBus" 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef XK_BITBUS_PI_ 21 | #define XK_BITBUS_PI_ 22 | 23 | #include 24 | 25 | #include "BitBus.hpp" 26 | 27 | namespace XK 28 | { 29 | class BitBusPI : public BitBus 30 | { 31 | public: 32 | BitBusPI(); 33 | void DelayMicroseconds(uint64_t usec); 34 | std::string GetHardwareString(); 35 | void SetGPIOMode(GPIOMode gpiomode); 36 | void Clock(); 37 | void SetBusMode(BusMode busmode); 38 | void WriteByte(const uint8_t& data); 39 | uint8_t ReadByte(); 40 | 41 | private: 42 | void InitGPIO(); 43 | }; 44 | } 45 | 46 | #endif -------------------------------------------------------------------------------- /xenium-flash/src/flash/Flash.cpp: -------------------------------------------------------------------------------- 1 | /* Programming a SPANSION flash via 4-bit bus 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "Flash.hpp" 21 | 22 | namespace XK 23 | { 24 | Flash::Flash() : 25 | bitbus_(std::make_unique()) 26 | { 27 | //check if delay needs to be injected for non Pi-Zero models.. 28 | platform_delay_ = bitbus_->GetHardwareString().find("Zero") == std::string::npos; 29 | bitbus_->SetPlatformDelay(platform_delay_); 30 | 31 | // Innitialize with GPIO for READ 32 | bitbus_->SetGPIOMode(GPIO_IN); 33 | gpiomode_ = GPIO_IN; 34 | 35 | // toggle modes to reset bus to READ 36 | bitbus_-> SetBusMode(BITBUS_WRITE); 37 | bitbus_-> SetBusMode(BITBUS_READ); 38 | busmode_ = BITBUS_READ; 39 | 40 | } 41 | 42 | std::string Flash::GetHardwareString() 43 | { 44 | return bitbus_->GetHardwareString(); 45 | } 46 | 47 | uint8_t Flash::GetManufacturerID() 48 | { 49 | // Identification Command 50 | // Address 0x00 = ManufacturerID 51 | SetBusMode(BITBUS_WRITE); 52 | WriteByte(0xAAA, 0xAA); 53 | WriteByte(0x555, 0x55); 54 | WriteByte(0xAAA, 0x90); 55 | 56 | SetBusMode(BITBUS_READ); 57 | uint8_t manid = ReadByte(0x00); 58 | return manid; 59 | } 60 | 61 | uint8_t Flash::GetDeviceID() 62 | { 63 | // Identification Command 64 | // Address 0x02 = DeviceID 65 | SetBusMode(BITBUS_WRITE); 66 | WriteByte(0xAAA, 0xAA); 67 | WriteByte(0x555, 0x55); 68 | WriteByte(0xAAA, 0x90); 69 | 70 | SetBusMode(BITBUS_READ); 71 | uint8_t chipid = ReadByte(0x02); 72 | return chipid; 73 | } 74 | 75 | void Flash::ChipReset() 76 | { 77 | //ManufacturerID Command 78 | SetBusMode(BITBUS_WRITE); 79 | WriteByte(0x000, 0xF0); 80 | 81 | //force toggle mode lines to reset bus 82 | bitbus_-> SetBusMode(BITBUS_READ); 83 | bitbus_-> SetBusMode(BITBUS_WRITE); 84 | } 85 | 86 | void Flash::ChipErase() 87 | { 88 | SetBusMode(BITBUS_WRITE); 89 | // Send Chip Erase Command 90 | WriteByte(0xAAA, 0xAA); 91 | WriteByte(0x555, 0x55); 92 | WriteByte(0xAAA, 0x80); 93 | WriteByte(0xAAA, 0xAA); 94 | WriteByte(0x555, 0x55); 95 | WriteByte(0xAAA, 0x10); 96 | } 97 | 98 | uint8_t Flash::Read(const uint32_t& address) 99 | { 100 | SetBusMode(BITBUS_READ); 101 | uint8_t ret = ReadByte(address); 102 | return ret; 103 | } 104 | 105 | void Flash::Write(const uint32_t& address, const char& data) 106 | { 107 | SetBusMode(BITBUS_WRITE); 108 | //Send Program Command 109 | WriteByte(0xAAA, 0xAA); 110 | WriteByte(0x555, 0x55); 111 | WriteByte(0xAAA, 0xA0); 112 | 113 | //write byte 114 | WriteByte(address, data); 115 | } 116 | 117 | void Flash::SetBusMode(BusMode busmode) 118 | { 119 | if (busmode_ != busmode) 120 | { 121 | busmode_ = busmode; 122 | bitbus_->SetBusMode(busmode_); 123 | } 124 | } 125 | 126 | void Flash::SetGPIOMode(GPIOMode gpiomode) 127 | { 128 | if (gpiomode_ != gpiomode) 129 | { 130 | gpiomode_ = gpiomode; 131 | bitbus_->SetGPIOMode(gpiomode_); 132 | } 133 | } 134 | 135 | uint8_t Flash::ReadByte(const uint32_t& address) 136 | { 137 | uint8_t bb_data = 0x00; 138 | uint8_t* addr_byte = (uint8_t*) &address; 139 | 140 | // transmit 24-bits of address (only 21-bits are used) 141 | SetGPIOMode(GPIO_OUT); 142 | bitbus_->WriteByte(addr_byte[0]); 143 | bitbus_->WriteByte(addr_byte[1]); 144 | bitbus_->WriteByte(addr_byte[2]); 145 | 146 | // flash: we=1, oe=0; 147 | bitbus_->Clock(); 148 | 149 | // read 8-bit data 150 | SetGPIOMode(GPIO_IN); 151 | bb_data = bitbus_->ReadByte(); 152 | 153 | // flash: we=1, oe=1 154 | bitbus_->Clock(); 155 | 156 | return bb_data; 157 | } 158 | 159 | void Flash::WriteByte(const uint32_t& address, const uint8_t& data) 160 | { 161 | uint8_t* addr_byte = (uint8_t*) &address; 162 | 163 | // transmit 24-bits of address (only 21-bits are used) 164 | SetGPIOMode(GPIO_OUT); 165 | bitbus_->WriteByte(addr_byte[0]); 166 | bitbus_->WriteByte(addr_byte[1]); 167 | bitbus_->WriteByte(addr_byte[2]); 168 | 169 | // flash: we=0, oe=1; 170 | bitbus_->Clock(); 171 | 172 | // transmit 8 bit data 173 | bitbus_->WriteByte(data); 174 | 175 | // flash: we=1, oe=1; 176 | bitbus_->Clock(); 177 | 178 | // small delay between writes makes it much more stable 179 | bitbus_->DelayMicroseconds(3); 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /xenium-flash/src/flash/Flash.hpp: -------------------------------------------------------------------------------- 1 | /* Programming a SPANSION flash via 4-bit bus 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef XK_FLASH_ 21 | #define XK_FLASH_ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef OMEGA2 28 | #include "BitBusOmega2.hpp" 29 | #define PLATFORMBUS BitBusOmega2 30 | #else 31 | #include "BitBusPI.hpp" 32 | #define PLATFORMBUS BitBusPI 33 | #endif 34 | 35 | namespace XK 36 | { 37 | class Flash final 38 | { 39 | public: 40 | Flash(); 41 | std::string GetHardwareString(); 42 | uint8_t GetManufacturerID(); 43 | uint8_t GetDeviceID(); 44 | void ChipReset(); 45 | void ChipErase(); 46 | uint8_t Read(const uint32_t& address); 47 | void Write(const uint32_t& address, const char& data); 48 | 49 | private: 50 | std::unique_ptr bitbus_; 51 | BusMode busmode_; 52 | GPIOMode gpiomode_; 53 | bool platform_delay_; 54 | 55 | void SetBusMode(BusMode busmode); 56 | void SetGPIOMode(GPIOMode gpiomode); 57 | uint8_t ReadByte(const uint32_t& address); 58 | void WriteByte(const uint32_t& address, const uint8_t& data); 59 | }; 60 | } 61 | 62 | #endif -------------------------------------------------------------------------------- /xenium-flash/src/jtag/IOBase.cpp: -------------------------------------------------------------------------------- 1 | /* JTAG low level functions and base class for cables 2 | 3 | Copyright (C) 2004 Andrew Rogers 4 | Copyright (C) 2005-2013 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de 5 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | Changes: 22 | Koos du Preez [kdupreez@hotmail.com] Jan 1 2019 23 | Removed everything not needed for Raspberry PI and Xilinx xc9572xl 24 | */ 25 | 26 | #include "IOBase.h" 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | using namespace std; 33 | IOBase::IOBase() 34 | { 35 | verbose = false; 36 | memset( ones,0xff,CHUNK_SIZE); 37 | memset(zeros, 0,CHUNK_SIZE); 38 | memset(tms_buf, 0,CHUNK_SIZE); 39 | tms_len = 0; 40 | } 41 | 42 | void IOBase::flush_tms(int force) 43 | { 44 | if (tms_len) 45 | tx_tms(tms_buf, tms_len, force); 46 | memset(tms_buf, 0,CHUNK_SIZE); 47 | tms_len = 0; 48 | } 49 | 50 | void IOBase::set_tms(bool val) 51 | { 52 | if( tms_len + 1 > CHUNK_SIZE*8) 53 | flush_tms(false); 54 | if(val) 55 | tms_buf[tms_len/8] |= (1 <<(tms_len &0x7)); 56 | tms_len++; 57 | } 58 | 59 | void IOBase::shiftTDITDO(const unsigned char *tdi, unsigned char *tdo, 60 | int length, bool last) 61 | { 62 | if(length==0) return; 63 | flush_tms(false); 64 | txrx_block(tdi, tdo, length,last); 65 | return; 66 | } 67 | 68 | void IOBase::shiftTDI(const unsigned char *tdi, int length, bool last) 69 | { 70 | shiftTDITDO(tdi, NULL, length,last); 71 | } 72 | 73 | // TDI gets a load of zeros, we just record TDO. 74 | void IOBase::shiftTDO(unsigned char *tdo, int length, bool last) 75 | { 76 | shiftTDITDO(NULL, tdo, length,last); 77 | } 78 | 79 | // TDI gets a load of zeros or ones, and we ignore TDO 80 | void IOBase::shift(bool tdi, int length, bool last) 81 | { 82 | int len = length; 83 | unsigned char *block = (tdi)?ones:zeros; 84 | flush_tms(false); 85 | while (len > CHUNK_SIZE*8) 86 | { 87 | txrx_block(block, NULL, CHUNK_SIZE*8, false); 88 | len -= (CHUNK_SIZE*8); 89 | } 90 | shiftTDITDO(block, NULL, len, last); 91 | } 92 | 93 | 94 | void IOBase::Usleep(unsigned int usec) 95 | { 96 | flush_tms(false); 97 | flush(); 98 | 99 | usleep(usec); 100 | } 101 | 102 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/IOBase.h: -------------------------------------------------------------------------------- 1 | /* JTAG low level functions and base class for cables 2 | 3 | Copyright (C) 2004 Andrew Rogers 4 | Copyright (C) 2005-2013 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de 5 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | Changes: 22 | Koos du Preez [kdupreez@hotmail.com] Jan 1 2019 23 | Removed everything not needed for Raspberry PI and Xilinx xc9572xl 24 | Renamed files to match class names - a pet peeve of mine :) 25 | */ 26 | 27 | #ifndef IOBASE_H 28 | #define IOBASE_H 29 | 30 | #define BLOCK_SIZE 65536 31 | #define CHUNK_SIZE 128 32 | #define TICK_COUNT 2048 33 | 34 | #include 35 | 36 | class IOBase 37 | { 38 | 39 | protected: 40 | bool verbose; 41 | unsigned char ones[CHUNK_SIZE], zeros[CHUNK_SIZE]; 42 | unsigned char tms_buf[CHUNK_SIZE]; 43 | unsigned int tms_len; /* in Bits*/ 44 | 45 | public: 46 | virtual ~IOBase() {} 47 | 48 | virtual void flush() {} 49 | virtual void Usleep(unsigned int usec); 50 | 51 | void setVerbose(bool v) { verbose = v; } 52 | void shiftTDITDO(const unsigned char *tdi, unsigned char *tdo, int length, bool last=true); 53 | void shiftTDI(const unsigned char *tdi, int length, bool last=true); 54 | void shiftTDO(unsigned char *tdo, int length, bool last=true); 55 | void shift(bool tdi, int length, bool last=true); 56 | void set_tms(bool value); 57 | void flush_tms(int force); 58 | 59 | protected: 60 | IOBase(); 61 | 62 | virtual void txrx_block(const unsigned char *tdi, unsigned char *tdo, int length, bool last)=0; 63 | virtual void tx_tms(unsigned char *pat, int length, int force)=0; 64 | virtual void settype(int subtype) {} 65 | 66 | private: 67 | void nextTapState(bool tms); 68 | }; 69 | #endif // IOBASE_H 70 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/IOOmega2.cpp: -------------------------------------------------------------------------------- 1 | /* OmegaS2+ implementation of XC3SPROG IOBase 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | Changes: 20 | Koos du Preez [kdupreez@hotmail.com] Jan 1 2019 21 | Prettified and made more readable. 22 | */ 23 | 24 | #include "IOOmega2.h" 25 | 26 | 27 | IOOmega2::IOOmega2(int tms, int tck, int tdi, int tdo) 28 | : TMSPin(tms), TCKPin(tck), TDIPin(tdi), TDOPin(tdo) 29 | { 30 | 31 | omega_.pinMode(TDIPin, OMEGA_GPIO_OUT); 32 | omega_.pinMode(TMSPin, OMEGA_GPIO_OUT); 33 | omega_.pinMode(TCKPin, OMEGA_GPIO_OUT); 34 | omega_.pinMode(TDOPin, OMEGA_GPIO_IN); 35 | } 36 | 37 | IOOmega2::~IOOmega2() 38 | { 39 | } 40 | 41 | void IOOmega2::txrx_block(const unsigned char *tdi, unsigned char *tdo, int length, bool last) 42 | { 43 | int i=0; 44 | int j=0; 45 | unsigned char tdo_byte=0; 46 | unsigned char tdi_byte; 47 | 48 | if (tdi) 49 | tdi_byte = tdi[j]; 50 | 51 | while( i < length-1) 52 | { 53 | tdo_byte = tdo_byte + (txrx(false, (tdi_byte&1) == 1) << (i%8)); 54 | 55 | if (tdi) 56 | tdi_byte = tdi_byte >> 1; 57 | 58 | i++; 59 | 60 | // Next byte 61 | if ((i%8) == 0) 62 | { 63 | // Save the TDO byte 64 | if(tdo) 65 | tdo[j] = tdo_byte; 66 | 67 | // Get the next TDI byte 68 | tdo_byte = 0; 69 | j++; 70 | 71 | if (tdi) 72 | tdi_byte = tdi[j]; 73 | } 74 | } 75 | 76 | tdo_byte = tdo_byte + (txrx(last, (tdi_byte&1)==1) << (i%8)); 77 | 78 | if(tdo) 79 | tdo[j]=tdo_byte; 80 | 81 | omega_.digitalWrite(TCKPin, OMEGA_LOW); 82 | 83 | return; 84 | } 85 | 86 | void IOOmega2::tx_tms(unsigned char *pat, int length, int force) 87 | { 88 | int i; 89 | unsigned char tms; 90 | 91 | for (i = 0; i < length; i++) 92 | { 93 | if ((i & 0x7) == 0) 94 | tms = pat[i>>3]; 95 | 96 | tx((tms & 0x01), true); 97 | tms = tms >> 1; 98 | } 99 | 100 | omega_.digitalWrite(TCKPin, OMEGA_LOW); 101 | } 102 | 103 | void IOOmega2::tx(bool tms, bool tdi) 104 | { 105 | omega_.digitalWrite(TCKPin, OMEGA_LOW); 106 | 107 | if(tdi) 108 | omega_.digitalWrite(TDIPin, OMEGA_HIGH); 109 | else 110 | omega_.digitalWrite(TDIPin, OMEGA_LOW); 111 | 112 | if(tms) 113 | omega_.digitalWrite(TMSPin, OMEGA_HIGH); 114 | else 115 | omega_.digitalWrite(TMSPin, OMEGA_LOW); 116 | 117 | omega_.digitalWrite(TCKPin, OMEGA_HIGH); 118 | } 119 | 120 | 121 | bool IOOmega2::txrx(bool tms, bool tdi) 122 | { 123 | tx(tms, tdi); 124 | return omega_.digitalRead(TDOPin); 125 | } 126 | 127 | 128 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/IOOmega2.h: -------------------------------------------------------------------------------- 1 | /* OmegaS2+ implementation of XC3SPROG IOBase 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef __IO_OMEGA_2__ 21 | #define __IO_OMEGA_2__ 22 | 23 | #include "IOBase.h" 24 | #include "FastGpioOmega2.hpp" 25 | 26 | class IOOmega2 : public IOBase 27 | { 28 | public: 29 | IOOmega2(int tms, int tck, int tdi, int tdo); 30 | virtual ~IOOmega2(); 31 | 32 | protected: 33 | void tx(bool tms, bool tdi); 34 | bool txrx(bool tms, bool tdi); 35 | 36 | void txrx_block(const unsigned char *tdi, unsigned char *tdo, int length, bool last); 37 | void tx_tms(unsigned char *pat, int length, int force); 38 | 39 | int TMSPin; 40 | int TCKPin; 41 | int TDIPin; 42 | int TDOPin; 43 | 44 | FastGpioOmega2 omega_; 45 | 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/IOWiringPi.cpp: -------------------------------------------------------------------------------- 1 | /* Onion Omega 2 implementation of XC3SPROG IOBase 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "IOWiringPi.h" 21 | #include 22 | 23 | IOWiringPi::IOWiringPi(int tms, int tck, int tdi, int tdo) 24 | : TMSPin(tms), TCKPin(tck), TDIPin(tdi), TDOPin(tdo) 25 | { 26 | wiringPiSetupGpio(); 27 | pinMode(TDIPin, OUTPUT); 28 | pinMode(TMSPin, OUTPUT); 29 | pinMode(TCKPin, OUTPUT); 30 | pinMode(TDOPin, INPUT); 31 | } 32 | 33 | IOWiringPi::~IOWiringPi() 34 | { 35 | } 36 | 37 | void IOWiringPi::txrx_block(const unsigned char *tdi, unsigned char *tdo, int length, bool last) 38 | { 39 | int i=0; 40 | int j=0; 41 | unsigned char tdo_byte=0; 42 | unsigned char tdi_byte; 43 | 44 | if (tdi) 45 | tdi_byte = tdi[j]; 46 | 47 | while( i < length-1) 48 | { 49 | tdo_byte = tdo_byte + (txrx(false, (tdi_byte&1) == 1) << (i%8)); 50 | 51 | if (tdi) 52 | tdi_byte = tdi_byte >> 1; 53 | 54 | i++; 55 | 56 | // Next byte 57 | if ((i%8) == 0) 58 | { 59 | // Save the TDO byte 60 | if(tdo) 61 | tdo[j] = tdo_byte; 62 | 63 | // Get the next TDI byte 64 | tdo_byte = 0; 65 | j++; 66 | 67 | if (tdi) 68 | tdi_byte = tdi[j]; 69 | } 70 | } 71 | 72 | tdo_byte = tdo_byte + (txrx(last, (tdi_byte&1)==1) << (i%8)); 73 | 74 | if(tdo) 75 | tdo[j]=tdo_byte; 76 | 77 | digitalWrite(TCKPin, LOW); 78 | 79 | return; 80 | } 81 | 82 | void IOWiringPi::tx_tms(unsigned char *pat, int length, int force) 83 | { 84 | int i; 85 | unsigned char tms; 86 | 87 | for (i = 0; i < length; i++) 88 | { 89 | if ((i & 0x7) == 0) 90 | tms = pat[i>>3]; 91 | 92 | tx((tms & 0x01), true); 93 | tms = tms >> 1; 94 | } 95 | 96 | digitalWrite(TCKPin, LOW); 97 | } 98 | 99 | void IOWiringPi::tx(bool tms, bool tdi) 100 | { 101 | digitalWrite(TCKPin, LOW); 102 | 103 | if(tdi) 104 | digitalWrite(TDIPin, HIGH); 105 | else 106 | digitalWrite(TDIPin, LOW); 107 | 108 | if(tms) 109 | digitalWrite(TMSPin, HIGH); 110 | else 111 | digitalWrite(TMSPin, LOW); 112 | 113 | digitalWrite(TCKPin, HIGH); 114 | } 115 | 116 | 117 | bool IOWiringPi::txrx(bool tms, bool tdi) 118 | { 119 | tx(tms, tdi); 120 | 121 | return digitalRead(TDOPin); 122 | } 123 | 124 | 125 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/IOWiringPi.h: -------------------------------------------------------------------------------- 1 | /* WiringPI implementation of XC3SPROG IOBase 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef __IO_WIRING_PI__ 21 | #define __IO_WIRING_PI__ 22 | 23 | #include "IOBase.h" 24 | 25 | class IOWiringPi : public IOBase 26 | { 27 | public: 28 | IOWiringPi(int tms, int tck, int tdi, int tdo); 29 | virtual ~IOWiringPi(); 30 | 31 | protected: 32 | void tx(bool tms, bool tdi); 33 | bool txrx(bool tms, bool tdi); 34 | 35 | void txrx_block(const unsigned char *tdi, unsigned char *tdo, int length, bool last); 36 | void tx_tms(unsigned char *pat, int length, int force); 37 | 38 | int TMSPin; 39 | int TCKPin; 40 | int TDIPin; 41 | int TDOPin; 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/IOXenium.h: -------------------------------------------------------------------------------- 1 | /* PI and Omega2/+ IOBase specialized for Xenium's CPLD 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef __IO_XENIUM__ 21 | #define __IO_XENIUM__ 22 | 23 | #include "XeniumDefines.h" 24 | 25 | #ifdef OMEGA2 26 | #include "IOOmega2.h" 27 | #define PLATFORMIO IOOmega2 28 | #else 29 | #include "IOWiringPi.h" 30 | #define PLATFORMIO IOWiringPi 31 | 32 | #endif 33 | 34 | class IOXenium : public PLATFORMIO 35 | { 36 | public: 37 | IOXenium() 38 | :PLATFORMIO(XENIUM_TMS, XENIUM_TCK, XENIUM_TDI, XENIUM_TDO) {} 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/JedecFile.cpp: -------------------------------------------------------------------------------- 1 | /* Jedec .jed file parser 2 | 3 | Copyright (C) Uwe Bonnes 2009 bon@elektron.ikp.physik.tu-darmstadt.de 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 18 | /* 19 | * Using a slightly corrected version from IPAL libjedec 20 | * Copyright (c) 2000 Stephen Williams (steve@icarus.com) 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "JedecFile.h" 31 | #include "io_exception.h" 32 | 33 | static unsigned char*allocate_fusemap(unsigned size) 34 | { 35 | unsigned char*ptr = (unsigned char*) calloc(size/8 + ((size%8)?1:0), 1); 36 | return ptr; 37 | } 38 | 39 | int jedec_get_fuse(jedec_data_t jed, unsigned idx) 40 | { 41 | unsigned int bval, bit; 42 | if(idx >= jed->fuse_count) 43 | throw io_exception(std::string("jedec_get_fuse")); 44 | 45 | bval = idx / 8; 46 | bit = idx % 8; 47 | return (jed->fuse_list[bval] & (1 << bit))? 1 : 0; 48 | } 49 | 50 | void jedec_set_fuse(jedec_data_t jed, unsigned idx, int blow) 51 | { 52 | unsigned int bval, bit; 53 | if(idx >= jed->fuse_count) 54 | throw io_exception(std::string("jedec_set_fuse")); 55 | 56 | bval = idx / 8; 57 | bit = idx % 8; 58 | 59 | if (blow) 60 | jed->fuse_list[bval] |= (1 << bit); 61 | else 62 | jed->fuse_list[bval] &= ~(1 << bit); 63 | } 64 | 65 | struct state_mach { 66 | jedec_data_t jed; 67 | 68 | void (*state)(int ch, struct state_mach*m); 69 | 70 | unsigned int checksum; 71 | union { 72 | struct { 73 | unsigned cur_fuse; 74 | } l; 75 | } m; 76 | }; 77 | 78 | static void m_startup(int ch, struct state_mach*m); 79 | static void m_header(int ch, struct state_mach*m); 80 | static void m_base(int ch, struct state_mach*m); 81 | static void m_C(int ch, struct state_mach*m); 82 | static void m_L(int ch, struct state_mach*m); 83 | static void m_Lfuse(int ch, struct state_mach*m); 84 | static void m_Q(int ch, struct state_mach*m); 85 | static void m_QF(int ch, struct state_mach*m); 86 | static void m_QP(int ch, struct state_mach*m); 87 | static void m_skip(int ch, struct state_mach*m); 88 | static void m_N(int ch, struct state_mach*m); 89 | 90 | int m_N_item; 91 | int m_N_pos; 92 | int m_H_pos = 0; 93 | char m_H_string[MAX_SIZE]; 94 | char m_N_strings[MAX_ITEM][MAX_SIZE]; 95 | 96 | static void m_startup(int ch, struct state_mach*m) 97 | { 98 | switch (ch) 99 | { 100 | case '\002': 101 | m->state = m_base; 102 | break; 103 | 104 | case 'D': 105 | m->state = m_header; 106 | break; 107 | 108 | default: 109 | break; 110 | } 111 | } 112 | 113 | static void m_header(int ch, struct state_mach*m) 114 | { 115 | switch (ch) 116 | { 117 | case '\n': 118 | case '\r': 119 | if (m_H_pos) 120 | { 121 | char * ptr = strchr( m_H_string, ':'); 122 | if (ptr) 123 | strncpy(m->jed->date, ptr, MAX_SIZE); 124 | } 125 | m->state = m_startup; 126 | break; 127 | default: 128 | m_H_string[m_H_pos] = ch; 129 | m_H_pos++; 130 | } 131 | } 132 | 133 | static void m_base(int ch, struct state_mach*m) 134 | { 135 | if (isspace(ch)) 136 | return; 137 | 138 | switch (ch) { 139 | case 'L': 140 | m->state = m_L; 141 | m->m.l.cur_fuse = 0; 142 | break; 143 | case 'Q': 144 | m->state = m_Q; 145 | break; 146 | case 'C': 147 | m->state = m_C; 148 | m->jed->checksum = 0; 149 | break; 150 | case 'N': 151 | m->state = m_N; 152 | m_N_item = -1; 153 | break; 154 | default: 155 | m->state = m_skip; 156 | break; 157 | } 158 | } 159 | 160 | static void m_C(int ch, struct state_mach*m) 161 | { 162 | if (isspace(ch)) 163 | return; 164 | 165 | if (ch == '*') { 166 | m->state = m_base; 167 | return; 168 | } 169 | 170 | if(ch >='0' && ch <='9') 171 | { 172 | m->jed->checksum <<=4; 173 | m->jed->checksum += ch - '0'; 174 | return; 175 | } 176 | ch &= 0x5f; 177 | if(ch >='A' && ch <= 'F') 178 | { 179 | m->jed->checksum <<=4; 180 | m->jed->checksum += ch - '7'; 181 | return; 182 | } 183 | 184 | fprintf(stderr, "m_C: Dangling '%c' 0x%02x\n", ch, ch); 185 | fflush(stderr); 186 | throw io_exception(std::string("m_C")); 187 | } 188 | static void m_L(int ch, struct state_mach*m) 189 | { 190 | if (isdigit(ch)) { 191 | m->m.l.cur_fuse *= 10; 192 | m->m.l.cur_fuse += ch - '0'; 193 | return; 194 | } 195 | 196 | if (isspace(ch)) { 197 | m->state = m_Lfuse; 198 | return; 199 | } 200 | 201 | if (ch == '*') { 202 | m->state = m_base; 203 | return; 204 | } 205 | 206 | fprintf(stderr, "m_L: Dangling '%c' 0x%02x\n", ch, ch); 207 | fflush(stderr); 208 | m->state = 0; 209 | } 210 | 211 | static void m_Lfuse(int ch, struct state_mach*m) 212 | { 213 | switch (ch) { 214 | 215 | case '*': 216 | m->state = m_base; 217 | break; 218 | 219 | case '0': 220 | jedec_set_fuse(m->jed, m->m.l.cur_fuse, 0); 221 | m->m.l.cur_fuse += 1; 222 | break; 223 | 224 | case '1': 225 | jedec_set_fuse(m->jed, m->m.l.cur_fuse, 1); 226 | m->m.l.cur_fuse += 1; 227 | break; 228 | 229 | case ' ': 230 | case '\n': 231 | case '\r': 232 | break; 233 | 234 | default: 235 | fprintf(stderr, "m_LFuse: Dangling '%c' 0x%02x\n", ch, ch); 236 | fflush(stderr); 237 | m->state = 0; 238 | break; 239 | } 240 | } 241 | 242 | #if defined(__unix__) || defined(__MACH__) 243 | #define stricmp strcasecmp 244 | #define strnicmp strncasecmp 245 | #endif 246 | 247 | static void m_N(int ch, struct state_mach*m) 248 | { 249 | switch (ch) { 250 | 251 | case '*': 252 | if ((stricmp(m_N_strings[0], "DEVICE")) == 0) 253 | { 254 | m_N_strings[m_N_item][m_N_pos] = 0; 255 | strncpy(m->jed->device, m_N_strings[1], MAX_SIZE); 256 | } 257 | if ((stricmp(m_N_strings[0], "VERSION")) == 0) 258 | { 259 | m_N_strings[m_N_item][m_N_pos] = 0; 260 | strncpy(m->jed->version, m_N_strings[1], MAX_SIZE); 261 | } 262 | m->state = m_base; 263 | m_N_item= -1; 264 | break; 265 | case ' ': 266 | if(m_N_item >=0) 267 | m_N_strings[m_N_item][m_N_pos] = 0; 268 | if (m_N_item < MAX_ITEM) 269 | { 270 | /* Don't stumble on too many items like in ISE XC2C Jedecfiles */ 271 | m_N_item++; 272 | } 273 | m_N_pos = 0; 274 | case '\n': 275 | case '\r': 276 | break; 277 | 278 | default: 279 | if((m_N_item >=0) && (m_N_item jed->fuse_count != 0) { 291 | m->state = 0; 292 | return; 293 | } 294 | m->state = m_QF; 295 | m->jed->fuse_count = 0; 296 | break; 297 | case 'P': 298 | if (m->jed->pin_count != 0) { 299 | m->state = 0; 300 | return; 301 | } 302 | m->state = m_QP; 303 | m->jed->pin_count = 0; 304 | break; 305 | default: 306 | m->state = m_skip; 307 | break; 308 | } 309 | } 310 | 311 | static void m_QF(int ch, struct state_mach*m) 312 | { 313 | if (isspace(ch)) 314 | return; 315 | 316 | if (isdigit(ch)) { 317 | m->jed->fuse_count *= 10; 318 | m->jed->fuse_count += ch - '0'; 319 | return; 320 | } 321 | 322 | if (ch == '*') { 323 | m->state = m_base; 324 | m->jed->fuse_list = allocate_fusemap(m->jed->fuse_count); 325 | return; 326 | } 327 | 328 | throw io_exception(std::string("m_QF")); 329 | } 330 | 331 | static void m_QP(int ch, struct state_mach*m) 332 | { 333 | if (isspace(ch)) 334 | return; 335 | 336 | if (isdigit(ch)) { 337 | m->jed->pin_count *= 10; 338 | m->jed->pin_count += ch - '0'; 339 | return; 340 | } 341 | 342 | if (ch == '*') { 343 | m->state = m_base; 344 | return; 345 | } 346 | 347 | throw io_exception(std::string("m_QP")); 348 | } 349 | 350 | static void m_skip(int ch, struct state_mach*m) 351 | { 352 | switch (ch) { 353 | case '*': 354 | m->state = m_base; 355 | break; 356 | 357 | default: 358 | break; 359 | } 360 | } 361 | JedecFile::JedecFile(void) 362 | : Error(false), logfile(stderr) 363 | { 364 | jed.checksum = 0; 365 | jed.fuse_count = 0; 366 | jed.pin_count = 0; 367 | jed.fuse_list = 0; 368 | jed.device[0] = 0; 369 | jed.version[0] = 0; 370 | jed.date[0] = 0; 371 | } 372 | 373 | JedecFile::~JedecFile(void) 374 | { 375 | if(jed.fuse_list) 376 | free(jed.fuse_list); 377 | } 378 | 379 | int JedecFile::readFile(FILE *fp) 380 | { 381 | int ch; 382 | struct state_mach m; 383 | 384 | if(!fp) 385 | return 1; 386 | 387 | m.jed = &jed; 388 | m.state = m_startup; 389 | while ((ch = fgetc(fp)) != EOF) { 390 | m.state(ch, &m); 391 | if (m.state == 0) { 392 | /* Some sort of error happened. */ 393 | return 2; 394 | } 395 | } 396 | if (!jed.fuse_count) 397 | return 3; 398 | return 0; 399 | } 400 | 401 | void JedecFile::saveAsJed(const char *device, FILE *fp) 402 | { 403 | unsigned int i, b=0, l=0 ,w=0; 404 | unsigned short chksum=0; 405 | unsigned int DRegLength; 406 | int type=-1; 407 | 408 | if (!fp) 409 | return; 410 | if (strnicmp("XC9536",device, sizeof("XC9536X")-1) == 0) 411 | { 412 | type = JED_XC95; 413 | } 414 | else if (strnicmp("XC9572",device, sizeof("XC9572X")-1) == 0) 415 | { 416 | type = JED_XC95; 417 | } 418 | else if (strnicmp("XC95108",device, sizeof("XC95144X")-1) == 0) 419 | { 420 | type = JED_XC95; 421 | } 422 | else if (strnicmp("XC95144",device, sizeof("XC95288X")-1) == 0) 423 | { 424 | type = JED_XC95; 425 | } 426 | else if (strnicmp("XC95216",device, sizeof("XC95288X")-1) == 0) 427 | { 428 | type = JED_XC95; 429 | } 430 | else if (strnicmp("XC95288",device, sizeof("XC95288X")-1) == 0) 431 | { 432 | type = JED_XC95; 433 | } 434 | else if (strnicmp("XC9536X",device, sizeof("XC9536X")-1) == 0) 435 | { 436 | type = JED_XC95X; 437 | DRegLength=2; 438 | } 439 | else if (strnicmp("XC9572X",device, sizeof("XC9572X")-1) == 0) 440 | { 441 | type = JED_XC95X; 442 | DRegLength=4; 443 | } 444 | else if (strnicmp("XC95144X",device, sizeof("XC95144X")-1) == 0) 445 | { 446 | type = JED_XC95X; 447 | DRegLength=8; 448 | } 449 | else if (strnicmp("XC95288X",device, sizeof("XC95288X")-1) == 0) 450 | { 451 | type = JED_XC95X; 452 | DRegLength=16; 453 | } 454 | else if (strnicmp("XC2C",device, sizeof("XC2C")-1) == 0) 455 | { 456 | type = JED_XC2C; 457 | } 458 | 459 | if (strlen(jed.date) == 0) 460 | { 461 | time_t t; 462 | struct tm *tmp; 463 | char outstr[200]; 464 | t = time(NULL); 465 | tmp = localtime(&t); 466 | if (tmp != NULL) 467 | { 468 | if (strftime(outstr, sizeof(outstr), "%a %b %d %T %Y", tmp)) 469 | fprintf(fp, "Date Extracted: %s\n\n", outstr); 470 | } 471 | } 472 | else 473 | fprintf(fp, "Date Extracted%s\n\n",jed.date); 474 | fprintf(fp, "\2QF%d*\nQV0*\nF0*\nX0*\nJ0 0*\n",jed.fuse_count); 475 | if (strlen(jed.version) == 0) 476 | fprintf(fp, "N VERSION XC3SPROG*\n"); 477 | else 478 | fprintf(fp, "N VERSION %s*\n",jed.version); 479 | fprintf(fp, "N DEVICE %s*\n", device); 480 | 481 | if(type == JED_XC95X) 482 | { 483 | /* Xilinx Impact (10.1) needs following additional items 484 | to recognizes as a valid Jedec File 485 | * the 4 Digits as total Checksum 486 | * N DEVICE 487 | */ 488 | 489 | for (i=0; i jed.fuse_count) 566 | { 567 | if (jed.fuse_list) 568 | free(jed.fuse_list); 569 | jed.fuse_list = new byte[f_count/8 + ((f_count%8)?1:0)]; 570 | memset(jed.fuse_list, 0xff, f_count/8 + ((f_count%8)?1:0)); 571 | } 572 | else 573 | { 574 | for (unsigned int i = f_count; i < jed.fuse_count; i++) 575 | set_fuse(i, 0); 576 | } 577 | jed.fuse_count = f_count; 578 | } 579 | 580 | void JedecFile::set_fuse(unsigned int idx, int blow) 581 | { 582 | jedec_set_fuse(&jed, idx,blow); 583 | } 584 | 585 | int JedecFile::get_fuse(unsigned int idx) 586 | { 587 | return jedec_get_fuse(&jed, idx); 588 | } 589 | 590 | unsigned short JedecFile::calcChecksum() 591 | { 592 | unsigned int i; 593 | unsigned short cc=0; 594 | 595 | for(i=0; i<(jed.fuse_count/8 + ((jed.fuse_count%8)?1:0)); i++) 596 | cc += jed.fuse_list[i]; 597 | return cc; 598 | } 599 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/JedecFile.h: -------------------------------------------------------------------------------- 1 | /* Jedec .jed file parser 2 | 3 | Copyright (C) Uwe Bonnes 2009 bon@elektron.ikp.physik.tu-darmstadt.de 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 18 | 19 | /* 20 | * Using a slightly corrected version from IPAL libjedec 21 | * Copyright (c) 2000 Stephen Williams (steve@icarus.com) 22 | */ 23 | 24 | #ifndef JEDECFILE_H 25 | #define JEDECFILE_H 26 | 27 | #include 28 | 29 | #define MAX_ITEM 8 30 | #define MAX_SIZE 256 31 | typedef unsigned char byte; 32 | 33 | struct jedec_data { 34 | char device[MAX_SIZE]; 35 | char version[MAX_SIZE]; 36 | char date[MAX_SIZE]; 37 | 38 | unsigned fuse_count; 39 | unsigned pin_count; 40 | unsigned vector_count; 41 | unsigned checksum; 42 | unsigned char fuse_default; 43 | 44 | unsigned char*fuse_list; 45 | }; 46 | typedef struct jedec_data *jedec_data_t; 47 | 48 | #define JED_XC95X 0 49 | #define JED_XC2C 1 50 | #define JED_XC95 2 51 | 52 | class JedecFile 53 | { 54 | private: 55 | struct jedec_data jed; 56 | bool Error; 57 | std::string errorStr; 58 | FILE *logfile; 59 | 60 | public: 61 | JedecFile(void); 62 | ~JedecFile(); 63 | 64 | public: 65 | int readFile(FILE *fp); 66 | inline unsigned int getLength(){return jed.fuse_count;} 67 | inline unsigned short getChecksum(){return jed.checksum;} 68 | char *getDevice(){return jed.device;} 69 | char *getVersion(){return jed.version;} 70 | char *getDate(){return jed.date;} 71 | unsigned short calcChecksum(); 72 | void setLength(unsigned int fuse_count); 73 | int get_fuse(unsigned int idx); 74 | void set_fuse(unsigned int idx, int blow); 75 | void saveAsJed(const char * device, FILE *fp); 76 | }; 77 | #endif //JEDECFILE_H 78 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/Jtag.cpp: -------------------------------------------------------------------------------- 1 | /* JTAG routines 2 | 3 | Copyright (C) 2004 Andrew Rogers 4 | Copyright (C) 2005-2009 Uwe Bonnes 5 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | Changes: 22 | Koos du Preez [kdupreez@hotmail.com] Jan 1 2019 23 | Removed everything not needed for Raspberry PI and Xilinx xc9572xl 24 | Renamed files to match class names - a pet peeve of mine :) 25 | Modernized to use smartpointers 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | #include "Jtag.h" 32 | #include 33 | 34 | Jtag::Jtag(std::unique_ptr iob) 35 | : io(std::move(iob)) 36 | 37 | { 38 | verbose = false; 39 | current_state = UNKNOWN; 40 | postDRState = RUN_TEST_IDLE; 41 | postIRState = RUN_TEST_IDLE; 42 | deviceIndex = -1; 43 | numDevices = -1; 44 | shiftDRincomplete=false; 45 | char *fname = getenv("JTAG_DEBUG"); 46 | if (fname) 47 | fp_dbg = fopen(fname,"wb"); 48 | else 49 | fp_dbg = NULL; 50 | } 51 | 52 | Jtag::~Jtag(void) 53 | { 54 | if(fp_dbg) 55 | fclose(fp_dbg); 56 | } 57 | 58 | /* Detect chain length on first start, return chain length else*/ 59 | int Jtag::getChain(bool detect) 60 | { 61 | if(numDevices == -1 || detect) 62 | { 63 | tapTestLogicReset(); 64 | setTapState(SHIFT_DR); 65 | byte idx[4]; 66 | byte zero[4]; 67 | numDevices=0; 68 | for(int i=0; i<4; i++)zero[i]=0; 69 | do{ 70 | io->shiftTDITDO(zero,idx,32,false); 71 | unsigned long id=byteArrayToLong(idx); 72 | if(id!=0 && id !=0xffffffff){ 73 | numDevices++; 74 | chainParam_t dev; 75 | dev.idcode=id; 76 | devices.insert(devices.begin(),dev); 77 | } 78 | else{ 79 | if (id == 0xffffffff && numDevices >0) 80 | { 81 | fprintf(stderr,"Probably a broken Atmel device in your chain!\n"); 82 | fprintf(stderr,"No succeeding device can be identified\n"); 83 | } 84 | break; 85 | } 86 | }while(numDevices=numDevices)deviceIndex=-1; 122 | else deviceIndex=dev; 123 | if(fp_dbg) 124 | fprintf(fp_dbg,"selectDevices %d\n", deviceIndex); 125 | return deviceIndex; 126 | } 127 | 128 | void Jtag::cycleTCK(int n, bool tdi) 129 | { 130 | if(current_state==TEST_LOGIC_RESET) 131 | fprintf(stderr, "cycleTCK in TEST_LOGIC_RESET\n"); 132 | if(fp_dbg) 133 | fprintf(fp_dbg, "cycleTCK %d TDI %s\n", n, (tdi)?"TRUE":"FALSE"); 134 | io->shift(tdi, n, false); 135 | } 136 | 137 | int Jtag::setDeviceIRLength(int dev, int len) 138 | { 139 | if(dev>=numDevices||dev<0)return -1; 140 | devices[dev].irlen=len; 141 | return dev; 142 | } 143 | 144 | void Jtag::shiftDR(const byte *tdi, byte *tdo, int length, 145 | int align, bool exit) 146 | { 147 | if(deviceIndex<0)return; 148 | int post=deviceIndex; 149 | 150 | if(!shiftDRincomplete){ 151 | int pre=numDevices-deviceIndex-1; 152 | if(align){ 153 | pre=-post; 154 | while(pre<=0)pre+=align; 155 | } 156 | /* We can combine the pre bits to reach the target device with 157 | the TMS bits to reach the SHIFT-DR state, as the pre bit can be '0'*/ 158 | setTapState(SHIFT_DR,pre); 159 | } 160 | if(fp_dbg) 161 | { 162 | fprintf(fp_dbg, "shiftDR len %d\n", length); 163 | if (tdi) 164 | { 165 | int i; 166 | fprintf(fp_dbg, "In:\n" ); 167 | for (i=0; i< (length+7)>>3; i++) 168 | { 169 | fprintf(fp_dbg, " %02x", tdi[i]); 170 | if (i % 26== 25) 171 | fprintf(fp_dbg, "\n"); 172 | } 173 | fprintf(fp_dbg, "\n"); 174 | } 175 | } 176 | if(tdi!=0&&tdo!=0)io->shiftTDITDO(tdi,tdo,length,post==0&&exit); 177 | else if(tdi!=0&&tdo==0)io->shiftTDI(tdi,length,post==0&&exit); 178 | else if(tdi==0&&tdo!=0)io->shiftTDO(tdo,length,post==0&&exit); 179 | else io->shift(false,length,post==0&&exit); 180 | if(fp_dbg) 181 | { 182 | if (tdo) 183 | { 184 | int i; 185 | fprintf(fp_dbg, "Out:\n" ); 186 | for (i=0; i< (length+7)>>3; i++) 187 | { 188 | fprintf(fp_dbg, " %02x", tdo[i]); 189 | if (i % 26 == 25) 190 | fprintf(fp_dbg, "\n"); 191 | } 192 | fprintf(fp_dbg, "\n"); 193 | } 194 | } 195 | nextTapState(post==0&&exit); // If TMS is set the the state of the tap changes 196 | if(exit){ 197 | io->shift(false,post); 198 | if (!(post==0&&exit)) 199 | nextTapState(true); 200 | setTapState(postDRState); 201 | shiftDRincomplete=false; 202 | } 203 | else shiftDRincomplete=true; 204 | } 205 | 206 | void Jtag::shiftIR(const byte *tdi, byte *tdo) 207 | { 208 | if(deviceIndex<0)return; 209 | setTapState(SHIFT_IR); 210 | if(fp_dbg) 211 | { 212 | fprintf(fp_dbg, "shiftIR "); 213 | if (tdi) 214 | fprintf(fp_dbg, "In: %02x", *tdi ); 215 | } 216 | int pre=0; 217 | for(int dev=deviceIndex+1; devshift(true,pre,false); 223 | if(tdo!=0)io->shiftTDITDO(tdi,tdo,devices[deviceIndex].irlen,post==0); 224 | else if(tdo==0)io->shiftTDI(tdi,devices[deviceIndex].irlen,post==0); 225 | io->shift(true,post); 226 | if(fp_dbg) 227 | { 228 | if (tdo) 229 | fprintf(fp_dbg, "Out: %02x", *tdo); 230 | fprintf(fp_dbg, "\n"); 231 | } 232 | nextTapState(true); 233 | setTapState(postIRState); 234 | } 235 | 236 | void Jtag::setTapState(tapState_t state, int pre) 237 | { 238 | bool tms; 239 | while(current_state!=state){ 240 | switch(current_state){ 241 | 242 | case TEST_LOGIC_RESET: 243 | switch(state){ 244 | case TEST_LOGIC_RESET: 245 | tms=true; 246 | break; 247 | default: 248 | tms=false; 249 | current_state=RUN_TEST_IDLE; 250 | }; 251 | break; 252 | 253 | case RUN_TEST_IDLE: 254 | switch(state){ 255 | case RUN_TEST_IDLE: 256 | tms=false; 257 | break; 258 | default: 259 | tms=true; 260 | current_state=SELECT_DR_SCAN; 261 | }; 262 | break; 263 | 264 | case SELECT_DR_SCAN: 265 | switch(state){ 266 | case CAPTURE_DR: 267 | case SHIFT_DR: 268 | case EXIT1_DR: 269 | case PAUSE_DR: 270 | case EXIT2_DR: 271 | case UPDATE_DR: 272 | tms=false; 273 | current_state=CAPTURE_DR; 274 | break; 275 | default: 276 | tms=true; 277 | current_state=SELECT_IR_SCAN; 278 | }; 279 | break; 280 | 281 | case CAPTURE_DR: 282 | switch(state){ 283 | case SHIFT_DR: 284 | tms=false; 285 | current_state=SHIFT_DR; 286 | break; 287 | default: 288 | tms=true; 289 | current_state=EXIT1_DR; 290 | }; 291 | break; 292 | 293 | case SHIFT_DR: 294 | switch(state){ 295 | case SHIFT_DR: 296 | tms=false; 297 | break; 298 | default: 299 | tms=true; 300 | current_state=EXIT1_DR; 301 | }; 302 | break; 303 | 304 | case EXIT1_DR: 305 | switch(state){ 306 | case PAUSE_DR: 307 | case EXIT2_DR: 308 | case SHIFT_DR: 309 | case EXIT1_DR: 310 | tms=false; 311 | current_state=PAUSE_DR; 312 | break; 313 | default: 314 | tms=true; 315 | current_state=UPDATE_DR; 316 | }; 317 | break; 318 | 319 | case PAUSE_DR: 320 | switch(state){ 321 | case PAUSE_DR: 322 | tms=false; 323 | break; 324 | default: 325 | tms=true; 326 | current_state=EXIT2_DR; 327 | }; 328 | break; 329 | 330 | case EXIT2_DR: 331 | switch(state){ 332 | case SHIFT_DR: 333 | case EXIT1_DR: 334 | case PAUSE_DR: 335 | tms=false; 336 | current_state=SHIFT_DR; 337 | break; 338 | default: 339 | tms=true; 340 | current_state=UPDATE_DR; 341 | }; 342 | break; 343 | 344 | case UPDATE_DR: 345 | switch(state){ 346 | case RUN_TEST_IDLE: 347 | tms=false; 348 | current_state=RUN_TEST_IDLE; 349 | break; 350 | default: 351 | tms=true; 352 | current_state=SELECT_DR_SCAN; 353 | }; 354 | break; 355 | 356 | case SELECT_IR_SCAN: 357 | switch(state){ 358 | case CAPTURE_IR: 359 | case SHIFT_IR: 360 | case EXIT1_IR: 361 | case PAUSE_IR: 362 | case EXIT2_IR: 363 | case UPDATE_IR: 364 | tms=false; 365 | current_state=CAPTURE_IR; 366 | break; 367 | default: 368 | tms=true; 369 | current_state=TEST_LOGIC_RESET; 370 | }; 371 | break; 372 | 373 | case CAPTURE_IR: 374 | switch(state){ 375 | case SHIFT_IR: 376 | tms=false; 377 | current_state=SHIFT_IR; 378 | break; 379 | default: 380 | tms=true; 381 | current_state=EXIT1_IR; 382 | }; 383 | break; 384 | 385 | case SHIFT_IR: 386 | switch(state){ 387 | case SHIFT_IR: 388 | tms=false; 389 | break; 390 | default: 391 | tms=true; 392 | current_state=EXIT1_IR; 393 | }; 394 | break; 395 | 396 | case EXIT1_IR: 397 | switch(state){ 398 | case PAUSE_IR: 399 | case EXIT2_IR: 400 | case SHIFT_IR: 401 | case EXIT1_IR: 402 | tms=false; 403 | current_state=PAUSE_IR; 404 | break; 405 | default: 406 | tms=true; 407 | current_state=UPDATE_IR; 408 | }; 409 | break; 410 | 411 | case PAUSE_IR: 412 | switch(state){ 413 | case PAUSE_IR: 414 | tms=false; 415 | break; 416 | default: 417 | tms=true; 418 | current_state=EXIT2_IR; 419 | }; 420 | break; 421 | 422 | case EXIT2_IR: 423 | switch(state){ 424 | case SHIFT_IR: 425 | case EXIT1_IR: 426 | case PAUSE_IR: 427 | tms=false; 428 | current_state=SHIFT_IR; 429 | break; 430 | default: 431 | tms=true; 432 | current_state=UPDATE_IR; 433 | }; 434 | break; 435 | 436 | case UPDATE_IR: 437 | switch(state){ 438 | case RUN_TEST_IDLE: 439 | tms=false; 440 | current_state=RUN_TEST_IDLE; 441 | break; 442 | default: 443 | tms=true; 444 | current_state=SELECT_DR_SCAN; 445 | }; 446 | break; 447 | 448 | default: 449 | tapTestLogicReset(); 450 | tms=true; 451 | }; 452 | if(fp_dbg) 453 | fprintf(fp_dbg,"TMS %d: %s\n", tms, getStateName(current_state)); 454 | io->set_tms(tms); 455 | } 456 | for(int i=0; iset_tms(false); 458 | } 459 | 460 | // After shift data into the DR or IR we goto the next state 461 | // This function should only be called from the end of a shift function 462 | void Jtag::nextTapState(bool tms) 463 | { 464 | if(current_state==SHIFT_DR){ 465 | if(tms)current_state=EXIT1_DR; // If TMS was set then goto next state 466 | } 467 | else if(current_state==SHIFT_IR){ 468 | if(tms)current_state=EXIT1_IR; // If TMS was set then goto next state 469 | } 470 | else 471 | { 472 | fprintf(stderr,"Unexpected state %d\n",current_state); 473 | tapTestLogicReset(); // We were in an unexpected state 474 | } 475 | } 476 | 477 | void Jtag::tapTestLogicReset() 478 | { 479 | int i; 480 | for(i=0; i<5; i++) 481 | io->set_tms(true); 482 | current_state=TEST_LOGIC_RESET; 483 | io->flush_tms(true); 484 | } 485 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/Jtag.h: -------------------------------------------------------------------------------- 1 | /* JTAG routines 2 | 3 | Copyright (C) 2004 Andrew Rogers 4 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | Changes: 21 | Koos du Preez [kdupreez@hotmail.com] Jan 1 2019 22 | Removed everything not needed for Raspberry PI and Xilinx xc9572xl 23 | Renamed files to match class names - a pet peeve of mine :) 24 | Modernized to use smartpointers 25 | */ 26 | 27 | 28 | 29 | #ifndef JTAG_H 30 | #define JTAG_H 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "IOBase.h" 38 | 39 | typedef unsigned char byte; 40 | typedef uint32_t DeviceID; 41 | 42 | class Jtag 43 | { 44 | public: 45 | enum tapState_t{ 46 | TEST_LOGIC_RESET=0, 47 | RUN_TEST_IDLE=1, 48 | SELECT_DR_SCAN=2, 49 | CAPTURE_DR=3, 50 | SHIFT_DR=4, 51 | EXIT1_DR=5, 52 | PAUSE_DR=6, 53 | EXIT2_DR=7, 54 | UPDATE_DR=8, 55 | SELECT_IR_SCAN=9, 56 | CAPTURE_IR=10, 57 | SHIFT_IR=11, 58 | EXIT1_IR=12, 59 | PAUSE_IR=13, 60 | EXIT2_IR=14, 61 | UPDATE_IR=15, 62 | UNKNOWN=999 63 | }; 64 | 65 | private: 66 | bool verbose; 67 | tapState_t current_state; 68 | static const int MAXNUMDEVICES=1000; 69 | protected: 70 | struct chainParam_t 71 | { 72 | DeviceID idcode; // Store IDCODE 73 | int irlen; // instruction register length. 74 | }; 75 | std::vector devices; 76 | std::unique_ptr io; 77 | int numDevices; 78 | tapState_t postDRState; 79 | tapState_t postIRState; 80 | int deviceIndex; 81 | FILE *fp_svf; 82 | bool shiftDRincomplete; 83 | FILE *fp_dbg; 84 | const char* getStateName(tapState_t s); 85 | public: 86 | Jtag(std::unique_ptr iob); 87 | ~Jtag(); 88 | void setVerbose(bool v) { verbose = v; } 89 | bool getVerbose(void) { return verbose; } 90 | int getChain(bool detect = false); // Shift IDCODEs from devices 91 | inline void setPostDRState(tapState_t s){postDRState=s;} 92 | inline void setPostIRState(tapState_t s){postIRState=s;} 93 | void setTapState(tapState_t state, int pre=0); 94 | void tapTestLogicReset(void); 95 | void nextTapState(bool tms); 96 | void cycleTCK(int n, bool tdi=1); 97 | tapState_t getTapState(void); 98 | int setDeviceIRLength(int dev, int len); 99 | DeviceID getDeviceID(unsigned int dev){ 100 | if(dev>=devices.size())return 0; 101 | return devices[dev].idcode; 102 | } 103 | void Usleep(unsigned int usec) {io->Usleep(usec);} 104 | int selectDevice(int dev); 105 | void shiftDR(const byte *tdi, byte *tdo, int length, int align=0, bool exit=true);// Some devices use TCK for aligning data, for example, Xilinx FPGAs for configuration data. 106 | void shiftIR(const byte *tdi, byte *tdo=0); // No length argumant required as IR length specified in chainParam_t 107 | inline void longToByteArray(unsigned long l, byte *b){ 108 | b[0]=(byte)(l&0xff); 109 | b[1]=(byte)((l>>8)&0xff); 110 | b[2]=(byte)((l>>16)&0xff); 111 | b[3]=(byte)((l>>24)&0xff); 112 | } 113 | 114 | inline void shortToByteArray(const unsigned short l, byte *b){ 115 | b[0]=(byte)(l&0xff); 116 | b[1]=(byte)((l>>8)&0xff); 117 | } 118 | inline unsigned long byteArrayToLong(const byte *b){ 119 | return ((unsigned long)b[3]<<24)+((unsigned long)b[2]<<16)+ 120 | ((unsigned long)b[1]<<8)+(unsigned long)b[0]; 121 | } 122 | static inline uint16_t byteArrayToShort(const byte *b) { 123 | return ((uint16_t)b[0]) | (((uint16_t)b[1]) << 8); 124 | } 125 | }; 126 | 127 | #endif //JTAG_H 128 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/ProgAlgXC95X.cpp: -------------------------------------------------------------------------------- 1 | /* XC95 CPLD JTAG programming algorithms 2 | 3 | Copyright (C) Copyright 2001 Nahitafu,Naitou Ryuji 4 | Copyright (C) 2008-2009 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de 5 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | Changes: 22 | Koos du Preez [kdupreez@hotmail.com] Jan 1 2019 23 | Accepts device ID and figures out DRLength 24 | */ 25 | 26 | /* Based on the Xilinx 1532 BSDL Files and alg95??.cpp for naxjp */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include "ProgAlgXC95X.h" 32 | 33 | const byte ProgAlgXC95X::ISC_NOOP=0xff; 34 | const byte ProgAlgXC95X::ISC_DISABLE=0xf0; 35 | const byte ProgAlgXC95X::ISC_ERASE=0xed; 36 | const byte ProgAlgXC95X::ISC_PROGRAM=0xea; 37 | const byte ProgAlgXC95X::ISC_READ=0xee; 38 | const byte ProgAlgXC95X::ISC_ENABLE=0xe9; 39 | 40 | const byte ProgAlgXC95X::XSC_BLANK_CHECK=0xe5; 41 | 42 | const byte ProgAlgXC95X::BYPASS=0xff; 43 | 44 | #define deltaT(tvp1, tvp2) (((tvp2)->tv_sec-(tvp1)->tv_sec)*1000000 + \ 45 | (tvp2)->tv_usec - (tvp1)->tv_usec) 46 | 47 | ProgAlgXC95X::ProgAlgXC95X(Jtag &j, const uint32_t device_id) 48 | { 49 | jtag=&j; 50 | 51 | int dr_type = (device_id & 0x000ff000) >> 13; 52 | switch (dr_type) 53 | { 54 | case 1: DRegLength = 2; 55 | break; 56 | case 2: DRegLength = 4; 57 | break; 58 | case 4: DRegLength = 8; 59 | break; 60 | case 11: DRegLength = 16; 61 | break; 62 | default: fprintf(stderr, "Unknown device\n"); 63 | } 64 | } 65 | 66 | void ProgAlgXC95X::flow_enable() 67 | { 68 | byte data[1]; 69 | 70 | jtag->shiftIR(&ISC_ENABLE); 71 | data[0]=0x15; 72 | jtag->shiftDR(data,0,6); 73 | jtag->cycleTCK(1); 74 | } 75 | 76 | void ProgAlgXC95X::flow_disable() 77 | { 78 | jtag->shiftIR(&ISC_DISABLE); 79 | jtag->Usleep(100); 80 | jtag->shiftIR(&BYPASS); 81 | jtag->cycleTCK(1); 82 | } 83 | 84 | 85 | void ProgAlgXC95X::flow_error_exit() 86 | { 87 | jtag->shiftIR(&ISC_NOOP); 88 | jtag->cycleTCK(1); 89 | } 90 | 91 | int ProgAlgXC95X::flow_blank_check() 92 | { 93 | byte i_data[3]={0x3,0,0}; 94 | byte o_data[3]; 95 | jtag->shiftIR(&XSC_BLANK_CHECK); 96 | jtag->shiftDR(i_data, 0,18); 97 | jtag->cycleTCK(500); 98 | jtag->shiftDR(0,o_data,18); 99 | if(jtag->getVerbose()) 100 | { 101 | if ((o_data[0] & 0x03) == 0x01) 102 | fprintf(stderr, "Device is blank\n"); 103 | else 104 | fprintf(stderr, "Device is not blank\n"); 105 | } 106 | return ((o_data[0] & 0x03) == 0x01); 107 | 108 | } 109 | 110 | void ProgAlgXC95X::flow_erase() 111 | { 112 | byte data[3] = {0x03, 0, 0}; 113 | jtag->shiftIR(&ISC_ERASE); 114 | jtag->shiftDR(data,0,18); 115 | jtag->Usleep(500000); 116 | jtag->shiftDR(0,data,18); 117 | if((data[0]& 0x03) != 0x01) 118 | fprintf(stderr, "Erase still running %02x\n", data[0]); 119 | } 120 | 121 | #define MaxSector 108 122 | #define MaxDRegLength 16 123 | 124 | int ProgAlgXC95X::flow_array_program(JedecFile &file) 125 | { 126 | byte preamble[1]= {0x01}; 127 | byte i_data[MaxDRegLength+2]; 128 | byte o_data[MaxDRegLength+3]; 129 | struct timeval tv[2]; 130 | unsigned long Addr=0; 131 | int bitlen; 132 | int k, sec,l,m; 133 | unsigned char data; 134 | unsigned int idx=0; 135 | 136 | 137 | gettimeofday(tv, NULL); 138 | for(sec=0;sec < MaxSector;sec++) 139 | { 140 | if(jtag->getVerbose()) 141 | { 142 | fprintf(stderr, " \r" 143 | "Programming Sector %3d", sec); 144 | } 145 | preamble[0]= 0x01; 146 | for(l=0;l<3;l++){ 147 | for(m=0;m<5;m++){ 148 | Addr = sec*0x20 + l*0x08 + m; 149 | i_data[DRegLength] = (byte) (Addr &0xff); 150 | i_data[DRegLength+1] = (byte) ((Addr>>8) &0xff); 151 | if(l*5+m >= 9){ 152 | bitlen=6; 153 | } 154 | else{ 155 | bitlen=8; 156 | } 157 | for(int j=0;jUsleep(1000); /*FIXME: IOFTDI Buffer causes abort with high 169 | rate on some board otherwise*/ 170 | jtag->shiftIR(&ISC_PROGRAM); 171 | jtag->shiftDR(preamble,0,2,0,false); 172 | jtag->shiftDR(i_data,0,(DRegLength+2)*8); 173 | if((l == 2) && (m == 4)) 174 | jtag->Usleep(50000); 175 | else 176 | jtag->cycleTCK(1); 177 | if ((l == 2) && (m == 4)) 178 | { 179 | preamble[0]= 0x00; 180 | for(k=0; k< 32; k++) 181 | { 182 | jtag->shiftIR(&ISC_PROGRAM); 183 | jtag->shiftDR(preamble, 0,2,0,false); 184 | jtag->shiftDR(i_data, 0,(DRegLength+2)*8); 185 | jtag->Usleep(50000); 186 | jtag->shiftDR(0,o_data, ((DRegLength+2)*8)+2); 187 | if(jtag->getVerbose()) 188 | { 189 | fprintf(stderr, "."); 190 | fflush(stderr); 191 | } 192 | if ((o_data[0] & 0x03) == 0x01) 193 | break; 194 | } 195 | if (k == 32) 196 | { 197 | fprintf(stderr, "failed\n"); 198 | return 1; 199 | } 200 | } 201 | } 202 | } 203 | } 204 | gettimeofday(tv+1, NULL); 205 | if(jtag->getVerbose()) 206 | fprintf(stderr, "\nProgramming time %.1f ms\n", 207 | (double)deltaT(tv, tv + 1)/1.0e3); 208 | return 0; 209 | } 210 | 211 | void ProgAlgXC95X::flow_array_read(JedecFile &rbfile) 212 | { 213 | byte preamble[1]= {0x03}; 214 | byte i_data[MaxDRegLength+2]; 215 | byte o_data[MaxDRegLength+2]; 216 | struct timeval tv[2]; 217 | 218 | unsigned long Addr=0; 219 | int bitlen; 220 | int sec,l,m; 221 | unsigned char data; 222 | unsigned int idx=0; 223 | 224 | gettimeofday(tv, NULL); 225 | for(sec=0;sec < MaxSector;sec++) 226 | { 227 | if(jtag->getVerbose()) 228 | { 229 | fprintf(stderr, "\rReading Sector %3d", sec); 230 | fflush(stderr); 231 | } 232 | for(l=0;l<3;l++){ 233 | for(m=0;m<5;m++){ 234 | Addr = sec*0x20 + l*0x08 + m; 235 | i_data[DRegLength] = (byte) (Addr &0xff); 236 | i_data[DRegLength+1] = (byte) ((Addr>>8) &0xff); 237 | jtag->shiftIR(&ISC_READ); 238 | jtag->shiftDR(preamble,0,2,0,false); 239 | jtag->shiftDR(i_data,o_data,(DRegLength+2)*8); 240 | jtag->cycleTCK(1); 241 | if(sec | l | m ) 242 | { 243 | for(int j=0;j> 1; 250 | } 251 | } 252 | } 253 | if(l*5+m >= 9){ 254 | bitlen=6; 255 | } 256 | else{ 257 | bitlen=8; 258 | } 259 | } 260 | } 261 | } 262 | /* Now read the security fuses*/ 263 | jtag->shiftIR(&ISC_READ); 264 | jtag->shiftDR(preamble,0,2,0,false); 265 | jtag->shiftDR(i_data,o_data,(DRegLength+2)*8); 266 | for(int j=0;j> 1; 272 | } 273 | } 274 | 275 | gettimeofday(tv+1, NULL); 276 | if(jtag->getVerbose()) 277 | fprintf(stderr, "\nReadback time %.1f ms\n", 278 | (double)deltaT(tv, tv + 1)/1.0e3); 279 | } 280 | 281 | int ProgAlgXC95X::flow_array_verify(JedecFile &file) 282 | { 283 | byte preamble[1]= {0x03}; 284 | byte i_data[MaxDRegLength+2]; 285 | byte o_data[MaxDRegLength+2]; 286 | struct timeval tv[2]; 287 | 288 | unsigned long Addr=0; 289 | int bitlen; 290 | int sec,l,m; 291 | unsigned char data; 292 | unsigned int idx=0; 293 | 294 | gettimeofday(tv, NULL); 295 | for(sec=0;sec < MaxSector;sec++) 296 | { 297 | if(jtag->getVerbose()) 298 | { 299 | fprintf(stderr, "\rVerify Sector %3d", sec); 300 | fflush(stderr); 301 | } 302 | for(l=0;l<3;l++){ 303 | for(m=0;m<5;m++){ 304 | Addr = sec*0x20 + l*0x08 + m; 305 | i_data[DRegLength] = (byte) (Addr &0xff); 306 | i_data[DRegLength+1] = (byte) ((Addr>>8) &0xff); 307 | jtag->shiftIR(&ISC_READ); 308 | jtag->shiftDR(preamble,0,2,0,false); 309 | jtag->shiftDR(i_data,o_data,(DRegLength+2)*8); 310 | jtag->cycleTCK(1); 311 | if(sec | l | m ) 312 | { 313 | for(int j=0;j> 1; 325 | idx++; 326 | } 327 | } 328 | } 329 | if(l*5+m >= 9){ 330 | bitlen=6; 331 | } 332 | else{ 333 | bitlen=8; 334 | } 335 | } 336 | } 337 | } 338 | /* Now read the security fuses*/ 339 | jtag->shiftIR(&ISC_READ); 340 | jtag->shiftDR(preamble,0,2,0,false); 341 | jtag->shiftDR(i_data,o_data,(DRegLength+2)*8); 342 | for(int j=0;j> 1; 354 | } 355 | } 356 | 357 | gettimeofday(tv+1, NULL); 358 | if(jtag->getVerbose()) 359 | fprintf(stderr, "\nSuccess! Verify time %.1f ms\n", 360 | (double)deltaT(tv, tv + 1)/1.0e3); 361 | return 0; 362 | } 363 | 364 | void ProgAlgXC95X::array_read(JedecFile &file) 365 | { 366 | file.setLength(108*108* DRegLength); 367 | flow_enable(); 368 | flow_array_read(file); 369 | flow_disable(); 370 | } 371 | 372 | int ProgAlgXC95X::array_program(JedecFile &file) 373 | { 374 | return flow_array_program(file); 375 | } 376 | 377 | int ProgAlgXC95X::array_verify(JedecFile &file) 378 | { 379 | int ret; 380 | flow_enable(); 381 | ret = flow_array_verify(file); 382 | flow_disable(); 383 | return ret; 384 | } 385 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/ProgAlgXC95X.h: -------------------------------------------------------------------------------- 1 | /* XC95 CPLD JTAG programming algorithms 2 | 3 | Copyright (C) 2008 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de 4 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | Changes: 21 | Koos du Preez [kdupreez@hotmail.com] Jan 1 2019 22 | Accepts device ID and figures out DRLength 23 | */ 24 | 25 | /* 26 | * Based on the Xilinx 1532 BSDL Files and alg95??.cpp for naxjp */ 27 | 28 | 29 | 30 | #ifndef PROGALGXC95X_H 31 | #define PROGALGXC95X_H 32 | 33 | #include "Jtag.h" 34 | #include "JedecFile.h" 35 | 36 | class ProgAlgXC95X 37 | { 38 | private: 39 | static const byte ISC_NOOP; 40 | static const byte ISC_DISABLE; 41 | static const byte ISC_ERASE; 42 | static const byte ISC_PROGRAM; 43 | static const byte ISC_READ; 44 | static const byte ISC_ENABLE; 45 | 46 | static const byte XSC_BLANK_CHECK; 47 | 48 | static const byte BYPASS; 49 | 50 | Jtag *jtag; 51 | int DRegLength; 52 | void flow_enable(); 53 | void flow_disable(); 54 | void flow_error_exit(); 55 | void flow_array_read(JedecFile &file); 56 | int flow_array_program(JedecFile &file); 57 | int flow_array_verify(JedecFile &file); 58 | int flow_blank_check(); 59 | void flow_erase(); 60 | public: 61 | ProgAlgXC95X(Jtag &j, const uint32_t device_id); 62 | int blank_check(){flow_enable(); int ret= flow_blank_check(); flow_disable(); return ret;}; 63 | int erase(){flow_enable(); flow_erase(); return flow_blank_check();}; 64 | int array_verify(JedecFile &file); 65 | void array_read(JedecFile &file); 66 | int array_program(JedecFile &file); 67 | }; 68 | 69 | 70 | 71 | #endif //PROGALGXC95X_H 72 | -------------------------------------------------------------------------------- /xenium-flash/src/jtag/io_exception.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (C) 2008 Thomas Preusser 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | */ 20 | 21 | #ifndef IO_EXCEPTION_H 22 | #define IO_EXCEPTION_H 23 | 24 | #include 25 | 26 | class io_exception { 27 | std::string const msg; 28 | 29 | public: 30 | io_exception(std::string const& _msg = "") : msg(_msg) {} 31 | ~io_exception() {} 32 | 33 | public: 34 | operator std::string const&() const { return getMessage(); } 35 | std::string const& getMessage() const { return msg; } 36 | }; 37 | #endif 38 | -------------------------------------------------------------------------------- /xenium-flash/src/omega2-gpio/FastGpioOmega2.cpp: -------------------------------------------------------------------------------- 1 | /* Register based GPIO for Onion Omega2+ 2 | 3 | ** Based on Onion's FastGPIO ** 4 | https://github.com/OnionIoT/fast-gpio 5 | 6 | Copyright Onion 7 | 8 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include "FastGpioOmega2.hpp" 26 | 27 | FastGpioOmega2::FastGpioOmega2(void) 28 | { 29 | // setup the memory address space 30 | _SetupAddress(REG_BLOCK_ADDR, REG_BLOCK_SIZE); 31 | } 32 | 33 | FastGpioOmega2::~FastGpioOmega2(void) 34 | { 35 | // nothing for now 36 | } 37 | 38 | void FastGpioOmega2::setGpioOffset(int gpio){ 39 | int mod; 40 | mod = gpio / 32; 41 | if(mod == 0){ 42 | this->ctrlOffset = REGISTER_CTRL0_OFFSET; 43 | this->dataOffset = REGISTER_DATA0_OFFSET; 44 | this->dataSetOffset = REGISTER_DSET0_OFFSET; 45 | this->dataClrOffset = REGISTER_DCLR0_OFFSET; 46 | } 47 | else if(mod == 1){ 48 | this->ctrlOffset = REGISTER_CTRL1_OFFSET; 49 | this->dataOffset = REGISTER_DATA1_OFFSET; 50 | this->dataSetOffset = REGISTER_DSET1_OFFSET; 51 | this->dataClrOffset = REGISTER_DCLR1_OFFSET; 52 | } else{ 53 | this->ctrlOffset = REGISTER_CTRL2_OFFSET; 54 | this->dataOffset = REGISTER_DATA2_OFFSET; 55 | this->dataSetOffset = REGISTER_DSET2_OFFSET; 56 | this->dataClrOffset = REGISTER_DCLR2_OFFSET; 57 | } 58 | } 59 | // public functions 60 | void FastGpioOmega2::pinMode(int pinNum, int bOutput) 61 | { 62 | unsigned long int regVal; 63 | setGpioOffset(pinNum); 64 | int gpio; 65 | gpio = pinNum % 32; 66 | // read the current input and output settings 67 | regVal = _ReadReg(ctrlOffset); 68 | if (verbosityLevel > 0) printf("Direction setting read: 0x%08lx\n", regVal); 69 | 70 | // set the OE for this pin 71 | _SetBit(regVal, gpio, bOutput); 72 | if (verbosityLevel > 0) printf("Direction setting write: 0x%08lx\n", regVal); 73 | 74 | // write the new register value 75 | _WriteReg(ctrlOffset, regVal); 76 | 77 | } 78 | 79 | int FastGpioOmega2::getPinMode(int pinNum) 80 | { 81 | unsigned long int regVal; 82 | setGpioOffset(pinNum); 83 | int gpio; 84 | gpio = pinNum % 32; 85 | // read the current input and output settings 86 | regVal = _ReadReg(ctrlOffset); 87 | if (verbosityLevel > 0) printf("Direction setting read: 0x%08lx\n", regVal); 88 | 89 | return _GetBit(regVal, gpio); 90 | } 91 | 92 | void FastGpioOmega2::digitalWrite(int pinNum, int value) 93 | { 94 | unsigned long int regAddr; 95 | unsigned long int regVal; 96 | setGpioOffset(pinNum); 97 | int gpio; 98 | gpio = pinNum % 32; 99 | 100 | if (value == 0 ) { 101 | // write to the clear register 102 | regAddr = dataClrOffset; 103 | } 104 | else { 105 | // write to the set register 106 | regAddr = dataSetOffset; 107 | } 108 | 109 | // put the desired pin value into the register 110 | regVal = (0x1 << gpio); 111 | 112 | // write to the register 113 | _WriteReg (regAddr, regVal); 114 | } 115 | 116 | int FastGpioOmega2::digitalRead(int pinNum) 117 | { 118 | unsigned long int regVal; 119 | setGpioOffset(pinNum); 120 | int gpio; 121 | gpio = pinNum % 32; 122 | // read the current value of all pins 123 | regVal = _ReadReg (dataOffset); 124 | 125 | // find the value of the specified pin 126 | return _GetBit(regVal, gpio); 127 | } -------------------------------------------------------------------------------- /xenium-flash/src/omega2-gpio/FastGpioOmega2.hpp: -------------------------------------------------------------------------------- 1 | /* Register based GPIO for Onion Omega2+ 2 | 3 | ** Based on Onion's FastGPIO ** 4 | https://github.com/OnionIoT/fast-gpio 5 | 6 | Copyright Onion 7 | 8 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifndef _FAST_GPIO_OMEGA2_H_ 26 | #define _FAST_GPIO_OMEGA2_H_ 27 | 28 | #include 29 | 30 | #include "Module.hpp" 31 | 32 | //Define Macros in derived class. 33 | #define REG_BLOCK_ADDR 0x10000000 34 | #define REG_BLOCK_SIZE 0x6AC 35 | //DIRECTION CONTROL REGISTERS 36 | 37 | //GPIO_CTRL_0 10000600(Directions for GPIO0-GPIO31) 38 | #define REGISTER_CTRL0_OFFSET 384 39 | //GPIO_CTRL_1 10000604(Directions for GPIO32-GPIO63) 40 | #define REGISTER_CTRL1_OFFSET 385 41 | //GPIO_CTRL_2 10000608(Directions for GPIO64-GPIO95) 42 | #define REGISTER_CTRL2_OFFSET 386 43 | 44 | //DATA REGISTERS: STATES OF GPIOS 45 | 46 | //GPIO_DATA_0 10000620(GPIO0-31) 47 | #define REGISTER_DATA0_OFFSET 392 48 | //GPIO_DATA_1 10000624(GPIO32-63) 49 | #define REGISTER_DATA1_OFFSET 393 50 | //GPIO_DATA_2 10000628(GPIO64-95) 51 | #define REGISTER_DATA2_OFFSET 394 52 | 53 | //DATA SET REGISTERS: SET STATES OF GPIO_DATA_x registers 54 | 55 | //GPIO_DSET_0 10000630(GPIO0-31) 56 | #define REGISTER_DSET0_OFFSET 396 57 | //GPIO_DSET_1 10000634(GPIO31-63) 58 | #define REGISTER_DSET1_OFFSET 397 59 | //GPIO_DSET_2 10000638(GPIO64-95) 60 | #define REGISTER_DSET2_OFFSET 398 61 | 62 | //DATA CLEAR REGISTERS: CLEAR BITS OF GPIO_DATA_x registers 63 | 64 | //GPIO_DCLR_0 10000640(GPIO0-31) 65 | #define REGISTER_DCLR0_OFFSET 400 66 | //GPIO_DCLR_1 10000644(GPIO31-63) 67 | #define REGISTER_DCLR1_OFFSET 401 68 | //GPIO_DCLR_2 10000648(GPIO64-95) 69 | #define REGISTER_DCLR2_OFFSET 402 70 | 71 | #define OMEGA_GPIO_OUT 1 72 | #define OMEGA_GPIO_IN 0 73 | 74 | #define OMEGA_HIGH 1 75 | #define OMEGA_LOW 0 76 | 77 | #define OMEGA_GPIO_0 0 78 | #define OMEGA_GPIO_1 1 79 | #define OMEGA_GPIO_2 2 80 | #define OMEGA_GPIO_3 3 81 | #define OMEGA_GPIO_6 6 82 | #define OMEGA_GPIO_11 11 83 | #define OMEGA_GPIO_15 15 84 | #define OMEGA_GPIO_16 16 85 | #define OMEGA_GPIO_17 17 86 | #define OMEGA_GPIO_18 18 87 | #define OMEGA_GPIO_19 19 88 | 89 | class FastGpioOmega2 : public Module 90 | { 91 | public: 92 | FastGpioOmega2(void); 93 | ~FastGpioOmega2(void); 94 | 95 | void pinMode(int pinNum, int bOutput); 96 | int getPinMode(int pinNum); 97 | 98 | void digitalWrite (int pinNum, int value); 99 | int digitalRead(int pinNum); 100 | 101 | private: 102 | // private functions 103 | int pinNumber; 104 | int ctrlOffset; 105 | int dataOffset; 106 | int dataSetOffset; 107 | int dataClrOffset; 108 | 109 | //Populates the offset private members above depending on selected GPIO 110 | void setGpioOffset(int gpio); 111 | }; 112 | 113 | 114 | #endif // _FAST_GPIO_OMEGA2_H_ -------------------------------------------------------------------------------- /xenium-flash/src/omega2-gpio/Module.cpp: -------------------------------------------------------------------------------- 1 | /* Register based GPIO for Onion Omega2+ 2 | 3 | ** Based on Onion's FastGPIO ** 4 | https://github.com/OnionIoT/fast-gpio 5 | 6 | Copyright Onion 7 | 8 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include "Module.hpp" 26 | 27 | Module::Module(void) 28 | { 29 | // not verbose by default 30 | verbosityLevel = 0; 31 | 32 | // not in debug mode by default 33 | debugLevel = 0; 34 | } 35 | 36 | Module::~Module(void) 37 | { 38 | // nothing for now 39 | } 40 | 41 | 42 | // Debug Functions 43 | void Module::SetVerbosity (int input) 44 | { 45 | verbosityLevel = input; 46 | } 47 | 48 | void Module::SetVerbosity (bool input) 49 | { 50 | verbosityLevel = (input ? 1 : 0); 51 | } 52 | 53 | void Module::SetDebugMode (int input) 54 | { 55 | debugLevel = input; 56 | } 57 | 58 | void Module::SetDebugMode (bool input) 59 | { 60 | debugLevel = (input ? 1 : 0); 61 | } 62 | 63 | 64 | // Register access 65 | int Module::_SetupAddress(unsigned long int blockBaseAddr, unsigned long int blockSize) 66 | { 67 | int m_mfd; 68 | if (debugLevel == 0) 69 | { 70 | if ((m_mfd = open("/dev/mem", O_RDWR)) < 0) 71 | { 72 | return EXIT_FAILURE; // maybe return -1 73 | } 74 | regAddress = (unsigned long int*)mmap ( NULL, 75 | 1024, 76 | PROT_READ|PROT_WRITE, 77 | MAP_FILE|MAP_SHARED, 78 | m_mfd, 79 | blockBaseAddr 80 | ); 81 | close(m_mfd); 82 | if (regAddress == MAP_FAILED) 83 | { 84 | return EXIT_FAILURE; // maybe return -2 85 | } 86 | } 87 | 88 | return EXIT_SUCCESS; // regAddress is now populated 89 | } 90 | 91 | void Module::_WriteReg(unsigned long int registerOffset, unsigned long int value) 92 | { 93 | if (verbosityLevel > 0) printf("Writing register 0x%08lx with data 0x%08lx \n", (long unsigned int)(regAddress + registerOffset), value); 94 | 95 | *(regAddress + registerOffset) = value; 96 | } 97 | 98 | unsigned long int Module::_ReadReg(unsigned long int registerOffset) 99 | { 100 | unsigned long int value = 0x0; 101 | // read the value 102 | value = *(regAddress + registerOffset); 103 | 104 | if (verbosityLevel > 0) printf("Read register 0x%08lx, data: 0x%08lx \n", (long unsigned int)(regAddress + registerOffset), value); 105 | 106 | return(value); 107 | } 108 | 109 | // change the value of a single bit 110 | void Module::_SetBit(unsigned long int ®Val, int bitNum, int value) 111 | { 112 | if (value == 1) { 113 | regVal |= (1 << bitNum); 114 | } 115 | else { 116 | regVal &= ~(1 << bitNum); 117 | } 118 | 119 | // try this out 120 | // regVal ^= (-value ^ regVal) & (1 << bitNum); 121 | } 122 | 123 | // find the value of a single bit 124 | int Module::_GetBit(unsigned long int regVal, int bitNum) 125 | { 126 | int value; 127 | 128 | // isolate the specific bit 129 | value = ((regVal >> bitNum) & 0x1); 130 | 131 | return (value); 132 | } -------------------------------------------------------------------------------- /xenium-flash/src/omega2-gpio/Module.hpp: -------------------------------------------------------------------------------- 1 | /* Register based GPIO for Onion Omega2+ 2 | 3 | ** Based on Onion's FastGPIO ** 4 | https://github.com/OnionIoT/fast-gpio 5 | 6 | Copyright Onion 7 | 8 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifndef _MODULE_H_ 26 | #define _MODULE_H_ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | class Module { 37 | public: 38 | Module(void); 39 | ~Module(void); 40 | 41 | void SetVerbosity (int input); 42 | void SetVerbosity (bool input); 43 | 44 | void SetDebugMode (int input); 45 | void SetDebugMode (bool input); 46 | 47 | 48 | protected: 49 | // protected functions 50 | int _SetupAddress (unsigned long int blockBaseAddr, unsigned long int blockSize); 51 | void _WriteReg (unsigned long int registerOffset, unsigned long int value); 52 | unsigned long int _ReadReg (unsigned long int registerOffset); 53 | 54 | void _SetBit (unsigned long int ®Val, int bitNum, int value); 55 | int _GetBit (unsigned long int regVal, int bitNum); 56 | 57 | // protected members 58 | int verbosityLevel; 59 | int debugLevel; 60 | 61 | unsigned long int *regAddress; 62 | }; 63 | 64 | #endif // _MODULE_H_ -------------------------------------------------------------------------------- /xenium-flash/src/xenium-flash.cpp: -------------------------------------------------------------------------------- 1 | /* Programming a FLASH on OpenXenium 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "Flash.hpp" 29 | 30 | #define FLASH_SIZE 0x200000 31 | #define KB 1024 32 | 33 | int main(int argc, char** argv) 34 | { 35 | XK::Flash flash; 36 | 37 | std::cout << "---------------------------" << std::endl; 38 | std::cout << "Xenium Flashing Tool - v0.1" << std::endl; 39 | std::cout << "---------------------------" << std::endl; 40 | 41 | if (argc < 2) 42 | { 43 | std::cout << "SYNTAX ERROR: Please provide flash BIN file path." << std::endl; 44 | std::cout << "\tExample: xenium_flash /path/to/file.bin" << std::endl; 45 | return -1; 46 | } 47 | 48 | // if -y supplied after filename, then dont ask to erase/flash 49 | bool force = false; 50 | if(argc > 2) 51 | { 52 | std::string cmd2 = argv[2]; 53 | force = cmd2.compare("-y") == 0; 54 | } 55 | 56 | // need pi hardware revision for timing control.. 57 | std::string pi_version = flash.GetHardwareString(); 58 | std::cout << "Checking Hardware: " << pi_version << std::endl; 59 | 60 | // ******************** LOADING FLASH FILE *************** 61 | std::string infile = argv[1]; 62 | std::cout << "Loading Xenium Flash BIN: " << infile << std::endl; 63 | 64 | std::ifstream fin(infile); 65 | if (fin.fail()) 66 | { 67 | std::cout << "ERROR LOADING FILE: " << infile << std::endl; 68 | return -1; 69 | } 70 | 71 | // check file size 72 | fin.seekg(0, std::ios::end); 73 | uint32_t flash_size = fin.tellg(); 74 | if (flash_size != FLASH_SIZE) 75 | { 76 | std::cout << "ERROR: Xenium Flash BIN file must be " << FLASH_SIZE << " Bytes" << std::endl; 77 | fin.close(); 78 | return -1; 79 | } 80 | 81 | //alloc memory and read file 82 | char* flash_buffer = new char[flash_size]; 83 | // seek back to start 84 | fin.seekg(0, std::ios::beg); 85 | // read entire flash in ram 86 | fin.read(flash_buffer, flash_size); 87 | // close file 88 | fin.close(); 89 | 90 | 91 | // ******************** CHECK XENIUM HARDWARE *************** 92 | std::cout << "Detecting Xenium Flash: " << std::flush; 93 | flash.ChipReset(); 94 | std::this_thread::sleep_for (std::chrono::milliseconds(500)); 95 | uint8_t manufacturer = flash.GetManufacturerID(); 96 | uint8_t deviceid = flash.GetDeviceID(); 97 | 98 | // OpenXenium CPLD brings back 0x55 and 0x5F.. very convenient.. 99 | if (manufacturer == 0x55 && deviceid == 0x5F) 100 | { 101 | std::cout << "ERROR\n\n** XENIUM NOT IN BITBUS MODE - Please program " 102 | << "the \"xeniumflash.jed\" file first! **" << std::endl; 103 | return -1; 104 | } 105 | else if (manufacturer == 0xFF && deviceid == 0xFF) 106 | { 107 | std::cout << "ERROR\n\n** XENIUM CPLD POSSIBLY BLANK - Please program " 108 | << "the \"xeniumflash.jed\" file first! **" << std::endl; 109 | return -1; 110 | } 111 | else if (manufacturer != 0x01 || deviceid != 0xC4) 112 | { 113 | std::cout << "ERROR\n\n** XENIUM FLASH DEVICE NOT FOUND - Manufacturer:" 114 | << (int) manufacturer << ", Device:" << (int) deviceid << " **\n" << std::endl; 115 | return -1; 116 | } 117 | else 118 | { 119 | std::cout << "OK [Spansion S29AL016J]" << std::endl; 120 | } 121 | 122 | // ********************* FLASH CHIP ERASE ***************** 123 | flash.ChipReset(); 124 | if (!force) 125 | { 126 | std::string erase_ok; 127 | std::cout << "This will ERASE your Xenium Flash, ARE YOU SURE? (Yes/No): " << std::flush; 128 | std::getline (std::cin, erase_ok); 129 | if ((erase_ok.find("Y") != 0) && (erase_ok.find("y") != 0)) 130 | { 131 | std::cout << "\n** XENIUM FLASH CANCELLED!! **\n" << std::endl; 132 | return -1; 133 | } 134 | } 135 | 136 | flash.ChipErase(); 137 | // wait for erase to complete.. 138 | auto now = std::chrono::steady_clock::now(); 139 | uint32_t erase_waits = 0; 140 | const char wait_anim[8] = {'-','\\','|','/'}; 141 | uint8_t anim_pos = 0; 142 | while (true) 143 | { 144 | if (erase_waits > 120) 145 | { 146 | std::cout << "\nERROR\n\n** XENIUM FLASH ERASE FAILED!! **\n" << std::endl; 147 | flash.ChipReset(); 148 | return -1; 149 | } 150 | 151 | //check toggle bits for erase complete after Xsec 152 | if ((erase_waits > 2) && (flash.Read(0x00) == flash.Read(0x00))) 153 | { 154 | break; 155 | } 156 | 157 | std::cout << "\rErasing Xenium Flash: " << wait_anim[anim_pos] << " (Waiting) " << std::flush; 158 | std::this_thread::sleep_for (std::chrono::milliseconds(500)); 159 | anim_pos = (anim_pos==3)?0:anim_pos+1; 160 | erase_waits++; 161 | } 162 | auto elapsed = std::chrono::steady_clock::now() - now; 163 | uint32_t sec = std::chrono::duration_cast(elapsed).count(); 164 | std::cout << "\rErasing Xenium Flash: DONE (" << sec << " Seconds)" << std::endl; 165 | 166 | 167 | // ********************* FLASH CHIP PROGRAM ***************** 168 | now = std::chrono::steady_clock::now(); 169 | float progress = 0.0; 170 | for (uint32_t i = 0; i < flash_size; i++) 171 | { 172 | //write byte to flash 173 | flash.Write(i, flash_buffer[i]); 174 | 175 | float current_progress = (float) i / flash_size * 100.0f; 176 | if (current_progress > progress + 1) 177 | { 178 | progress = current_progress; 179 | std::cout << "\rWriting Flash: " << std::fixed << std::setprecision(0) 180 | << progress << "% " << std::flush; 181 | } 182 | } 183 | elapsed = std::chrono::steady_clock::now() - now; 184 | sec = std::chrono::duration_cast(elapsed).count(); 185 | std::cout << "\rWriting Flash: DONE (" << sec << " Seconds)" << std::endl; 186 | 187 | 188 | // ********************* FLASH CHIP VERIFY ***************** 189 | now = std::chrono::steady_clock::now(); 190 | progress = 0.0; 191 | for (uint32_t i = 0; i < flash_size; i++) 192 | { 193 | //read byte from flash 194 | uint inbyte = flash.Read(i); 195 | if (flash_buffer[i] == (char)inbyte) 196 | { 197 | flash_buffer[i] = inbyte; 198 | } 199 | else 200 | { 201 | std::cout << std::endl << "ERROR\n\n** XENIUM FLASH VERIFY FAILED!! **\n" << std::endl; 202 | flash.ChipReset(); 203 | return -1; 204 | } 205 | 206 | float current_progress = (float) i / flash_size * 100.0f; 207 | if (current_progress > progress + 1) 208 | { 209 | progress = current_progress; 210 | std::cout << "\rVerifying Flash: " << std::fixed << std::setprecision(0) 211 | << progress << "% " << std::flush; 212 | } 213 | } 214 | elapsed = std::chrono::steady_clock::now() - now; 215 | sec = std::chrono::duration_cast(elapsed).count(); 216 | std::cout << "\rVerifying Flash: DONE (" << sec << " Seconds)" << std::endl; 217 | 218 | // you can uncomment this code if you wish to dump to file from xenium 219 | // //write to file 220 | // std::string outfile = "flash.bin"; 221 | // std::ofstream fout(outfile); 222 | // fout.write(flash_buffer, flash_size); 223 | // fout.close(); 224 | // std::cout << "Writing Xenium flash dumped to file: " << outfile << std::endl; 225 | 226 | // clear out flash memory. 227 | delete[] flash_buffer; 228 | 229 | //reset to turn LED blue.. 230 | flash.ChipReset(); 231 | 232 | std::cout << std::endl << "Xenium Flash SUCCESS!!" << std::endl << std::endl; 233 | 234 | return 0; 235 | } 236 | -------------------------------------------------------------------------------- /xenium-flash/src/xenium-jtag.cpp: -------------------------------------------------------------------------------- 1 | /* Programming a CPLD on OpenXenium 2 | 3 | Copyright (C) 2019-2020 Koos du Preez (kdupreez@hotmail.com) 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include "IOXenium.h" 24 | #include "Jtag.h" 25 | #include "JedecFile.h" 26 | #include "ProgAlgXC95X.h" 27 | 28 | 29 | // IDCODE IR_len ID_Cmd Text 30 | // 09604093 8 0xfe XC9572XL 31 | 32 | // Constants for Xilinx Device ID and string.. 33 | const uint32_t XC9572XL_ID = 0x09604093; 34 | const int32_t XC9572XL_IR_len = 8; 35 | const char XC9572XL_STR[] = "XC9572XL"; 36 | 37 | int main(int argc, char** argv) 38 | { 39 | std::cout << "-----------------------" << std::endl; 40 | std::cout << "Xenium JTAG Tool - v0.1" << std::endl; 41 | std::cout << "-----------------------" << std::endl; 42 | 43 | if (argc < 2) 44 | { 45 | std::cout << "SYNTAX ERROR: Please provide JED file path." << std::endl; 46 | std::cout << "\tExample: xenium_jtag /path/to/file.jed" << std::endl; 47 | return -1; 48 | } 49 | 50 | // ******************** LOADING JED FILE *************** 51 | std::string jed_file = argv[1]; 52 | std::cout << "Loading JEDEC File: " << std::endl; 53 | JedecFile jed; 54 | FILE *jed_fp = fopen(jed_file.c_str(),"rb"); 55 | 56 | //failed to load JED 57 | if (!jed_fp) 58 | { 59 | std::cout << "ERROR LOADING FILE: " << jed_file << std::endl; 60 | return -1; 61 | } 62 | 63 | //process JED file 64 | jed.readFile(jed_fp); 65 | std::string jed_device = jed.getDevice(); 66 | std:: cout << "\tLoaded: " << jed_file << std::endl; 67 | std:: cout << "\tFound JED file device: " << jed_device << std::endl; 68 | 69 | // ******************** SCANNING JTAG CHAIN *************** 70 | 71 | // create PI JTAG Obj 72 | std::unique_ptr io = std::make_unique(); 73 | Jtag jtag(std::move(io)); 74 | jtag.setVerbose(false); 75 | 76 | // Scanning JTAG Chain 77 | std::cout << "Scanning JTAG Chain: " << std::endl; 78 | 79 | int device_cnt = jtag.getChain(); 80 | std::cout << "\tDevices found: " << device_cnt << std::endl; 81 | 82 | //zero devices found? 83 | if (device_cnt <= 0) 84 | { 85 | std::cout << "** ERROR- NO DEVICES ON JTAG CHAIN!" << std::endl; 86 | return -1; 87 | } 88 | 89 | //Check Device ID against xc9572xl 90 | uint32_t device_id = jtag.getDeviceID(0); 91 | std::cout << "\tChecking for " << XC9572XL_STR << ": "; 92 | if ((device_id & 0x0fffffff) == XC9572XL_ID) 93 | { 94 | std::cout << "[ OK ]" << std::endl; 95 | } 96 | else 97 | { 98 | std::cout << "[ ** NOT FOUND **]" << std::endl; 99 | return -1; 100 | } 101 | 102 | //Select JTAG device 0 and set instruction length 103 | jtag.selectDevice(0); 104 | jtag.setDeviceIRLength(0, XC9572XL_IR_len); 105 | 106 | // Validate JTAG device against JED device 107 | std:: cout << "\tJTAG/JED Device Match: " << jed_device << " "; 108 | if (jed_device.find(XC9572XL_STR) != std::string::npos) 109 | { 110 | std::cout << "[ OK ]" << std::endl; 111 | } 112 | else 113 | { 114 | std::cout << "[ ** DEVICE MISMATCH ** ]" << std::endl; 115 | return -1; 116 | } 117 | 118 | // setup programmer 119 | std::cout << "JTAG Programming Device: " << std::endl; 120 | ProgAlgXC95X jtag_device(jtag, device_id); 121 | 122 | //Erase 123 | std:: cout << "\tErasing: " << std::flush; 124 | if (jtag_device.erase()) 125 | { 126 | std:: cout << "[ OK ]" << std::endl; 127 | } 128 | else 129 | { 130 | std:: cout << "[ ** ERASE FAILED ** ]" << std::endl; 131 | return -1; 132 | } 133 | 134 | //programming 135 | std:: cout << "\tProgramming: [ Please wait.. ]" << std::flush; 136 | jtag_device.array_program(jed); 137 | std:: cout << "\r\tProgramming: [ DONE ] " << std::endl; 138 | 139 | //verifying 140 | std:: cout << "\tVerifying: " << std::flush; 141 | if (jtag_device.array_verify(jed) == 0) 142 | { 143 | std:: cout << "[ OK ]" << std::endl; 144 | } 145 | else 146 | { 147 | std:: cout << "[ ** VERIFY FAILED ** ] " << std::endl; 148 | return -1; 149 | } 150 | 151 | fclose(jed_fp); 152 | 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /xenium-programmer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo -e '▒██ ██▒▓█████ ███▄ █ ██▓ █ ██ ███▄ ▄███▓' 3 | echo -e '▒▒ █ █ ▒░▓█ ▀ ██ ▀█ █ ▓██▒ ██ ▓██▒▓██▒▀█▀ ██▒' 4 | echo -e '░░ █ ░▒███ ▓██ ▀█ ██▒▒██▒▓██ ▒██░▓██ ▓██░' 5 | echo -e ' ░ █ █ ▒ ▒▓█ ▄ ▓██▒ ▐▌██▒░██░▓▓█ ░██░▒██ ▒██ ' 6 | echo -e '▒██▒ ▒██▒░▒████▒▒██░ ▓██░░██░▒▒█████▓ ▒██▒ ░██▒' 7 | echo -e '▒▒ ░ ░▓ ░░░ ▒░ ░░ ▒░ ▒ ▒ ░▓ ░▒▓▒ ▒ ▒ ░ ▒░ ░ ░' 8 | echo -e '░░ ░▒ ░ ░ ░ ░░ ░░ ░ ▒░ ▒ ░░░▒Programmer░ ░' 9 | echo -e ' ░ ░ ░ ░ ░ ░ ▒kooscode@github ░ ' 10 | echo -e ' ░ ░ ░ ░ ░ ░ ░ ░ ' 11 | 12 | # Paths to default Firmware and XeniumOS files 13 | XENIUM_OS=xenium-bin/xenium_blue.bin 14 | XENIUM_JED=xenium-bin/openxenium.jed 15 | FLASH_JED=xenium-bin/xeniumflash.jed 16 | 17 | if [ $# -eq 1 ] ; then 18 | XENIUM_OS=$1 19 | echo -e 'Using XeniumOS: ' $1 20 | fi 21 | 22 | # Program the Xilinx CPLD with BitBus to Flash firmware. 23 | echo -e '--------------------------------------' 24 | echo -e 'PROGRAMMING XILINX CPLD: BITBUS BRIDGE' 25 | echo -e '--------------------------------------' 26 | xenium-flash/bin/xenium-jtag $FLASH_JED 27 | if [ $? -ne 0 ] 28 | then 29 | echo "ERROR Programming the Xilinx CPLD: " $FLASH_JED 30 | echo "Please double check your JTAG connection and wires!" 31 | exit $? 32 | fi 33 | 34 | # Send XeniumOS Image to Flash Memory via bitbus bridge 35 | echo -e '-----------------------------' 36 | echo -e 'PROGRAMMING FLASH : XENIUM OS' 37 | echo -e '-----------------------------' 38 | xenium-flash/bin/xenium-flash $XENIUM_OS $2 39 | if [ $? -ne 0 ] 40 | then 41 | echo "ERROR Loading XeniumOS into OpenXenium Flash memory!" 42 | echo "Please double check your LPC Header connection and wires!" 43 | exit $? 44 | fi 45 | 46 | # Program the Xilinx CPLD with OpenXenium Firmware 47 | echo -e '---------------------------------------------' 48 | echo -e 'PROGRAMMING XILINX CPLD: OPEN XENIUM FIRMWARE' 49 | echo -e '---------------------------------------------' 50 | xenium-flash/bin/xenium-jtag $XENIUM_JED 51 | if [ $? -ne 0 ] 52 | then 53 | echo "ERROR Programming the Xilinx CPLD: " $XENIUM_JED 54 | echo "Please double check your JTAG connection and wires!" 55 | exit $? 56 | fi 57 | 58 | -------------------------------------------------------------------------------- /xenium-programmer-pi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | 4 | # Python wrapper for Xenium programming using Pi-ZeroW PC-Board 5 | # 6 | # Copyright (C) 2019 Koos du Preez (kdupreez@hotmail.com) 7 | # 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | 22 | import os 23 | import subprocess 24 | import RPi.GPIO as GPIO 25 | import time 26 | 27 | print("▒██ ██▒▓█████ ███▄ █ ██▓ █ ██ ███▄ ▄███▓") 28 | print("▒▒ █ █ ▒░▓█ ▀ ██ ▀█ █ ▓██▒ ██ ▓██▒▓██▒▀█▀ ██▒") 29 | print("░░ █ ░▒███ ▓██ ▀█ ██▒▒██▒▓██ ▒██░▓██ ▓██░") 30 | print(" ░ █ █ ▒ ▒▓█ ▄ ▓██▒ ▐▌██▒░██░▓▓█ ░██░▒██ ▒██ ") 31 | print("▒██▒ ▒██▒░▒████▒▒██░ ▓██░░██░▒▒█████▓ ▒██▒ ░██▒") 32 | print("▒▒ ░ ░▓ ░░░ ▒░ ░░ ▒░ ▒ ▒ ░▓ ░▒▓▒ ▒ ▒ ░ ▒░ ░ ░") 33 | print("░░ ░▒ ░ ░ ░ ░░ ░░ ░ ▒░ ▒ ░░░▒Programmer░ ░") 34 | print(" ░ ░ ░ ░ ░ ░ ▒kooscode@github ░ ") 35 | print(" ░ ░ ░ ░ ░ ░ ░ ░ ", flush=True) 36 | 37 | 38 | # git root folder. 39 | programmer_root = os.getcwd() 40 | 41 | # Commands 42 | cmd_jtag = os.path.join(programmer_root, "xenium-flash/bin/xenium-jtag") 43 | cmd_jflash = os.path.join(programmer_root, "xenium-flash/bin/xenium-flash") 44 | 45 | # Data Files 46 | flash_jed = os.path.join(programmer_root, "xenium-bin/xeniumflash.jed") 47 | xenium_os = os.path.join(programmer_root, "xenium-bin/xenium_blue.bin") 48 | xenium_jed= os.path.join(programmer_root, "xenium-bin/openxenium.jed") 49 | 50 | # LED Pins 51 | led1 = 19 52 | led2 = 6 53 | led3 = 7 54 | 55 | def set_ok(): 56 | GPIO.output(led1, GPIO.HIGH) 57 | GPIO.output(led2, GPIO.LOW) 58 | GPIO.output(led3, GPIO.LOW) 59 | 60 | def set_busy(): 61 | GPIO.output(led1, GPIO.LOW) 62 | GPIO.output(led2, GPIO.HIGH) 63 | GPIO.output(led3, GPIO.LOW) 64 | 65 | def set_error(): 66 | GPIO.output(led1, GPIO.LOW) 67 | GPIO.output(led2, GPIO.LOW) 68 | GPIO.output(led3, GPIO.HIGH) 69 | 70 | def set_init(): 71 | GPIO.output(led1, GPIO.HIGH) 72 | time.sleep(0.1) 73 | GPIO.output(led2, GPIO.HIGH) 74 | time.sleep(0.1) 75 | GPIO.output(led3, GPIO.HIGH) 76 | time.sleep(0.1) 77 | 78 | #using Broadcom pin numbering. 79 | GPIO.setmode(GPIO.BCM) 80 | GPIO.setwarnings(False) 81 | 82 | #setup pin as output 83 | GPIO.setup(led1, GPIO.OUT) 84 | GPIO.setup(led2, GPIO.OUT) 85 | GPIO.setup(led3, GPIO.OUT) 86 | 87 | set_init() 88 | 89 | # Program CPLD with BitBus Flash Writer code. 90 | set_busy() 91 | print("-------------------------------------") 92 | print("PROGRAMMING XILINX CPLD: BITBUS BRIDGE") 93 | print("--------------------------------------", flush=True) 94 | sub_proc = subprocess.run([cmd_jtag, flash_jed]) 95 | if sub_proc.returncode == 0: 96 | set_ok() 97 | 98 | # Write OpenXenium OS to Flash Chip 99 | set_busy() 100 | print("-----------------------------") 101 | print("PROGRAMMING FLASH : XENIUM OS") 102 | print("-----------------------------", flush=True) 103 | sub_proc = subprocess.run([cmd_jflash, xenium_os, "-y"]) 104 | if sub_proc.returncode == 0: 105 | set_ok() 106 | 107 | set_busy() 108 | # Program CPLD with OpenXenium Firmware. 109 | print("---------------------------------------------") 110 | print("PROGRAMMING XILINX CPLD: OPEN XENIUM FIRMWARE") 111 | print("---------------------------------------------", flush=True) 112 | sub_proc = subprocess.run([cmd_jtag, xenium_jed]) 113 | if sub_proc.returncode == 0: 114 | set_ok() 115 | 116 | else: 117 | print("ERROR Programming the Xilinx CPLD!") 118 | print("Please double check your JTAG connection and wires!", flush=True) 119 | set_error() 120 | 121 | else: 122 | set_error() 123 | print("ERROR Loading XeniumOS into OpenXenium Flash memory!") 124 | print("Please double check your LPC Header connection and wires!", flush=True) 125 | else: 126 | set_error() 127 | print("ERROR Programming the Xilinx CPLD!") 128 | print("Please double check your JTAG connection and wires!", flush=True) 129 | 130 | # # cleanup GPIO 131 | # GPIO.cleanup() 132 | --------------------------------------------------------------------------------