├── .gitignore ├── LICENSE ├── Makefile ├── README ├── agents ├── cc13xx-romapi.h ├── cc13xx.c ├── efr32bg2x.c ├── lpc13xx.c ├── lpc13xx_lpc15xx.c ├── lpc15xx.c ├── lpc43xx-spifi.c ├── lpclink2.c ├── nrf528xx.c ├── pico.c ├── stm32f0xx.c ├── stm32f4xx.c └── stm32fxxx.c ├── build ├── agent.ld └── build.mk ├── docs ├── 99-mdebug.rules ├── building-cross-compiler.txt ├── memory-barriers.txt ├── notes.txt ├── todo.txt └── usb-protocols.txt ├── firmware ├── README ├── lpclink2-boot.bin ├── lpclink2-dfu.bin └── lpclink2-mdebug.bin ├── include ├── agent │ └── flash.h ├── fw │ ├── io.h │ └── types.h └── protocol │ └── rswdp.h └── tools ├── arm-m-debug.c ├── arm-v7m.h ├── base64.c ├── bless-lpc.c ├── builtins.c ├── dap-registers.h ├── debugger-commands.c ├── debugger-core.c ├── debugger.c ├── debugger.h ├── gdb-bridge.c ├── jtag-dap.c ├── jtag.c ├── jtag.h ├── linenoise.c ├── linenoise.h ├── lkdebug.c ├── lkdebug.h ├── lpcboot.c ├── mkbuiltins.c ├── picoboot.c ├── rswdp.c ├── rswdp.h ├── sha1.c ├── sha1.h ├── socket.c ├── stm32boot.c ├── swo.c ├── ti-icepick.h ├── uconsole.c ├── usb.c ├── usb.h ├── usbmon.c ├── usbmon.h ├── usbtest.c ├── websocket.c └── websocket.h /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | out 4 | bin 5 | local.mk 6 | tags 7 | TAGS 8 | cscope.out 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | what_to_build:: all 3 | 4 | -include local.mk 5 | 6 | include build/build.mk 7 | 8 | # bootloader download tool 9 | SRCS := tools/lpcboot.c \ 10 | tools/usb.c 11 | $(call program,lpcboot,$(SRCS)) 12 | 13 | # debugger 14 | SRCS := tools/debugger.c \ 15 | tools/debugger-core.c \ 16 | tools/debugger-commands.c \ 17 | tools/gdb-bridge.c \ 18 | tools/jtag.c \ 19 | tools/jtag-dap.c \ 20 | tools/arm-m-debug.c \ 21 | tools/linenoise.c \ 22 | tools/lkdebug.c \ 23 | tools/rswdp.c \ 24 | tools/socket.c \ 25 | tools/swo.c \ 26 | tools/websocket.c \ 27 | tools/base64.c \ 28 | tools/sha1.c \ 29 | tools/usb.c 30 | 31 | ifneq ($(TOOLCHAIN),) 32 | SRCS += out/builtins.c 33 | else 34 | SRCS += tools/builtins.c 35 | endif 36 | $(call program,debugger,$(SRCS)) 37 | 38 | 39 | ifneq ($(TOOLCHAIN),) 40 | # if there's a cross-compiler, build agents from source 41 | 42 | $(call agent, lpclink2, 0x10080400, M3) 43 | $(call agent, stm32f4xx, 0x20000400, M3) 44 | $(call agent, stm32f0xx, 0x20000400, M0) 45 | $(call agent, lpc13xx, 0x10000400, M3) 46 | $(call agent, lpc15xx, 0x02000400, M3) 47 | $(call agent, cc13xx, 0x20000400, M3) 48 | $(call agent, nrf528xx, 0x20000400, M3) 49 | $(call agent, efr32bg2x, 0x20000400, M3) 50 | $(call agent, pico, 0x20000400, M0) 51 | 52 | $(call program,picoboot,tools/picoboot.c) 53 | 54 | # tool to pack the agents into a source file 55 | SRCS := tools/mkbuiltins.c 56 | $(call program,mkbuiltins,$(SRCS)) 57 | 58 | AGENT_BINS := $(patsubst %,out/agent-%.bin,$(AGENTS)) 59 | 60 | out/builtins.c: $(AGENT_BINS) bin/mkbuiltins 61 | @mkdir -p $(dir $@) 62 | @echo generate $@ 63 | $(QUIET)./bin/mkbuiltins $(AGENT_BINS) > $@ 64 | endif 65 | 66 | -include $(DEPS) 67 | 68 | all: $(ALL) 69 | 70 | clean:: 71 | rm -rf out bin 72 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | =========================================================================== 3 | mdebug - A debugger for Cortex-M MCUs 4 | =========================================================================== 5 | 6 | This is a debugger for Cortex-M MCUs using SWD (serial wire debug) and 7 | (optionally) SWO. It provides basic standalone functionality including 8 | memory inspection and modification, processor halt, register inspection, 9 | single stepping, breakpoints, etc. It also acts as a GDB agent, allowing 10 | GDB to control the target device. 11 | 12 | Previously it used a custom debug probe board (m3debug). In its current 13 | iteration firmware is provided for the readily available (and much more 14 | powerful) LPC Link 2 probe board, which is available from Digikey for 15 | under $20: 16 | http://www.digikey.com/product-detail/en/OM13054,598/568-10930-ND/ 17 | http://www.embeddedartists.com/products/lpcxpresso/lpclink2.php 18 | 19 | It provides flashing functionality via "flash agents" which are little 20 | programs downloaded to the target board RAM and then controlled by the 21 | debugger. Currently agents are included for the lpc13xx, lpc15xx, 22 | stm32f4xx series MCUs and the lpclink2 board itself (lpc43xx + spifi). 23 | 24 | Recently it's seem the most testing against stm32f4xx and lpc43xx MCUs. 25 | It has previously been used successfully with lpc13xx, lpc15xx, and 26 | stm32f2xx MCUs. 27 | 28 | Firmware for the LPC Link 2 and installation instructions are in the 29 | firmware directory. Firmware source code is part of the lk embedded 30 | kernel project (look in app/mdebug): 31 | https://github.com/travisg/lk 32 | https://github.com/travisg/lk/tree/master/app/mdebug 33 | 34 | Everything is either Apache 2 or BSD licensed, to allow for easy, 35 | no-strings-attached, inclusion in your own projects. Share and enjoy! 36 | 37 | Features 38 | -------- 39 | 40 | * simple standalone interactive debugger 41 | * GDB stub/remote integration (default port localhost:5555) 42 | * simple and efficient remoted SWD transaction protocol 43 | * pretty fast: 450KB/s download to target w/ 8MHz SWD clock 44 | * simple flash agents: easy to add support for a new MCU or memory device 45 | * integration with LK for multi-threaded GDB debugging 46 | * supports console-over-SWO, and console-commands-over-SWD (with LK) 47 | * host software runs on Linux or OSX (Windows support not far off) 48 | * only external dependency is libusb 1.0 49 | 50 | 51 | Included Third Party Software 52 | ----------------------------- 53 | 54 | linenoise.[ch] 55 | excellent tiny commandline editor (BSD license) 56 | https://github.com/antirez/linenoise 57 | 58 | 59 | Useful Documents 60 | ---------------- 61 | 62 | ARM DDI0337E Cortex M3 r1p1 Technical Reference Manual 63 | Has useful details on SW-DP and debug peripherals that was removed 64 | in later versions of the TRM as "redundant" with other documents. 65 | 66 | 67 | Historical Notes 68 | ---------------- 69 | 70 | This work is an extension of the older m3dev project, but only brings 71 | the debugger tools foward. The embedded firmware stuff lives on in 72 | m3dev and the next-gen firmware is part of lk. 73 | 74 | https://github.com/swetland/m3dev 75 | -------------------------------------------------------------------------------- /agents/cc13xx-romapi.h: -------------------------------------------------------------------------------- 1 | 2 | #define ROM_API_TABLE ((u32*) 0x10000180) 3 | #define ROM_API_FLASH_TABLE ((u32*) (ROM_API_TABLE[10])) 4 | 5 | #define ROM_FlashPowerModeGet \ 6 | ((u32 (*)(void)) \ 7 | ROM_API_FLASH_TABLE[1]) 8 | 9 | #define ROM_FlashProtectionSet \ 10 | ((void (*)(u32 ui32SectorAddress, u32 ui32ProtectMode)) \ 11 | ROM_API_FLASH_TABLE[2]) 12 | 13 | #define ROM_FlashProtectionGet \ 14 | ((u32 (*)(u32 ui32SectorAddress)) \ 15 | ROM_API_FLASH_TABLE[3]) 16 | 17 | #define ROM_FlashProtectionSave \ 18 | ((u32 (*)(u32 ui32SectorAddress)) \ 19 | ROM_API_FLASH_TABLE[4]) 20 | 21 | #define ROM_FlashSectorErase \ 22 | ((u32 (*)(u32 ui32SectorAddress)) \ 23 | ROM_API_FLASH_TABLE[5]) 24 | 25 | #define ROM_FlashProgram \ 26 | ((u32 (*)(const void *pui8DataBuffer, u32 ui32Address, u32 ui32Count)) \ 27 | ROM_API_FLASH_TABLE[6]) 28 | 29 | #define ROM_FlashEfuseReadRow \ 30 | ((u32 (*)(u32* pui32EfuseData, u32 ui32RowAddress)) \ 31 | ROM_API_FLASH_TABLE[8]) 32 | 33 | #define ROM_FlashDisableSectorsForWrite \ 34 | ((void (*)(void)) \ 35 | ROM_API_FLASH_TABLE[9]) 36 | -------------------------------------------------------------------------------- /agents/cc13xx.c: -------------------------------------------------------------------------------- 1 | // agent-lpc15xx/main.c 2 | // 3 | // Copyright 2016 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #include 18 | #include "cc13xx-romapi.h" 19 | 20 | int flash_agent_setup(flash_agent *agent) { 21 | return ERR_NONE; 22 | } 23 | 24 | int flash_agent_erase(u32 flash_addr, u32 length) { 25 | if (flash_addr & 0xFFF) { 26 | return ERR_ALIGNMENT; 27 | } 28 | while (length > 0) { 29 | if (ROM_FlashSectorErase(flash_addr)) { 30 | return ERR_FAIL; 31 | } 32 | if (length > 4096) { 33 | length -= 4096; 34 | flash_addr += 4096; 35 | } else { 36 | break; 37 | } 38 | } 39 | return 0; 40 | } 41 | 42 | int flash_agent_write(u32 flash_addr, const void *data, u32 length) { 43 | if (flash_addr & 0xFFF) { 44 | return ERR_ALIGNMENT; 45 | } 46 | if (ROM_FlashProgram(data, flash_addr, length)) { 47 | return ERR_FAIL; 48 | } 49 | return 0; 50 | } 51 | 52 | 53 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 54 | return ERR_INVALID; 55 | } 56 | 57 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 58 | .magic = AGENT_MAGIC, 59 | .version = AGENT_VERSION, 60 | .flags = 0, 61 | .load_addr = 0x20000400, 62 | .data_addr = 0x20001000, 63 | .data_size = 0x1000, 64 | .flash_addr = 0x00000000, 65 | .flash_size = 0x00020000, 66 | .setup = flash_agent_setup, 67 | .erase = flash_agent_erase, 68 | .write = flash_agent_write, 69 | .ioctl = flash_agent_ioctl, 70 | }; 71 | -------------------------------------------------------------------------------- /agents/efr32bg2x.c: -------------------------------------------------------------------------------- 1 | // agents/efr32bg2x.c 2 | // 3 | // Copyright 2022 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #define LOADADDR 0x20000400 18 | 19 | #define FLASH_BASE 0x00000000 20 | 21 | #include 22 | #include 23 | 24 | #define CMU_CLKEN1_SET 0x40009068 25 | #define CMU_CLKEN1_MSC (1U<<17) 26 | 27 | #define MSC_WRITECTRL 0x4003000C 28 | #define MSC_WRITECTRL_SET 0x4003100C 29 | #define MSC_WRITECTRL_CLR 0x4003200C 30 | #define MSC_WRITECMD 0x40030010 31 | #define MSC_WRITECMD_SET 0x40031010 32 | #define MSC_WRITECMD_CLR 0x40032010 33 | #define MSC_ADDRB 0x40030014 34 | #define MSC_WDATA 0x40030018 35 | #define MSC_STATUS 0x4003001C 36 | 37 | #define MSC_WRITECTRL_WREN 1 38 | 39 | #define MSC_WRITECMD_WRITEND (1U<<2) 40 | #define MSC_WRITECMD_ERASEPAGE (1U<<1) 41 | 42 | #define MSC_STATUS_WREADY (1U<<27) 43 | #define MSC_STATUS_PWRON (1U<<24) 44 | #define MSC_STATUS_REGLOCK (1U<<16) 45 | #define MSC_STATUS_TIMEOUT (1U<<6) 46 | #define MSC_STATUS_PENDING (1U<<5) 47 | #define MSC_STATUS_ERASEABORTYED (1U<<4) 48 | #define MSC_STATUS_WDATAREADY (1U<<3) 49 | #define MSC_STATUS_INVADDR (1U<<2) 50 | #define MSC_STATUS_LOCKED (1U<<1) 51 | #define MSC_STATUS_BUSY (1U<<0) 52 | 53 | static unsigned FLASH_PAGE_SIZE = 8192; 54 | static unsigned FLASH_SIZE = 352 * 1024; 55 | 56 | int flash_agent_setup(flash_agent *agent) { 57 | // TODO - validate part ID 58 | if (0) { 59 | // unknown part 60 | return ERR_INVALID; 61 | } 62 | 63 | // TODO: read from userdata 64 | agent->flash_size = FLASH_SIZE; 65 | 66 | return ERR_NONE; 67 | } 68 | 69 | int flash_agent_erase(u32 flash_addr, u32 length) { 70 | unsigned v; 71 | int status = ERR_NONE; 72 | if (flash_addr > FLASH_SIZE) { 73 | return ERR_INVALID; 74 | } 75 | if (flash_addr & (FLASH_PAGE_SIZE - 1)) { 76 | return ERR_ALIGNMENT; 77 | } 78 | 79 | writel(CMU_CLKEN1_MSC, CMU_CLKEN1_SET); 80 | writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_SET); 81 | while (length > 0) { 82 | writel(flash_addr, MSC_ADDRB); 83 | v = readl(MSC_STATUS); 84 | if (v & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED)) { 85 | status = ERR_INVALID; 86 | break; 87 | } 88 | if (!(v & MSC_STATUS_WREADY)) { 89 | status = ERR_FAIL; 90 | break; 91 | } 92 | if (length > FLASH_PAGE_SIZE) { 93 | length -= FLASH_PAGE_SIZE; 94 | } else { 95 | length = 0; 96 | } 97 | writel(MSC_WRITECMD_ERASEPAGE, MSC_WRITECMD_SET); 98 | while (readl(MSC_STATUS) & MSC_STATUS_BUSY) ; 99 | for (unsigned n = 0; n < FLASH_PAGE_SIZE; n += 4) { 100 | if (readl(flash_addr + n) != 0xFFFFFFFF) { 101 | status = ERR_FAIL; 102 | goto done; 103 | } 104 | } 105 | flash_addr += FLASH_PAGE_SIZE; 106 | } 107 | done: 108 | writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_CLR); 109 | return status; 110 | } 111 | 112 | int flash_agent_write(u32 flash_addr, const void *_data, u32 length) { 113 | int status = ERR_NONE; 114 | const unsigned *data = _data; 115 | unsigned v; 116 | if (flash_addr > FLASH_SIZE) { 117 | return ERR_INVALID; 118 | } 119 | if ((flash_addr & 3) || (length & 3)) { 120 | return ERR_ALIGNMENT; 121 | } 122 | writel(CMU_CLKEN1_MSC, CMU_CLKEN1_SET); 123 | writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_SET); 124 | while (length > 0) { 125 | writel(flash_addr, MSC_ADDRB); 126 | v = readl(MSC_STATUS); 127 | if (v & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED)) { 128 | status = ERR_INVALID; 129 | break; 130 | } 131 | if (!(v & MSC_STATUS_WREADY)) { 132 | status = ERR_FAIL; 133 | break; 134 | } 135 | writel(*data, MSC_WDATA); 136 | while (readl(MSC_STATUS) & MSC_STATUS_BUSY) ; 137 | if (readl(flash_addr) != *data) { 138 | status = ERR_FAIL; 139 | goto done; 140 | } 141 | data++; 142 | length -= 4; 143 | flash_addr += 4; 144 | } 145 | done: 146 | writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_CLR); 147 | return status; 148 | } 149 | 150 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 151 | return ERR_INVALID; 152 | } 153 | 154 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 155 | .magic = AGENT_MAGIC, 156 | .version = AGENT_VERSION, 157 | .flags = 0, 158 | .load_addr = LOADADDR, 159 | .data_addr = LOADADDR + 0x400, 160 | .data_size = 0x4000, 161 | .flash_addr = FLASH_BASE, 162 | .flash_size = 0, 163 | .setup = flash_agent_setup, 164 | .erase = flash_agent_erase, 165 | .write = flash_agent_write, 166 | .ioctl = flash_agent_ioctl, 167 | }; 168 | -------------------------------------------------------------------------------- /agents/lpc13xx.c: -------------------------------------------------------------------------------- 1 | #define LOADADDR 0x10000400 2 | #define FLASH_BASE 0x00000000 3 | #define FLASH_SIZE 0x00008000 4 | 5 | #include "lpc13xx_lpc15xx.c" 6 | -------------------------------------------------------------------------------- /agents/lpc13xx_lpc15xx.c: -------------------------------------------------------------------------------- 1 | // agent-lpc15xx/main.c 2 | // 3 | // Copyright 2015 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #include 18 | 19 | #ifdef ARCH_LPC15XX 20 | #define LPC_IAP_FUNC 0x03000205 21 | #else 22 | #define LPC_IAP_FUNC 0x1fff1ff1 23 | #endif 24 | 25 | #define LPC_IAP_PREPARE 50 26 | #define LPC_IAP_WRITE 51 27 | #define LPC_IAP_ERASE 52 28 | 29 | // Note that while the databook claims you can reuse the same array 30 | // for both parameters and results, this is a lie. Attempting to 31 | // do so causes an invalid command failure. 32 | 33 | 34 | int flash_agent_setup(flash_agent *agent) { 35 | return ERR_NONE; 36 | } 37 | 38 | int flash_agent_erase(u32 flash_addr, u32 length) { 39 | void (*romcall)(u32 *, u32 *) = (void*) LPC_IAP_FUNC; 40 | u32 p[5],r[4]; 41 | u32 page = flash_addr >> 12; 42 | u32 last = page + ((length - 1) >> 12); 43 | if (flash_addr & 0xFFF) { 44 | return ERR_ALIGNMENT; 45 | } 46 | 47 | p[0] = LPC_IAP_PREPARE; 48 | p[1] = page; 49 | p[2] = last; 50 | romcall(p,r); 51 | if (r[0]) { 52 | return ERR_FAIL; 53 | } 54 | 55 | p[0] = LPC_IAP_ERASE; 56 | p[1] = page; 57 | p[2] = last; 58 | p[3] = 0x2ee0; 59 | romcall(p,r); 60 | if (r[0]) { 61 | return ERR_FAIL; 62 | } 63 | return ERR_NONE; 64 | } 65 | 66 | int flash_agent_write(u32 flash_addr, const void *data, u32 length) { 67 | void (*romcall)(u32 *,u32 *) = (void*) LPC_IAP_FUNC; 68 | u32 p[5],r[4]; 69 | u32 page = flash_addr >> 12; 70 | if (flash_addr & 0xFFF) { 71 | return ERR_ALIGNMENT; 72 | } 73 | 74 | p[0] = LPC_IAP_PREPARE; 75 | p[1] = page; 76 | p[2] = page; 77 | romcall(p,r); 78 | if (r[0]) { 79 | return ERR_FAIL; 80 | } 81 | 82 | // todo: smaller writes, etc 83 | if (length != 4096) { 84 | int n; 85 | for (n = length; n < 4096; n++) { 86 | ((char*) data)[n] = 0; 87 | } 88 | } 89 | p[0] = LPC_IAP_WRITE; 90 | p[1] = flash_addr; 91 | p[2] = (u32) data; 92 | p[3] = 0x1000; 93 | p[4] = 0x2ee0; 94 | romcall(p,r); 95 | if (r[0]) { 96 | return ERR_FAIL; 97 | } 98 | 99 | return ERR_NONE; 100 | } 101 | 102 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 103 | return ERR_INVALID; 104 | } 105 | 106 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 107 | .magic = AGENT_MAGIC, 108 | .version = AGENT_VERSION, 109 | .flags = FLAG_BOOT_ROM_HACK, 110 | .load_addr = LOADADDR, 111 | .data_addr = LOADADDR + 0x400, 112 | .data_size = 0x1000, 113 | .flash_addr = FLASH_BASE, 114 | .flash_size = FLASH_SIZE, 115 | .setup = flash_agent_setup, 116 | .erase = flash_agent_erase, 117 | .write = flash_agent_write, 118 | .ioctl = flash_agent_ioctl, 119 | }; 120 | -------------------------------------------------------------------------------- /agents/lpc15xx.c: -------------------------------------------------------------------------------- 1 | #define ARCH_LPC15XX 1 2 | 3 | #define LOADADDR 0x02000400 4 | #define FLASH_BASE 0x00000000 5 | #define FLASH_SIZE 0x00010000 6 | 7 | #include "lpc13xx_lpc15xx.c" 8 | -------------------------------------------------------------------------------- /agents/lpc43xx-spifi.c: -------------------------------------------------------------------------------- 1 | // agent-lpc15xx/main.c 2 | // 3 | // Copyright 2015 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #include 18 | #include 19 | 20 | // ---- pinmux 21 | 22 | #define PIN_CFG(m,n) (0x40086000 + ((m) * 0x80) + ((n) * 4)) 23 | #define PIN_MODE(n) ((n) & 3) 24 | #define PIN_PULLUP (0 << 3) // pull-up, no pull-down 25 | #define PIN_REPEATER (1 << 3) // repeater mode 26 | #define PIN_PLAIN (2 << 3) // no pull-up, no pull-down 27 | #define PIN_PULLDOWN (3 << 3) // pull-down, no pull-up 28 | #define PIN_SLOW (0 << 5) // slow slew rate (low noise, medium speed) 29 | #define PIN_FAST (1 << 5) // fast slew rate (medium noise, fast speed) 30 | #define PIN_INPUT (1 << 6) // enable input buffer, required for inputs 31 | #define PIN_FILTER (1 << 7) // enable glitch filter, not for >30MHz signals 32 | 33 | // ---- spifi serial flash controller 34 | 35 | #define SPIFI_CTRL 0x40003000 // Control 36 | #define SPIFI_CMD 0x40003004 // Command 37 | #define SPIFI_ADDR 0x40003008 // Address 38 | #define SPIFI_IDATA 0x4000300C // Intermediate Data 39 | #define SPIFI_CLIMIT 0x40003010 // Cache Limit 40 | #define SPIFI_DATA 0x40003014 // Data 41 | #define SPIFI_MCMD 0x40003018 // Memory Command 42 | #define SPIFI_STAT 0x4000301C // Status 43 | 44 | #define CTRL_TIMEOUT(n) ((n) & 0xFFFF) 45 | #define CTRL_CSHIGH(n) (((n) & 0xF) << 16) // Minimum /CS high time (serclks - 1) 46 | #define CTRL_D_PRFTCH_DIS (1 << 21) // Disable Prefetch of Data 47 | #define CTRL_INTEN (1 << 22) // Enable IRQ on end of command 48 | #define CTRL_MODE3 (1 << 23) // 0=SCK low after +edge of last bit, 1=high 49 | #define CTRL_PRFTCH_DIS (1 << 27) // Disable Prefetch 50 | #define CTRL_DUAL (1 << 28) // 0=Quad 1=Dual (bits in "wide" ops) 51 | #define CTRL_QUAD (0 << 28) 52 | #define CTRL_RFCLK (1 << 29) // 1=sample read data on -edge clock 53 | #define CTRL_FBCLK (1 << 30) // use feedback clock from SCK pin for sampling 54 | #define CTRL_DMAEN (1 << 31) // enable DMA request output 55 | 56 | #define CMD_DATALEN(n) ((n) & 0x3FFF) 57 | #define CMD_POLL (1 << 14) // if set, read byte repeatedly until condition 58 | #define CMD_POLLBIT(n) ((n) & 7) // which bit# to check 59 | #define CMD_POLLSET (1 << 3) // condition is bit# set 60 | #define CMD_POLLCLR (0 << 3) // condition is bit# clear 61 | #define CMD_DOUT (1 << 15) // 1=data phase output, 0=data phase input 62 | #define CMD_DIN (0 << 15) 63 | #define CMD_INTLEN(n) (((n) & 7) << 16) // count of intermediate bytes 64 | #define CMD_FF_SERIAL (0 << 19) // all command fields serial 65 | #define CMD_FF_WIDE_DATA (1 << 19) // data is wide, all other fields serial 66 | #define CMD_FF_SERIAL_OPCODE (2 << 19) // opcode is serial, all other fields wide 67 | #define CMD_FF_WIDE (3 << 19) // all command fields wide 68 | #define CMD_FR_OP (1 << 21) // frame format: opcode only 69 | #define CMD_FR_OP_1B (2 << 21) // opcode, lsb addr 70 | #define CMD_FR_OP_2B (3 << 21) // opcode, 2 lsb addr 71 | #define CMD_FR_OP_3B (4 << 21) // opcode, 3 lsb addr 72 | #define CMD_FR_OP_4B (5 << 21) // opcode, 4b address 73 | #define CMD_FR_3B (6 << 21) // 3 lsb addr 74 | #define CMD_FR_4B (7 << 21) // 4 lsb addr 75 | #define CMD_OPCODE(n) ((n) << 24) 76 | 77 | #define STAT_MCINIT (1 << 0) // set on sw write to MCMD, clear on RST, wr(0) 78 | #define STAT_CMD (1 << 1) // set when CMD written, clear on CS, RST 79 | #define STAT_RESET (1 << 4) // write 1 to abort current txn or memory mode 80 | #define STAT_INTRQ (1 << 5) // read IRQ status, wr(1) to clear 81 | 82 | #define CMD_PAGE_PROGRAM 0x02 83 | #define CMD_READ_DATA 0x03 84 | #define CMD_READ_STATUS 0x05 85 | #define CMD_WRITE_ENABLE 0x06 86 | #define CMD_SECTOR_ERASE 0x20 87 | 88 | static void spifi_write_enable(void) { 89 | writel(CMD_FF_SERIAL | CMD_FR_OP | CMD_OPCODE(CMD_WRITE_ENABLE), 90 | SPIFI_CMD); 91 | while (readl(SPIFI_STAT) & STAT_CMD) ; 92 | } 93 | 94 | static void spifi_wait_busy(void) { 95 | while (readl(SPIFI_STAT) & STAT_CMD) ; 96 | writel(CMD_POLLBIT(0) | CMD_POLLCLR | CMD_POLL | 97 | CMD_FF_SERIAL | CMD_FR_OP | CMD_OPCODE(CMD_READ_STATUS), 98 | SPIFI_CMD); 99 | while (readl(SPIFI_STAT) & STAT_CMD) ; 100 | // discard matching status byte from fifo 101 | readb(SPIFI_DATA); 102 | } 103 | 104 | static void spifi_page_program(u32 addr, u32 *ptr, u32 count) { 105 | spifi_write_enable(); 106 | writel(addr, SPIFI_ADDR); 107 | writel(CMD_DATALEN(count * 4) | CMD_FF_SERIAL | CMD_FR_OP_3B | 108 | CMD_DOUT | CMD_OPCODE(CMD_PAGE_PROGRAM), SPIFI_CMD); 109 | while (count-- > 0) { 110 | writel(*ptr++, SPIFI_DATA); 111 | } 112 | spifi_wait_busy(); 113 | } 114 | 115 | static void spifi_sector_erase(u32 addr) { 116 | spifi_write_enable(); 117 | writel(addr, SPIFI_ADDR); 118 | writel(CMD_FF_SERIAL | CMD_FR_OP_3B | CMD_OPCODE(CMD_SECTOR_ERASE), 119 | SPIFI_CMD); 120 | spifi_wait_busy(); 121 | } 122 | 123 | static int verify_erased(u32 addr, u32 count) { 124 | int err = 0; 125 | writel(addr, SPIFI_ADDR); 126 | writel(CMD_DATALEN(count * 4) | CMD_FF_SERIAL | CMD_FR_OP_3B | 127 | CMD_OPCODE(CMD_READ_DATA), SPIFI_CMD); 128 | while (count-- > 0) { 129 | if (readl(SPIFI_DATA) != 0xFFFFFFFF) err = -1; 130 | } 131 | while (readl(SPIFI_STAT) & STAT_CMD) ; 132 | return err; 133 | } 134 | 135 | static int verify_page(u32 addr, u32 *ptr) { 136 | int count = 256 / 4; 137 | int err = 0; 138 | writel(addr, SPIFI_ADDR); 139 | writel(CMD_DATALEN(count * 4) | CMD_FF_SERIAL | CMD_FR_OP_3B | 140 | CMD_OPCODE(CMD_READ_DATA), SPIFI_CMD); 141 | while (count-- > 0) { 142 | if (readl(SPIFI_DATA) != *ptr++) err = -1; 143 | } 144 | while (readl(SPIFI_STAT) & STAT_CMD) ; 145 | return err; 146 | } 147 | 148 | // at reset-stop, all clocks are running from 12MHz internal osc 149 | // todo: run SPIFI_CLK at a much higher rate 150 | // todo: use 4bit modes 151 | int flash_agent_setup(flash_agent *agent) { 152 | // configure pinmux 153 | writel(PIN_MODE(3) | PIN_PLAIN, PIN_CFG(3,3)); // SPIFI_SCK 154 | writel(PIN_MODE(3) | PIN_PLAIN | PIN_INPUT, PIN_CFG(3, 4)); // SPIFI_SIO3 155 | writel(PIN_MODE(3) | PIN_PLAIN | PIN_INPUT, PIN_CFG(3, 5)); // SPIFI_SIO2 156 | writel(PIN_MODE(3) | PIN_PLAIN | PIN_INPUT, PIN_CFG(3, 6)); // SPIFI_MISO 157 | writel(PIN_MODE(3) | PIN_PLAIN | PIN_INPUT, PIN_CFG(3, 7)); // SPIFI_MOSI 158 | writel(PIN_MODE(3) | PIN_PLAIN, PIN_CFG(3, 8)); // SPIFI_CS 159 | 160 | // reset spifi controller 161 | writel(STAT_RESET, SPIFI_STAT); 162 | while (readl(SPIFI_STAT) & STAT_RESET) ; 163 | writel(0xFFFFF, SPIFI_CTRL); 164 | 165 | return ERR_NONE; 166 | } 167 | 168 | int flash_agent_erase(u32 flash_addr, u32 length) { 169 | if (flash_addr & 0xFFF) { 170 | return ERR_ALIGNMENT; 171 | } 172 | while (length != 0) { 173 | spifi_sector_erase(flash_addr); 174 | if (verify_erased(flash_addr, 0x1000/4)) { 175 | return ERR_FAIL; 176 | } 177 | if (length < 0x1000) break; 178 | length -= 0x1000; 179 | flash_addr += 0x1000; 180 | } 181 | return ERR_NONE; 182 | } 183 | 184 | int flash_agent_write(u32 flash_addr, const void *data, u32 length) { 185 | char *x = (void*) data; 186 | if (flash_addr & 0xFFF) { 187 | return ERR_ALIGNMENT; 188 | } 189 | while (length != 0) { 190 | if (length < 256) { 191 | int n; 192 | for (n = length; n < 256; n++) { 193 | x[n] = 0; 194 | } 195 | } 196 | spifi_page_program(flash_addr, (void*) x, 256 / 4); 197 | if (verify_page(flash_addr, (void*) x)) { 198 | return ERR_FAIL; 199 | } 200 | if (length < 256) break; 201 | length -= 256; 202 | flash_addr += 256; 203 | x += 256; 204 | } 205 | writel(CMD_FF_SERIAL | CMD_FR_OP_3B | CMD_OPCODE(CMD_READ_DATA), SPIFI_MCMD); 206 | return ERR_NONE; 207 | } 208 | 209 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 210 | return ERR_INVALID; 211 | } 212 | 213 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 214 | .magic = AGENT_MAGIC, 215 | .version = AGENT_VERSION, 216 | .flags = 0, 217 | .load_addr = LOADADDR, 218 | .data_addr = LOADADDR + 0x400, 219 | .data_size = 0x8000, 220 | .flash_addr = FLASH_BASE, 221 | .flash_size = FLASH_SIZE, 222 | .setup = flash_agent_setup, 223 | .erase = flash_agent_erase, 224 | .write = flash_agent_write, 225 | .ioctl = flash_agent_ioctl, 226 | }; 227 | -------------------------------------------------------------------------------- /agents/lpclink2.c: -------------------------------------------------------------------------------- 1 | #define FLASH_BASE 0x00000000 2 | #define FLASH_SIZE 0x00100000 3 | #define LOADADDR 0x10080400 4 | 5 | #include "lpc43xx-spifi.c" 6 | -------------------------------------------------------------------------------- /agents/nrf528xx.c: -------------------------------------------------------------------------------- 1 | // agents/nrf528xx.c 2 | // 3 | // Copyright 2019 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #define LOADADDR 0x20000400 18 | 19 | #define FLASH_BASE 0x00000000 20 | 21 | #include 22 | #include 23 | 24 | #define NVMC_READY 0x4001E400 25 | #define NVMC_CONFIG 0x4001E504 26 | #define NVMC_CONFIG_READ 0 27 | #define NVMC_CONFIG_WRITE 1 28 | #define NVMC_CONFIG_ERASE 2 29 | #define NVMC_ERASEPAGE 0x4001E508 30 | 31 | #define FICR_CODEPAGESIZE 0x10000010 32 | #define FICR_CODESIZE 0x10000014 33 | 34 | static unsigned FLASH_PAGE_SIZE = 1024; 35 | static unsigned FLASH_SIZE = 192 * 1024; 36 | 37 | int flash_agent_setup(flash_agent *agent) { 38 | 39 | // TODO - validate part ID 40 | if (0) { 41 | // unknown part 42 | return ERR_INVALID; 43 | } 44 | 45 | // check flash size 46 | FLASH_PAGE_SIZE = readl(FICR_CODEPAGESIZE); 47 | FLASH_SIZE = FLASH_PAGE_SIZE * readl(FICR_CODESIZE); 48 | 49 | agent->flash_size = FLASH_SIZE; 50 | 51 | return ERR_NONE; 52 | } 53 | 54 | int flash_agent_erase(u32 flash_addr, u32 length) { 55 | int status = ERR_NONE; 56 | if (flash_addr > FLASH_SIZE) { 57 | return ERR_INVALID; 58 | } 59 | if (flash_addr & (FLASH_PAGE_SIZE - 1)) { 60 | return ERR_ALIGNMENT; 61 | } 62 | writel(NVMC_CONFIG_ERASE, NVMC_CONFIG); 63 | while (length > 0) { 64 | if (length > FLASH_PAGE_SIZE) { 65 | length -= FLASH_PAGE_SIZE; 66 | } else { 67 | length = 0; 68 | } 69 | writel(flash_addr, NVMC_ERASEPAGE); 70 | while (readl(NVMC_READY) != 1) ; 71 | for (unsigned n = 0; n < FLASH_PAGE_SIZE; n += 4) { 72 | if (readl(flash_addr + n) != 0xFFFFFFFF) { 73 | status = ERR_FAIL; 74 | goto done; 75 | } 76 | } 77 | flash_addr += FLASH_PAGE_SIZE; 78 | } 79 | done: 80 | writel(NVMC_CONFIG_READ, NVMC_CONFIG); 81 | return status; 82 | } 83 | 84 | int flash_agent_write(u32 flash_addr, const void *_data, u32 length) { 85 | int status = ERR_NONE; 86 | const unsigned *data = _data; 87 | if (flash_addr > FLASH_SIZE) { 88 | return ERR_INVALID; 89 | } 90 | if ((flash_addr & 3) || (length & 3)) { 91 | return ERR_ALIGNMENT; 92 | } 93 | writel(NVMC_CONFIG_WRITE, NVMC_CONFIG); 94 | while (length > 0) { 95 | writel(*data, flash_addr); 96 | while (readl(NVMC_READY) != 1) ; 97 | if (readl(flash_addr) != *data) { 98 | status = ERR_FAIL; 99 | goto done; 100 | } 101 | data++; 102 | length -= 4; 103 | flash_addr += 4; 104 | } 105 | done: 106 | writel(NVMC_CONFIG_READ, NVMC_CONFIG); 107 | return status; 108 | } 109 | 110 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 111 | return ERR_INVALID; 112 | } 113 | 114 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 115 | .magic = AGENT_MAGIC, 116 | .version = AGENT_VERSION, 117 | .flags = 0, 118 | .load_addr = LOADADDR, 119 | .data_addr = LOADADDR + 0x400, 120 | .data_size = 0x4000, 121 | .flash_addr = FLASH_BASE, 122 | .flash_size = 0, 123 | .setup = flash_agent_setup, 124 | .erase = flash_agent_erase, 125 | .write = flash_agent_write, 126 | .ioctl = flash_agent_ioctl, 127 | }; 128 | -------------------------------------------------------------------------------- /agents/pico.c: -------------------------------------------------------------------------------- 1 | // agents/pico.c 2 | // 3 | // Copyright 2020 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #define LOADADDR 0x20000400 18 | 19 | #define FLASH_BASE 0x00000000 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | static unsigned FLASH_BLOCK_SIZE = 256; 26 | static unsigned FLASH_PAGE_SIZE = 4096; 27 | static unsigned FLASH_SIZE = 4 * 1024 * 1024; 28 | 29 | #define FLASH_XIP_BASE 0x10000000 30 | 31 | #define CODE(c1, c2) (((c2) << 8) | (c1)) 32 | 33 | #define ROM_LOOKUP_FN_PTR 0x18 34 | #define ROM_FN_TABLE_PTR 0x14 35 | 36 | // lookup fn for code using ROM lookup helper and ROM fn table 37 | void* lookup_fn(uint32_t code) { 38 | void* (*lookup)(uint32_t table, uint32_t code) = 39 | (void*) (uintptr_t) *((uint16_t*) ROM_LOOKUP_FN_PTR); 40 | 41 | return lookup(*((uint16_t*)ROM_FN_TABLE_PTR), code); 42 | } 43 | 44 | static void (*_flash_connect)(void); 45 | static void (*_flash_exit_xip)(void); 46 | static void (*_flash_erase)(uint32_t addr, uint32_t len, 47 | uint32_t block_size, uint32_t block_cmd); 48 | static void (*_flash_write)(uint32_t addr, const void* data, uint32_t len); 49 | static void (*_flash_flush_cache)(void); 50 | static void (*_flash_enter_xip)(void); 51 | 52 | // erase: addr and count must be 4096 aligned 53 | // write: addr and len must be 256 aligned 54 | 55 | int flash_agent_setup(flash_agent *agent) { 56 | // TODO - validate part ID 57 | if (0) { 58 | // unknown part 59 | return ERR_INVALID; 60 | } 61 | 62 | _flash_connect = lookup_fn(CODE('I','F')); 63 | _flash_exit_xip = lookup_fn(CODE('E','X')); 64 | _flash_erase = lookup_fn(CODE('R','E')); 65 | _flash_write = lookup_fn(CODE('R','P')); 66 | _flash_flush_cache = lookup_fn(CODE('F','C')); 67 | _flash_enter_xip = lookup_fn(CODE('C','X')); 68 | 69 | // TODO: obtain from spi flash 70 | agent->flash_size = FLASH_SIZE; 71 | 72 | return ERR_NONE; 73 | } 74 | 75 | int flash_agent_erase(u32 flash_addr, u32 length) { 76 | if (flash_addr > FLASH_SIZE) { 77 | return ERR_INVALID; 78 | } 79 | if (flash_addr & (FLASH_PAGE_SIZE - 1)) { 80 | return ERR_ALIGNMENT; 81 | } 82 | if (length & (FLASH_PAGE_SIZE-1)) { 83 | length = (length & (~(FLASH_PAGE_SIZE-1))) + FLASH_PAGE_SIZE; 84 | } 85 | 86 | _flash_connect(); 87 | _flash_exit_xip(); 88 | _flash_erase(flash_addr, length, 65536, 0xD8); 89 | _flash_flush_cache(); 90 | _flash_enter_xip(); 91 | 92 | uint32_t* flash = (void*) (flash_addr + FLASH_XIP_BASE); 93 | for (uint32_t n = 0; n < length; n+= 4) { 94 | if (*flash++ != 0xFFFFFFFF) { 95 | return ERR_FAIL; 96 | } 97 | } 98 | 99 | return ERR_NONE; 100 | } 101 | 102 | int flash_agent_write(u32 flash_addr, const void *data, u32 length) { 103 | if (flash_addr > FLASH_SIZE) { 104 | return ERR_INVALID; 105 | } 106 | if (flash_addr & (FLASH_BLOCK_SIZE - 1)) { 107 | return ERR_ALIGNMENT; 108 | } 109 | if (length & (FLASH_BLOCK_SIZE-1)) { 110 | length = (length & (~(FLASH_BLOCK_SIZE-1))) + FLASH_BLOCK_SIZE; 111 | } 112 | 113 | _flash_connect(); 114 | _flash_exit_xip(); 115 | _flash_write(flash_addr, data, length); 116 | _flash_flush_cache(); 117 | _flash_enter_xip(); 118 | 119 | uint32_t* flash = (void*) (flash_addr + FLASH_XIP_BASE); 120 | const uint32_t* xdata = data; 121 | for (uint32_t n = 0; n < length; n += 4) { 122 | if (*flash++ != *xdata++) { 123 | return ERR_FAIL; 124 | } 125 | } 126 | 127 | return ERR_NONE; 128 | } 129 | 130 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 131 | return ERR_INVALID; 132 | } 133 | 134 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 135 | .magic = AGENT_MAGIC, 136 | .version = AGENT_VERSION, 137 | .flags = 0, 138 | .load_addr = LOADADDR, 139 | .data_addr = LOADADDR + 0x400, 140 | .data_size = 0x4000, 141 | .flash_addr = FLASH_BASE, 142 | .flash_size = 0, 143 | .setup = flash_agent_setup, 144 | .erase = flash_agent_erase, 145 | .write = flash_agent_write, 146 | .ioctl = flash_agent_ioctl, 147 | }; 148 | -------------------------------------------------------------------------------- /agents/stm32f0xx.c: -------------------------------------------------------------------------------- 1 | // agents/stm-main.c 2 | // 3 | // Copyright 2015 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #define LOADADDR 0x20000400 18 | 19 | #define FLASH_BASE 0x08000000 20 | #define FLASH_SIZE 0x00004000 21 | 22 | #include 23 | #include 24 | 25 | #define _FLASH_BASE 0x40022000 26 | #define FLASH_ACR (_FLASH_BASE + 0x00) 27 | 28 | #define FLASH_KEYR (_FLASH_BASE + 0x04) 29 | #define FLASH_KEYR_KEY1 0x45670123 30 | #define FLASH_KEYR_KEY2 0xCDEF89AB 31 | 32 | #define FLASH_SR (_FLASH_BASE + 0x0C) 33 | #define FLASH_SR_EOP (1 << 5) // end of operation 34 | #define FLASH_SR_WP_ERR (1 << 4) // write protect error 35 | #define FLASH_SR_PG_ERR (1 << 2) // programming error 36 | #define FLASH_SR_BSY (1 << 0) // busy 37 | #define FLASH_SR_ERR_MASK (FLASH_SR_WP_ERR | FLASH_SR_PG_ERR) 38 | 39 | #define FLASH_CR (_FLASH_BASE + 0x10) 40 | #define FLASH_CR_OBL_LAUNCH (1 << 13) // reload option byte & reset system 41 | #define FLASH_CR_EOPIE (1 << 12) // enable end-of-op irq 42 | #define FLASH_CR_ERRIE (1 << 10) // enable error irq 43 | #define FLASH_CR_OPTWRE (1 << 9) // option byte write enable 44 | #define FLASH_CR_LOCK (1 << 7) // indicates flash is locked 45 | #define FLASH_CR_STRT (1 << 6) // start erase operation 46 | #define FLASH_CR_OPTER (1 << 5) // option byte erase 47 | #define FLASH_CR_OPTPG (1 << 4) // option byte program 48 | #define FLASH_CR_MER (1 << 2) // mass erase 49 | #define FLASH_CR_PER (1 << 1) // page erase 50 | #define FLASH_CR_PG (1 << 0) // programming 51 | #define FLASH_CR_MASK (~0x000036F7) // bits to not modify 52 | 53 | #define FLASH_AR (_FLASH_BASE + 0x14) 54 | 55 | static unsigned FLASH_PAGE_SIZE = 1024; 56 | 57 | int flash_agent_setup(flash_agent *agent) { 58 | 59 | // check MCU ID 60 | switch (readl(0x40015800) & 0xFFF) { 61 | case 0x444: // F03x 62 | case 0x445: // F04x 63 | case 0x440: // F05x 64 | break; 65 | case 0x448: // F07x 66 | case 0x442: // F09x 67 | FLASH_PAGE_SIZE = 2048; 68 | break; 69 | default: 70 | // unknown part 71 | return ERR_INVALID; 72 | } 73 | 74 | // check flash size 75 | agent->flash_size = readw(0x1FFFF7CC) * 1024; 76 | 77 | writel(FLASH_KEYR_KEY1, FLASH_KEYR); 78 | writel(FLASH_KEYR_KEY2, FLASH_KEYR); 79 | if (readl(FLASH_CR) & FLASH_CR_LOCK) { 80 | return ERR_FAIL; 81 | } else { 82 | return ERR_NONE; 83 | } 84 | } 85 | 86 | int flash_agent_erase(u32 flash_addr, u32 length) { 87 | u32 cr; 88 | int n; 89 | if (flash_addr & (FLASH_PAGE_SIZE - 1)) { 90 | return ERR_ALIGNMENT; 91 | } 92 | cr = readl(FLASH_CR) & FLASH_CR_MASK; 93 | 94 | while (length > 0) { 95 | if (length > FLASH_PAGE_SIZE) { 96 | length -= FLASH_PAGE_SIZE; 97 | } else { 98 | length = 0; 99 | } 100 | writel(cr | FLASH_CR_PER, FLASH_CR); 101 | writel(flash_addr, FLASH_AR); 102 | writel(cr | FLASH_CR_PER | FLASH_CR_STRT, FLASH_CR); 103 | while (readl(FLASH_SR) & FLASH_SR_BSY) ; 104 | for (n = 0; n < FLASH_PAGE_SIZE; n += 4) { 105 | if (readl(flash_addr + n) != 0xFFFFFFFF) { 106 | return ERR_FAIL; 107 | } 108 | } 109 | flash_addr += FLASH_PAGE_SIZE; 110 | } 111 | return ERR_NONE; 112 | } 113 | 114 | int flash_agent_write(u32 flash_addr, const void *_data, u32 length) { 115 | const unsigned short *data = _data; 116 | u32 v, cr; 117 | if ((flash_addr & 3) || (length & 3)) { 118 | return ERR_ALIGNMENT; 119 | } 120 | cr = readl(FLASH_CR) & FLASH_CR_MASK; 121 | writel(cr | FLASH_CR_PG, FLASH_CR); 122 | while (length > 0) { 123 | writew(*data, flash_addr); 124 | while ((v = readl(FLASH_SR)) & FLASH_SR_BSY) ; 125 | if (readw(flash_addr) != *data) { 126 | writel(cr, FLASH_CR); 127 | return ERR_FAIL; 128 | } 129 | data++; 130 | length -= 2; 131 | flash_addr += 2; 132 | } 133 | writel(cr, FLASH_CR); 134 | return ERR_NONE; 135 | } 136 | 137 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 138 | return ERR_INVALID; 139 | } 140 | 141 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 142 | .magic = AGENT_MAGIC, 143 | .version = AGENT_VERSION, 144 | .flags = 0, 145 | .load_addr = LOADADDR, 146 | .data_addr = LOADADDR + 0x400, 147 | .data_size = 0x1000, 148 | .flash_addr = FLASH_BASE, 149 | .flash_size = FLASH_SIZE, 150 | .setup = flash_agent_setup, 151 | .erase = flash_agent_erase, 152 | .write = flash_agent_write, 153 | .ioctl = flash_agent_ioctl, 154 | }; 155 | -------------------------------------------------------------------------------- /agents/stm32f4xx.c: -------------------------------------------------------------------------------- 1 | #define LOADADDR 0x20000400 2 | 3 | #define FLASH_BASE 0x00000000 4 | #define FLASH_SIZE 0x00100000 5 | 6 | #include "stm32fxxx.c" 7 | -------------------------------------------------------------------------------- /agents/stm32fxxx.c: -------------------------------------------------------------------------------- 1 | // agents/stm-main.c 2 | // 3 | // Copyright 2015 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #include 18 | #include 19 | 20 | #define _FLASH_BASE 0x40023C00 21 | #define FLASH_ACR (_FLASH_BASE + 0x00) 22 | 23 | #define FLASH_KEYR (_FLASH_BASE + 0x04) 24 | #define FLASH_KEYR_KEY1 0x45670123 25 | #define FLASH_KEYR_KEY2 0xCDEF89AB 26 | 27 | #define FLASH_SR (_FLASH_BASE + 0x0C) 28 | #define FLASH_SR_BSY (1 << 16) 29 | #define FLASH_SR_PGSERR (1 << 7) // sequence error 30 | #define FLASH_SR_PGPERR (1 << 6) // parallelism error 31 | #define FLASH_SR_PGAERR (1 << 5) // alignment error 32 | #define FLASH_SR_WRPERR (1 << 4) // write-protect error 33 | #define FLASH_SR_OPERR (1 << 1) // operation error 34 | #define FLASH_SR_ERRMASK 0xF2 35 | #define FLASH_SR_EOP (1 << 0) // end of operation 36 | 37 | #define FLASH_CR (_FLASH_BASE + 0x10) 38 | #define FLASH_CR_LOCK (1 << 31) 39 | #define FLASH_CR_ERRIE (1 << 25) // error irq en 40 | #define FLASH_CR_EOPIE (1 << 24) // end of op irq en 41 | #define FLASH_CR_STRT (1 << 16) // start 42 | #define FLASH_CR_PSIZE_8 (0 << 8) 43 | #define FLASH_CR_PSIZE_16 (1 << 8) 44 | #define FLASH_CR_PSIZE_32 (2 << 8) 45 | #define FLASH_CR_PSIZE_64 (3 << 8) 46 | #define FLASH_CR_SNB(n) (((n) & 15) << 3) // sector number 47 | #define FLASH_CR_MER (1 << 2) // mass erase 48 | #define FLASH_CR_SER (1 << 1) // sector erase 49 | #define FLASH_CR_PG (1 << 0) // programming 50 | 51 | 52 | #define SECTORS 12 53 | 54 | static u32 sectors[SECTORS + 1] = { 55 | 0x00000000, 56 | 0x00004000, 57 | 0x00008000, 58 | 0x0000C000, 59 | 0x00010000, 60 | 0x00020000, 61 | 0x00040000, 62 | 0x00060000, 63 | 0x00080000, 64 | 0x000A0000, 65 | 0x000C0000, 66 | 0x000E0000, 67 | 0x00100000, 68 | }; 69 | 70 | int flash_agent_setup(flash_agent *agent) { 71 | writel(FLASH_KEYR_KEY1, FLASH_KEYR); 72 | writel(FLASH_KEYR_KEY2, FLASH_KEYR); 73 | if (readl(FLASH_CR) & FLASH_CR_LOCK) { 74 | return ERR_FAIL; 75 | } else { 76 | return ERR_NONE; 77 | } 78 | } 79 | 80 | int flash_agent_erase(u32 flash_addr, u32 length) { 81 | u32 v; 82 | int n; 83 | for (n = 0; n < SECTORS; n++) { 84 | if (flash_addr == sectors[n]) goto ok; 85 | } 86 | return ERR_ALIGNMENT; 87 | ok: 88 | for (;;) { 89 | writel(FLASH_CR_SER | FLASH_CR_SNB(n), FLASH_CR); 90 | writel(FLASH_CR_STRT | FLASH_CR_SER | FLASH_CR_SNB(n), FLASH_CR); 91 | while ((v = readl(FLASH_SR)) & FLASH_SR_BSY) ; 92 | if (v & FLASH_SR_ERRMASK) { 93 | return ERR_FAIL; 94 | } 95 | n++; 96 | if (n == SECTORS) break; 97 | if ((sectors[n] - flash_addr) >= length) break; 98 | } 99 | return ERR_NONE; 100 | } 101 | 102 | int flash_agent_write(u32 flash_addr, const void *_data, u32 length) { 103 | const u32 *data = _data; 104 | u32 v; 105 | if ((flash_addr & 3) || (length & 3)) { 106 | return ERR_ALIGNMENT; 107 | } 108 | writel(FLASH_CR_PG | FLASH_CR_PSIZE_32, FLASH_CR); 109 | while (length > 0) { 110 | writel(*data, flash_addr); 111 | data++; 112 | length -= 4; 113 | flash_addr += 4; 114 | while ((v = readl(FLASH_SR)) & FLASH_SR_BSY) ; 115 | if (v & FLASH_SR_ERRMASK) { 116 | writel(0, FLASH_CR); 117 | return ERR_FAIL; 118 | } 119 | } 120 | writel(0, FLASH_CR); 121 | return ERR_NONE; 122 | } 123 | 124 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) { 125 | return ERR_INVALID; 126 | } 127 | 128 | const flash_agent __attribute((section(".vectors"))) FlashAgent = { 129 | .magic = AGENT_MAGIC, 130 | .version = AGENT_VERSION, 131 | .flags = 0, 132 | .load_addr = LOADADDR, 133 | .data_addr = LOADADDR + 0x400, 134 | .data_size = 0x8000, 135 | .flash_addr = FLASH_BASE, 136 | .flash_size = FLASH_SIZE, 137 | .setup = flash_agent_setup, 138 | .erase = flash_agent_erase, 139 | .write = flash_agent_write, 140 | .ioctl = flash_agent_ioctl, 141 | }; 142 | -------------------------------------------------------------------------------- /build/agent.ld: -------------------------------------------------------------------------------- 1 | 2 | /* RAM only binary layout */ 3 | 4 | SECTIONS { 5 | .text : { 6 | . = ALIGN(4); 7 | KEEP (*(.vectors)) 8 | *(.text) 9 | *(.text.*) 10 | *(.rodata) 11 | *(.rodata.*) 12 | . = ALIGN(4); 13 | __data_init__ = . ; 14 | } /* >RAM */ 15 | .data : { 16 | . = ALIGN(4); 17 | __data_start__ = . ; 18 | *(.data) 19 | *(.data.*) 20 | . = ALIGN(4); 21 | __data_end__ = . ; 22 | } /* >RAM */ 23 | .bss : { 24 | . = ALIGN(4); 25 | __bss_start__ = . ; 26 | *(.bss) 27 | *(.bss.*) 28 | *(COMMON) 29 | . = ALIGN(4); 30 | __bss_end__ = . ; 31 | } /*>RAM */ 32 | } 33 | -------------------------------------------------------------------------------- /build/build.mk: -------------------------------------------------------------------------------- 1 | 2 | what_to_build:: all 3 | 4 | -include local.mk 5 | 6 | #TOOLCHAIN ?= arm-none-eabi- 7 | 8 | TARGET_CC := $(TOOLCHAIN)gcc 9 | TARGET_OBJCOPY := $(TOOLCHAIN)objcopy 10 | TARGET_OBJDUMP := $(TOOLCHAIN)objdump 11 | 12 | ARCH_M3_CFLAGS := -mcpu=cortex-m3 -mthumb 13 | ARCH_M3_LIBS := $(shell $(TARGET_CC) $(ARCH_M3_CFLAGS) -print-libgcc-file-name) 14 | 15 | ARCH_M0_CFLAGS := -mcpu=cortex-m0 -mthumb 16 | ARCH_M0_LIBS := $(shell $(TARGET_CC) $(ARCH_M0_CFLAGS) -print-libgcc-file-name) 17 | 18 | TARGET_CFLAGS := -g -Os -Wall 19 | TARGET_CFLAGS += -Wno-unused-but-set-variable 20 | TARGET_CFLAGS += -I. -Iinclude 21 | #TARGET_CFLAGS += -mcpu=cortex-m3 -mthumb -mthumb-interwork 22 | TARGET_CFLAGS += -ffunction-sections -fdata-sections 23 | TARGET_CFLAGS += -fno-builtin -nostdlib 24 | 25 | # tell gcc there's not a full libc it can depend on 26 | # so it won't do thinks like printf("...") -> puts("...") 27 | TARGET_CFLAGS += -ffreestanding 28 | 29 | QUIET := @ 30 | 31 | UNAME := $(shell uname) 32 | UNAME_M := $(shell uname -m) 33 | 34 | HOST_CFLAGS := -g -O1 -Wall 35 | HOST_CFLAGS += -Itools -Iinclude 36 | HOST_CFLAGS += -DLINENOISE_INTERRUPTIBLE 37 | 38 | ifeq ($(UNAME),Darwin) 39 | HOST_CFLAGS += -I/opt/local/include -L/opt/local/lib 40 | HOST_LIBS += -lusb-1.0 41 | endif 42 | ifeq ($(UNAME),Linux) 43 | HOST_LIBS += -lusb-1.0 -lpthread -lrt 44 | endif 45 | 46 | AGENTS := 47 | ALL := 48 | DEPS := 49 | 50 | out/agent-%.bin: out/agent-%.elf 51 | @mkdir -p $(dir $@) 52 | @echo generate $@ 53 | $(QUIET)$(TARGET_OBJCOPY) -O binary $< $@ 54 | 55 | out/agent-%.lst: out/agent-%.elf 56 | @mkdir -p $(dir $@) 57 | @echo generate $@ 58 | $(QUIET)$(TARGET_OBJDUMP) -d $< > $@ 59 | 60 | out/agent-%.elf: agents/%.c 61 | @mkdir -p $(dir $@) 62 | @echo compile $@ 63 | $(QUIET)$(TARGET_CC) $(TARGET_CFLAGS) $(ARCH_$(ARCH)_CFLAGS) -Wl,--script=build/agent.ld -Wl,-Ttext=$(LOADADDR) -o $@ $< $(ARCH_$(ARCH)_LIBS) 64 | 65 | out/%.o: %.c 66 | @mkdir -p $(dir $@) 67 | @echo compile $< 68 | $(QUIET)gcc -MMD -MP -c $(HOST_CFLAGS) -o $@ $< 69 | 70 | define _program 71 | ALL += bin/$1 72 | DEPS += $3 73 | bin/$1: $2 74 | @mkdir -p $$(dir $$@) 75 | @echo link $$@ 76 | $(QUIET)gcc $(HOST_CFLAGS) -o $$@ $2 $(HOST_LIBS) 77 | endef 78 | 79 | program = $(eval $(call _program,$1,$(patsubst %.c,out/%.o,$2),$(patsubst %.c,out/%.d,$2))) 80 | 81 | agent = $(eval AGENTS += $(strip $1))\ 82 | $(eval ALL += $(patsubst %,out/agent-%.bin,$(strip $1)))\ 83 | $(eval ALL += $(patsubst %,out/agent-%.lst,$(strip $1)))\ 84 | $(eval out/agent-$(strip $1).elf: LOADADDR := $(strip $2))\ 85 | $(eval out/agent-$(strip $1).elf: ARCH := $(strip $3)) 86 | 87 | -------------------------------------------------------------------------------- /docs/99-mdebug.rules: -------------------------------------------------------------------------------- 1 | # mdebug debugger firmware and lpcboot protocol 2 | SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="5038", MODE="0660", GROUP="plugdev" 3 | SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="5039", MODE="0660", GROUP="plugdev" 4 | 5 | # nxp rom loader 6 | SUBSYSTEM=="usb", ATTR{idVendor}=="1fc9", ATTR{idProduct}=="000c", MODE="0660", GROUP="plugdev" 7 | 8 | -------------------------------------------------------------------------------- /docs/building-cross-compiler.txt: -------------------------------------------------------------------------------- 1 | 2 | New Instructions 3 | ---------------- 4 | 5 | Use http://github.com/travisg/toolchains 6 | 7 | 1. % git clone https://github.com/travisg/toolchains.git 8 | 2. % cd toolchains 9 | 3. % ARCHES=arm ./doit 10 | 4. wait while it downloads and builds the toolchain 11 | 5. arrange for toolchains/arm-eabi-4.8.2-Linux-x86_64/bin to be in your 12 | path or use local.mk to override the TOOLCHAIN build variable 13 | 14 | 15 | 16 | Old Instructions 17 | ---------------- 18 | 19 | This is a transcript of how I built the toolchain, not really intended 20 | to be run as a script. 21 | 22 | TODO: see if it's smaller/faster/etc to build only for cortex-m3 23 | 24 | Inspired by http://www.hermann-uwe.de/blog/building-an-arm-cross-toolchain-with-binutils-gcc-newlib-and-gdb-from-source and the gcc online manuals. 25 | 26 | 27 | # install packages needed on ubuntu 28 | sudo apt-get install libgmp3-dev libmpc-dev libgmp3-dev zlib1g-dev build-essential libncurses5-dev texinfo 29 | 30 | # setup workspace 31 | mkdir /work/tools 32 | cd /work/tools 33 | 34 | # grab sources 35 | wget http://mirrors.kernel.org/gnu/binutils/binutils-2.22.tar.bz2 36 | wget http://mirrors.kernel.org/gnu/gcc/gcc-4.6.2/gcc-4.6.2.tar.bz2 37 | wget http://mirrors.kernel.org/gnu/gdb/gdb-7.3.1.tar.bz2 38 | tar -xjvf binutils-2.22.tar.bz2 39 | tar -xjvf gcc-4.6.2.tar.bz2 40 | tar -xjvf gdb-7.3.1.tar.bz2 41 | 42 | mkdir build 43 | 44 | cd build 45 | ../binutils-2.22/configure --target=arm-none-eabi --prefix=/work/tools/arm --enable-interwork --enable-multilib --with-gnu-as --with-gnu-ld --disable-nls 46 | make 47 | make install 48 | cd .. 49 | rm -rf build/* 50 | 51 | cd build 52 | ../gcc-4.6.2/configure --target=arm-none-eabi --prefix=/work/tools/arm --enable-interwork --enable-multilib --enable-languages="c" --disable-nls --disable-shared --disable-threads --without-headers --with-gnu-as --with-gnu-ld --with-system-zlib --disable-libssp --disable-libmudflap --disable-libgomp 53 | make 54 | make install 55 | cd .. 56 | rm -rf build/* 57 | 58 | cd build 59 | ../gdb-7.3.1/configure --target=arm-none-eabi --prefix=/work/tools/arm --enable-interwork --enable-multilib 60 | make 61 | make install 62 | cd .. 63 | rm -rf build/* 64 | 65 | -------------------------------------------------------------------------------- /docs/memory-barriers.txt: -------------------------------------------------------------------------------- 1 | 2 | http://infocenter.arm.com/help/topic/com.arm.doc.genc007826/Barrier_Litmus_Tests_and_Cookbook_A08.pdf 3 | 4 | ----- 5 | 6 | http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka14041.html 7 | states: 8 | 9 | It is architecturally defined that software must perform a Data Memory 10 | Barrier (DMB) operation: 11 | - between acquiring a resource, for example, through locking a mutex 12 | (MUTual EXclusion) or decrementing a semaphore, and making any access 13 | to that resource 14 | - before making a resource available, for example, through unlocking a 15 | mutex or incrementing a semaphore. 16 | 17 | ----- 18 | 19 | To generate a scheduling barrier: 20 | asm volatile ("" : : : "memory"); 21 | 22 | To generate a hardware memory barrier: 23 | __sync_synchronize(); 24 | 25 | This appears to issue a "dmb sy" on cortex-m3 in arm-eabi-none 26 | 27 | 28 | Based on these excerpts from a gcc-help thread. References: 29 | http://gcc.gnu.org/ml/gcc-help/2011-04/msg00166.html 30 | http://gcc.gnu.org/ml/gcc-help/2011-04/msg00168.html 31 | http://gcc.gnu.org/ml/gcc-help/2011-04/msg00180.html 32 | 33 | From: Ian Lance Taylor 34 | Date: Mon, 11 Apr 2011 14:42:07 -0700 35 | Subject: Re: full memory barrier? 36 | 37 | Hei Chan writes: 38 | 39 | > I am a little bit confused what asm volatile ("" : : : "memory") does. 40 | > 41 | > I searched online; many people said that it creates the "full memory barrier". 42 | > 43 | > I have a test code: 44 | > int main() { 45 | > bool bar; 46 | > asm volatile ("" : : : "memory"); 47 | > bar = true; 48 | > return 1; 49 | > } 50 | > 51 | > Running g++ -c -g -Wa,-a,-ad foo.cpp gives me: 52 | > 53 | > 2:foo.cpp **** bool bar; 54 | > 3:foo.cpp **** asm volatile ("" : : : "memory"); 55 | > 22 .loc 1 3 0 56 | > 4:foo.cpp **** bar = true; 57 | > 23 .loc 1 4 0 58 | > 59 | > It doesn't involve any fence instruction. 60 | > 61 | > Maybe I completely misunderstand the idea of "full memory barrier". 62 | 63 | The definition of "memory barrier" is ambiguous when looking at code 64 | written in a high-level language. 65 | 66 | The statement "asm volatile ("" : : : "memory");" is a compiler 67 | scheduling barrier for all expressions that load from or store values to 68 | memory. That means something like a pointer dereference, an array 69 | index, or an access to a volatile variable. It may or may not include a 70 | reference to a local variable, as a local variable need not be in 71 | memory. 72 | 73 | This kind of compiler scheduling barrier can be used in conjunction with 74 | a hardware memory barrier. The compiler doesn't know that a hardware 75 | memory barrier is special, and it will happily move memory access 76 | instructions across the hardware barrier. Therefore, if you want to use 77 | a hardware memory barrier in compiled code, you must use it along with a 78 | compiler scheduling barrier. 79 | 80 | On the other hand a compiler scheduling barrier can be useful even 81 | without a hardware memory barrier. For example, in a coroutine based 82 | system with multiple light-weight threads running on a single processor, 83 | you need a compiler scheduling barrier, but you do not need a hardware 84 | memory barrier. 85 | 86 | gcc will generate a hardware memory barrier if you use the 87 | __sync_synchronize builtin function. That function acts as both a 88 | hardware memory barrier and a compiler scheduling barrier. 89 | 90 | Ian 91 | 92 | ----- 93 | 94 | From: Ian Lance Taylor 95 | Date: Mon, 11 Apr 2011 15:20:27 -0700 96 | Subject: Re: full memory barrier? 97 | 98 | Hei Chan writes: 99 | 100 | > You mentioned the statement "is a compiler scheduling barrier for all 101 | > expressions that load from or store values to memory". Does "memory" mean the 102 | > main memory? Or does it include the CPU cache? 103 | 104 | I tried to explain what I meant by way of example. It means pointer 105 | reference, array reference, volatile variable access. Also I should 106 | have added global variable access. In general it means memory from the 107 | point of view of the compiler. The compiler doesn't know anything about 108 | the CPU cache. When thinking about a "compiler scheduling barrier," you 109 | have to think about the world that the compiler sees, which is quite 110 | different from, though obviously related to, the world that the hardware 111 | sees. 112 | 113 | Ian 114 | 115 | ----- 116 | 117 | From: Ian Lance Taylor 118 | Date: Tue, 12 Apr 2011 15:36:58 -0700 119 | Subject: Re: full memory barrier? 120 | 121 | David Brown writes: 122 | 123 | > On 11/04/2011 23:42, Ian Lance Taylor wrote: 124 | >> 125 | >> The definition of "memory barrier" is ambiguous when looking at code 126 | >> written in a high-level language. 127 | >> 128 | >> The statement "asm volatile ("" : : : "memory");" is a compiler 129 | >> scheduling barrier for all expressions that load from or store values to 130 | >> memory. That means something like a pointer dereference, an array 131 | >> index, or an access to a volatile variable. It may or may not include a 132 | >> reference to a local variable, as a local variable need not be in 133 | >> memory. 134 | >> 135 | > 136 | > Is there any precise specifications for what counts as "memory" here? 137 | > As gcc gets steadily smarter, it gets harder to be sure that 138 | > order-specific code really is correctly ordered, while letting the 139 | > compiler do it's magic on the rest of the code. 140 | 141 | I'm not aware of a precise specification. It would be something like 142 | the list I made above, to which I would add global variables. But 143 | you're right, as the compiler gets smarter, it is increasingly able to 144 | lift things out of memory. I suppose that in the extreme case, it's 145 | possible that only volatile variables count. 146 | 147 | 148 | > For example, if you have code like this: 149 | > 150 | > static int x; 151 | > void test(void) { 152 | > x = 1; 153 | > asm volatile ("" : : : "memory"); 154 | > x = 2; 155 | > } 156 | > 157 | > The variable "x" is not volatile - can the compiler remove the 158 | > assignment "x = 1"? Perhaps with aggressive optimisation, the 159 | > compiler will figure out how and when x is used, and discover that it 160 | > doesn't need to store it in memory at all, but can keep it in a 161 | > register (perhaps all uses have ended up inlined inside the same 162 | > function). Then "x" is no longer in memory - will it still be 163 | > affected by the memory clobber? 164 | 165 | If the compiler manages to lift x into a register, then it will not be 166 | affected by the memory clobber, and, yes, the compiler would most likely 167 | remove the assignment "x = 1". 168 | 169 | 170 | > Also, is there any way to specify a more limited clobber than just 171 | > "memory", so that the compiler has as much freedom as possible? 172 | > Typical examples are to specify "clobbers" for just certain variables, 173 | > leaving others unaffected, or to distinguish between reads and writes. 174 | > For example, you might want to say "all writes should be completed by 175 | > this point, but data read into registers will stay valid". 176 | > 177 | > Some of this can be done with volatile accesses in different ways, but 178 | > not always optimally, and not always clearly. 179 | 180 | You can clobber certain variables by listing them in the output of the 181 | asm statement. There is no way to distinguish between reads and writes. 182 | 183 | Ian 184 | 185 | 186 | -------------------------------------------------------------------------------- /docs/notes.txt: -------------------------------------------------------------------------------- 1 | Cortex M3 2 | --------- 3 | - All M3 vectors are interwork style and MUST have the low bit set. 4 | Failure to do so will result in hardfaults on reset, etc. 5 | 6 | - You can start debugging from reset by asserting RESET, writing 1 to 7 | E000EDFC, then releasing RESET 8 | 9 | Linux Generic Serial Driver 10 | --------------------------- 11 | - class/subclass/protocol 0xff,0x00,0x00 (device and interface) 12 | - 1 interface, 1 bulk in, 1 bulk out 13 | - must modprobe usbserial vendor=0x0525 product=0xA4A6 14 | - must rmmod usbserial before modprobing it if it was previously loaded 15 | - publishes as /dev/ttyUSBx 16 | 17 | STM32F1xx 18 | --------- 19 | - clock config at boot: 20 | - HSI (internal 8MHz osc) is on and ready 21 | - SYSCLK = HSI (8MHz) 22 | - AHB = SYSCLK / 1 23 | - PCLK1 = HCLK / 1 24 | - PCLK2 = HCLK / 1 25 | - ADCCLK = PCLK2 / 2 (4MHz) 26 | 27 | LPC1343 28 | ------- 29 | - how to trap just before the bootloader jumps to user flash 30 | reset-stop 31 | watch-rw 0 32 | go 33 | 34 | gdb 35 | --- 36 | making the disassembler behave: 37 | set architecture armv4m 38 | set arm fallback-mode thumb 39 | 40 | connecting/disconnecting: 41 | target remote | out/gdb-bridge 42 | disconnect 43 | 44 | turn on tracing for the remote wire protocol 45 | set debug remote 1 46 | 47 | disassemble 4 instructions at pc 48 | x/4i $pc 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/todo.txt: -------------------------------------------------------------------------------- 1 | 2 | - debugger 3 | - more script work (integration of erase/flash scripts, etc) 4 | - flash support for stm32 parts 5 | - async/background usb io (to allow for serial trace, ITM trace, etc) 6 | - quieter script execution mode 7 | 8 | - m3debug 9 | - do some more useful stuff with LEDs 10 | - ITM support 11 | - serial debug support (feed serial down through usb) 12 | 13 | - swdp 14 | - fold things together with m3debug 15 | 16 | - lpc13boot 17 | - reset to a more like-POR state before jumping to app 18 | - provide a 'R'eboot protocol command 19 | - ability to reflash the bootloader (maybe w/ some sanity check?) 20 | 21 | - lpc13xx 22 | - clean up library code, more #defines, fewer magic numbers 23 | - real baud selection code in serial_init() 24 | 25 | - stm32f 26 | - usb feature parity 27 | 28 | - build system 29 | - easy way to build app variants for multiple boards 30 | (m3debug for m3debug, maple, etc) 31 | 32 | - arm m3 33 | - get interrupts, threads, etc going 34 | -------------------------------------------------------------------------------- /docs/usb-protocols.txt: -------------------------------------------------------------------------------- 1 | 2 | 18d1:db00 - lpcboot / m3boot 3 | ---------------------------- 4 | - provides a pair of USB bulk endpoints, IN and OUT 5 | - write a three word (32b-LE) command sequence ( MAGIC, CMD, ARG) 6 | - MAGIC is 0xDB00A5A5 7 | - see below for CMD 8 | - ARG should be zero if not specified 9 | - read a two word (32b-LE) response ( MAGIC, STATUS) 10 | - MAGIC is 0xDB00A5A5 11 | - nonzero STATUS is failure 12 | - read or write payload, as required 13 | 14 | - commands 15 | - write to flash: CMD='W', ARG=size 16 | - write to RAM (and execute): CMD='X', ARG=size 17 | - erase flash: CMD='E' 18 | - reboot: CMD='R' 19 | - start code in flash: CMD='A' 20 | - query device info: CMD='Q' 21 | 22 | struct device_info { 23 | char part[16]; /* "LPC1343", "STM32F103", etc */ 24 | char board[16]; /* "M3DEBUG", "TESTBOARD123", etc */ 25 | uint32_t version; /* protocol version: 0x0001000 -> V1.0 */ 26 | uint32_t ram_base; /* start of SRAM */ 27 | uint32_t ram_size; /* length of SRAM (minus 1K bootloader workspace) */ 28 | uint32_t rom_base; /* start of FLASH (after 4K bootloader) */ 29 | uint32_t rom_size; /* length of FLASH (minus 4K bootloader) 30 | uint32_t ununsed0; 31 | uint32_t ununsed1; 32 | uint32_t ununsed2; 33 | }; 34 | 35 | 36 | 18d1:db03 - remote swdp 37 | ----------------------- 38 | - provides a pair of USB bulk endpoints, IN and OUT 39 | - see include/protocol/rswdp.h for details 40 | 41 | 18d1:db05 - usb console 42 | ----------------------- 43 | - provides a pair of USB bulk endpoints, IN and OUT 44 | - console output (device to host) provided via BULK IN 45 | - console input (host to device) provided via BULK OUT (format TBD) 46 | 47 | 18d1:db04 - remote swdp + console 48 | --------------------------------- 49 | - interface 0 provides remote swdp 50 | - interface 1 provides usb console 51 | 52 | -------------------------------------------------------------------------------- /firmware/README: -------------------------------------------------------------------------------- 1 | Before you start 2 | ---------------- 3 | 4 | You'll need to build the lpcboot and debugger tools by running make at 5 | the top level first. 6 | 7 | On Linux you may need to install docs/99-mdebug.rules in /etc/udev/rules.d 8 | in order to have access to the debugger firmware and bootloader firmware 9 | without being root. This rules file allows group plugdev access, which 10 | covers users logged in on console (at least on Ubuntu) 11 | 12 | 13 | Installing lpcboot and mdebug on the LPC Link 2 board (first time) 14 | ------------------------------------------------------------------ 15 | 16 | 1. Remove jumper JP1 from lpclink2 17 | 18 | 2. Connect lpclink2 to USB 19 | 20 | 3. Download the "soft" bootloader via DFU 21 | (it is normal to get "dfu status: io error") 22 | $ ./bin/lpcboot dfu firmware/lpclink2-dfu.bin 23 | 24 | 4. flash bootloader: 25 | $ ./bin/lpcboot flash:boot firmware/lpclink2-boot.bin 26 | 27 | 5. flash mdebug firmware: 28 | $ ./bin/lpcboot flash firmware/lpclink2-mdebug.bin 29 | 30 | 6. install jumper JP1 on lpclink2 31 | 32 | 7. reboot the lpclink2: 33 | $ ./bin/lpcboot reboot 34 | 35 | 8. LED should blink for ~3 seconds (bootloader) then start mdebug 36 | 37 | 38 | Upgrading mdebug firmware on the LPC Link 2 board (after initial install) 39 | ------------------------------------------------------------------------- 40 | 41 | 1. disconnect lpclink2 from USB 42 | 43 | 2. $ ./bin/lpcboot flash firmware/lpclink2-mdebug.bin 44 | 45 | 3. connect lpclink2 to USB 46 | 47 | 4. If you get "flash failure", run the step #2 command again 48 | (without disconnecting and reconnecting the board) 49 | 50 | 5. reboot back into the debugger firmware 51 | $ ./bin/lpcboot reboot 52 | 53 | 54 | Checking firmware version (debugger should show this on connect) 55 | ---------------------------------------------------------------- 56 | 57 | usb: board id: LPCLINK2 58 | usb: build id: fw v0.91 (Jan 11 2016, 15:43:28) 59 | usb: protocol: 1.2 60 | usb: max data: 8192 byte rx buffer 61 | 62 | 63 | Connecting LPC Link 2 to debug target 64 | ------------------------------------- 65 | 66 | You can use the 10pin cable with the J7 connector to hook up to a target 67 | board that uses ARM's standard SWD debug pinout. If you want to supply 68 | 3.3v to the target and operate at that voltage, *install* the JP2 jumper. 69 | If you want to operate at the board voltage sensed by the VREF pin on the 70 | 10pin connector, *remote* the JP2 connector. 71 | 72 | You can use jumper wires from the 0.1" J6 header (see pinout below), but 73 | in this case there is no VREF pin available, so you must *install* the 74 | JP2 jumper and operate at 3.3v. 75 | 76 | 77 | J6 Header (pin 1 is furthest from J6 silkscreen) 78 | ------------------------------------------------ 79 | 1. 3V3 80 | 2. SWDIO 81 | 3. SWCLK 82 | 4. SWO 83 | 5. 84 | 6. 85 | 7. 86 | 8. GND 87 | 9. 88 | 89 | -------------------------------------------------------------------------------- /firmware/lpclink2-boot.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swetland/mdebug/449406f1147fbe37b1b2f109d4b9e63f9ea84101/firmware/lpclink2-boot.bin -------------------------------------------------------------------------------- /firmware/lpclink2-dfu.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swetland/mdebug/449406f1147fbe37b1b2f109d4b9e63f9ea84101/firmware/lpclink2-dfu.bin -------------------------------------------------------------------------------- /firmware/lpclink2-mdebug.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swetland/mdebug/449406f1147fbe37b1b2f109d4b9e63f9ea84101/firmware/lpclink2-mdebug.bin -------------------------------------------------------------------------------- /include/agent/flash.h: -------------------------------------------------------------------------------- 1 | // agent/flash.h 2 | // 3 | // Copyright 2015 Brian Swetland 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #ifndef _AGENT_FLASH_H_ 18 | #define _AGENT_FLASH_H_ 19 | 20 | typedef unsigned int u32; 21 | 22 | #define AGENT_MAGIC 0x42776166 23 | #define AGENT_VERSION 0x00010000 24 | 25 | typedef struct flash_agent { 26 | u32 magic; 27 | u32 version; 28 | u32 flags; 29 | u32 load_addr; 30 | 31 | u32 data_addr; 32 | u32 data_size; // bytes 33 | u32 flash_addr; 34 | u32 flash_size; // bytes 35 | 36 | u32 reserved0; 37 | u32 reserved1; 38 | u32 reserved2; 39 | u32 reserved3; 40 | 41 | #ifdef _AGENT_HOST_ 42 | u32 setup; 43 | u32 erase; 44 | u32 write; 45 | u32 ioctl; 46 | #else 47 | int (*setup)(struct flash_agent *agent); 48 | int (*erase)(u32 flash_addr, u32 length); 49 | int (*write)(u32 flash_addr, const void *data, u32 length); 50 | int (*ioctl)(u32 op, void *ptr, u32 arg0, u32 arg1); 51 | #endif 52 | } flash_agent; 53 | 54 | #ifndef _AGENT_HOST_ 55 | int flash_agent_setup(flash_agent *agent); 56 | int flash_agent_erase(u32 flash_addr, u32 length); 57 | int flash_agent_write(u32 flash_addr, const void *data, u32 length); 58 | int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1); 59 | #endif 60 | 61 | #define ERR_NONE 0 62 | #define ERR_FAIL -1 63 | #define ERR_INVALID -2 64 | #define ERR_ALIGNMENT -3 65 | 66 | #define FLAG_WSZ_256B 0x00000100 67 | #define FLAG_WSZ_512B 0x00000200 68 | #define FLAG_WSZ_1K 0x00000400 69 | #define FLAG_WSZ_2K 0x00000800 70 | #define FLAG_WSZ_4K 0x00001000 71 | // optional hints as to underlying write block sizes 72 | 73 | #define FLAG_BOOT_ROM_HACK 0x00000001 74 | // Allow a boot ROM to run after RESET by setting a watchpoint 75 | // at 0 and running until the watchpoint is hit. Necessary on 76 | // some parts which require boot ROM initialization of Flash 77 | // timing registers, etc. 78 | 79 | 80 | // Flash agent binaries will be downloaded to device memory at 81 | // fa.load_addr. The memory below this address will be used as 82 | // the stack for method calls. It should be sized appropriately. 83 | // 84 | // The fa.magic field will be replaced with 0xbe00be00 (two 85 | // Thumb BKPT instructions) before download to device. 86 | // 87 | // Calling convention for flash_agent methods: 88 | // 1. SP will be set to fa.load_addr - 4 89 | // 2. LR will be set to fa.load_addr 90 | // 3. PC will be set to the method address 91 | // 4. R0..R3 will be loaded with method arguments 92 | // 5. Processor will be resumed (in Privileged Thread mode) 93 | // 6. Upon processor entry to debug mode 94 | // a. if PC == fa.base_addr, status read from R0 95 | // b. else status = fatal error 96 | 97 | 98 | // setup() must be invoked after processor reset and before any 99 | // other methods are invoked. The fields data_addr, data_size, 100 | // flash_addr, and flash_size are read back after this method 101 | // returns success (to allow it to dynamically size flash based 102 | // on part ID, etc). 103 | // - ERR_INVALID indicates an unsupported part 104 | 105 | // fa.data_size must be a multiple of the minimum block size that 106 | // fa.write requires, so that if the host has to issue a series 107 | // of fa.write calls to do a larger-than-data-buffer-sized flash write, 108 | // subsequent write calls will have appropriate alignment. 109 | // 110 | // fa.write() may round writes up the the minimum write block size 111 | // as necessary, and should fill with 0s in that case.* 112 | // 113 | // fa.write() behaviour is undefined if the underlying flash has not 114 | // been erased first. It may fail (ERR_FAIL) or it may appear to 115 | // succeed, but flash contents may be incorrect. 116 | // 117 | // fa.write() may fail (ERR_ALIGN) if the start address is not aligned 118 | // with a flash page or block.* 119 | // 120 | // fa.erase() may round up to the next erasure block size if necessary 121 | // to ensure the requested region is erased.* 122 | // 123 | // fa.erase(fa.flash_addr, fa.flash_size) should cause a full erase if 124 | // possible. 125 | // 126 | // fa.ioctl() must return ERR_INVALID if op is unsupported. 127 | // Currently no ops are defined, but OTP/EEPROM/Config bits are 128 | // planned to be managed with ioctls. 129 | // 130 | // Bogus parameters may cause failure (ERR_INVALID) 131 | // 132 | // * In general, conveying the full complexity of embedded flash 133 | // configuration (which could include various banks of various sizes, 134 | // with differing write and erase block size requirements) is not 135 | // attempted. The goal is to provide an agent that can reasonably 136 | // handle reasonable flash requests (eg the user knows what a sane 137 | // starting alignment, etc is, does not split logical "partitions" 138 | // across physical erase block boundaries, etc) 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /include/fw/io.h: -------------------------------------------------------------------------------- 1 | /* io.h */ 2 | 3 | #ifndef _IO_H_ 4 | #define _IO_H_ 5 | 6 | #define readb(a) (*((volatile unsigned char *) (a))) 7 | #define writeb(v, a) (*((volatile unsigned char *) (a)) = (v)) 8 | 9 | #define readw(a) (*((volatile unsigned short *) (a))) 10 | #define writew(v, a) (*((volatile unsigned short *) (a)) = (v)) 11 | 12 | #define readl(a) (*((volatile unsigned int *) (a))) 13 | #define writel(v, a) (*((volatile unsigned int *) (a)) = (v)) 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/fw/types.h: -------------------------------------------------------------------------------- 1 | /* types.h */ 2 | 3 | #ifndef _FW_TYPES_H_ 4 | #define _FW_TYPES_H_ 5 | 6 | typedef unsigned long int u64; 7 | typedef signed long int i64; 8 | typedef unsigned int u32; 9 | typedef signed int i32; 10 | typedef unsigned short u16; 11 | typedef signed short i16; 12 | typedef unsigned char u8; 13 | typedef signed char i8; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/protocol/rswdp.h: -------------------------------------------------------------------------------- 1 | /* rswdp.h - remote serial wire debug protocol 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* Remote Serial Wire Debug Protocol */ 19 | 20 | #ifndef _RSWDP_PROTOCOL_H_ 21 | #define _RSWDP_PROTOCOL_H_ 22 | 23 | /* Basic framing: 24 | * - host and device exchange "transactions" consisting of 25 | * some number of "messages". 26 | * - each "message" has a 32bit header and may have 0 or more 27 | * 32bit words of payload 28 | * - a transaction may not exceed 4K (1024 words) 29 | * - a transaction is sent in a series of USB BULK packets 30 | * - the final packet must be a short packet unless the 31 | * transaction is exactly 4K in length 32 | * - packets must be a multiple of 4 bytes 33 | * - the first message in a transaction must be 34 | * CMD_TXN_START or CMD_TXN_ASYNC 35 | */ 36 | 37 | #define RSWD_MSG(cmd,op,n) ((((cmd)&0xFF) << 24) | (((op) & 0xFF)<<16) | ((n) & 0xFFFF)) 38 | #define RSWD_MSG_CMD(n) (((n) >> 24) & 0xFF) 39 | #define RSWD_MSG_OP(n) (((n) >> 16) & 0xFF) 40 | #define RSWD_MSG_ARG(n) ((n) & 0xFFFF) 41 | 42 | #define RSWD_TXN_START(seq) (0xAA770000 | ((seq) & 0xFFFF)) 43 | #define RSWD_TXN_ASYNC (0xAA001111) 44 | 45 | /* valid: either */ 46 | #define CMD_NULL 0x00 /* used for padding */ 47 | 48 | /* valid: host to target */ 49 | #define CMD_SWD_WRITE 0x01 /* op=addr arg=count payload: data x count */ 50 | #define CMD_SWD_READ 0x02 /* op=addr arg=count payload: data x count */ 51 | #define CMD_SWD_DISCARD 0x03 /* op=addr arg=count payload: none (discards) */ 52 | #define CMD_ATTACH 0x04 /* do swdp reset/connect handshake */ 53 | #define CMD_RESET 0x05 /* arg=1 -> assert RESETn, otherwise deassert */ 54 | #define CMD_DOWNLOAD 0x06 /* arg=wordcount, payload: addr x 1, data x n */ 55 | #define CMD_EXECUTE 0x07 /* payload: addr x 1 */ 56 | #define CMD_TRACE 0x08 /* op=tracebits n=0 */ 57 | #define CMD_BOOTLOADER 0x09 /* return to bootloader for reflashing */ 58 | #define CMD_SET_CLOCK 0x0A /* set SWCLK rate to n khz */ 59 | #define CMD_SWO_CLOCK 0x0B /* set SWOCLK rate to n khz, 0 = disable SWO */ 60 | #define CMD_JTAG_IO 0x0C /* op=0, arg=bitcount, data x (count/32) * 2 */ 61 | /* tms, tdi word pairs per 32bits */ 62 | 63 | /* ATTACH ops */ 64 | #define ATTACH_SWD_RESET 0 65 | #define ATTACH_JTAG_TO_SWD 1 66 | #define ATTACH_DORMANT_TO_SWD 2 67 | #define ATTACH_SWD_TO_DORMANT 3 68 | 69 | /* valid: target to host */ 70 | #define CMD_STATUS 0x10 /* op=errorcode, arg=commands since last TXN_START */ 71 | #define CMD_SWD_DATA 0x11 /* op=0 arg=count, payload: data x count */ 72 | #define CMD_SWO_DATA 0x12 /* op=0 arg=count, payload: ((count+3)/4) words */ 73 | #define CMD_JTAG_DATA 0x14 /* op=0 arg=bitcount, payload: (bitcount/32) words */ 74 | 75 | /* valid: target to host async */ 76 | #define CMD_DEBUG_PRINT 0x20 /* arg*4 bytes of ascii debug output */ 77 | 78 | /* valid: bidirectional query/config messages */ 79 | #define CMD_VERSION 0x30 /* arg=bcdversion (0x0100 etc) */ 80 | #define CMD_BUILD_STR 0x31 /* arg=wordcount, payload = asciiz */ 81 | #define CMD_BOARD_STR 0x32 /* arg=wordcount, payload = asciiz */ 82 | #define CMD_RX_MAXDATA 0x33 /* arg=bytes, declares senders rx buffer size */ 83 | #define CMD_CLOCK_KHZ 0x34 /* arg=khz, reports active clock rate */ 84 | 85 | /* CMD_STATUS error codes */ 86 | #define ERR_NONE 0 87 | #define ERR_INTERNAL 1 88 | #define ERR_TIMEOUT 2 89 | #define ERR_IO 3 90 | #define ERR_PARITY 4 91 | 92 | #define RSWD_VERSION 0x0101 93 | 94 | #define RSWD_VERSION_1_0 0x0100 95 | #define RSWD_VERSION_1_1 0x0101 96 | 97 | // Pre-1.0 98 | // - max packet size fixed at 2048 bytes 99 | // 100 | // Version 1.0 101 | // - CMD_VERSION, CMD_BUILD_STR, CMD_BOARD_STR, CMD_RX_MAXDATA, 102 | // CMD_CLOCK_KHZ added 103 | // 104 | // Version 1.1 105 | // - CMD_SWO_DATA arg is now byte count, not word count 106 | 107 | /* CMD_SWD_OP operations - combine for direct AP/DP io */ 108 | #define OP_RD 0x00 109 | #define OP_WR 0x01 110 | #define OP_DP 0x00 111 | #define OP_AP 0x02 112 | #define OP_X0 0x00 113 | #define OP_X4 0x04 114 | #define OP_X8 0x08 115 | #define OP_XC 0x0C 116 | 117 | /* DP registers */ 118 | #define DP_IDCODE (OP_DP|OP_X0) 119 | #define DP_ABORT (OP_DP|OP_X0) 120 | #define DP_DPCTRL (OP_DP|OP_X4) 121 | #define DP_RESEND (OP_DP|OP_X8) 122 | #define DP_SELECT (OP_DP|OP_X8) 123 | #define DP_BUFFER (OP_DP|OP_XC) 124 | 125 | /* AHB AP registers */ 126 | #define AHB_CSW 0x00 127 | #define AHB_TAR 0x04 128 | #define AHB_DRW 0x0C 129 | #define AHB_BD0 0x10 130 | #define AHB_BD1 0x14 131 | #define AHB_BD2 0x18 132 | #define AHB_BD3 0x20 133 | #define AHB_ROM_ADDR 0xF8 134 | #define AHB_IDR 0xFC 135 | 136 | #define AHB_CSW_MCORE (0 << 29) 137 | #define AHB_CSW_MDEBUG (1 << 29) 138 | #define AHB_CSW_USER (0 << 25) 139 | #define AHB_CSW_PRIV (1 << 25) 140 | #define AHB_CSW_DBG_EN (1 << 6) 141 | #define AHB_CSW_INC_NONE (0 << 4) 142 | #define AHB_CSW_INC_SINGLE (1 << 4) 143 | #define AHB_CSWINC_PACKED (2 << 4) 144 | #define AHB_CSW_8BIT (0 << 0) 145 | #define AHB_CSW_16BIT (1 << 0) 146 | #define AHB_CSW_32BIT (2 << 0) 147 | 148 | /* Core Debug registers */ 149 | #define CDBG_CSR 0xE000EDF0 150 | #define CDBG_REG_ADDR 0xE000EDF4 151 | #define CDBG_REG_DATA 0xE000EDF8 152 | #define CDBG_EMCR 0xE000EDFC 153 | 154 | #define CDBG_CSR_KEY 0xA05F0000 155 | #define CDBG_S_RESET_ST (1 << 25) 156 | #define CDBG_S_RETIRE_ST (1 << 24) 157 | #define CDBG_S_LOCKUP (1 << 19) 158 | #define CDBG_S_SLEEP (1 << 18) 159 | #define CDBG_S_HALT (1 << 17) 160 | #define CDBG_S_REGRDY (1 << 16) 161 | #define CDBG_C_SNAPSTALL (1 << 5) 162 | #define CDBG_C_MASKINTS (1 << 3) 163 | #define CDBG_C_STEP (1 << 2) 164 | #define CDBG_C_HALT (1 << 1) 165 | #define CDBG_C_DEBUGEN (1 << 0) 166 | 167 | #define IDCODE_M3 0x1BA01477 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /tools/arm-m-debug.c: -------------------------------------------------------------------------------- 1 | /* arm-m-debug 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include "debugger.h" 23 | #include "rswdp.h" 24 | 25 | #include "arm-v7m.h" 26 | 27 | // CDBG_* comes from here right now -- FIXME 28 | #include 29 | 30 | static volatile int ATTN; 31 | 32 | void swdp_interrupt(void) { 33 | ATTN++; 34 | if (write(2, "\b\b*INTERRUPT*\n", 16)) { /* do nothing */ } 35 | } 36 | 37 | 38 | int swdp_core_write(u32 n, u32 v) { 39 | if (mem_wr_32(CDBG_REG_DATA, v)) { 40 | return -1; 41 | } 42 | if (mem_wr_32(CDBG_REG_ADDR, (n & 0x1F) | 0x10000)) { 43 | return -1; 44 | } 45 | return 0; 46 | } 47 | 48 | int swdp_core_read(u32 n, u32 *v) { 49 | if (mem_wr_32(CDBG_REG_ADDR, n & 0x1F)) { 50 | return -1; 51 | } 52 | if (mem_rd_32(CDBG_REG_DATA, v)) { 53 | return -1; 54 | } 55 | return 0; 56 | } 57 | 58 | int swdp_core_read_all(u32 *v) { 59 | unsigned n; 60 | for (n = 0; n < 19; n++) { 61 | if (mem_wr_32(CDBG_REG_ADDR, n & 0x1F)) { 62 | return -1; 63 | } 64 | if (mem_rd_32(CDBG_REG_DATA, v++)) { 65 | return -1; 66 | } 67 | } 68 | return 0; 69 | } 70 | 71 | int swdp_step_no_ints = 0; 72 | 73 | int swdp_core_halt(void) { 74 | u32 x; 75 | if (mem_rd_32(CDBG_CSR, &x)) return -1; 76 | x &= (CDBG_C_HALT | CDBG_C_DEBUGEN | CDBG_C_MASKINTS); 77 | x |= CDBG_CSR_KEY | CDBG_C_DEBUGEN | CDBG_C_HALT; 78 | return mem_wr_32(CDBG_CSR, x); 79 | } 80 | 81 | int swdp_core_step(void) { 82 | u32 x; 83 | if (mem_rd_32(CDBG_CSR, &x)) return -1; 84 | x &= (CDBG_C_HALT | CDBG_C_DEBUGEN | CDBG_C_MASKINTS); 85 | x |= CDBG_CSR_KEY; 86 | 87 | if (!(x & CDBG_C_HALT)) { 88 | // HALT if we're not already HALTED 89 | x |= CDBG_C_HALT | CDBG_C_DEBUGEN; 90 | mem_wr_32(CDBG_CSR, x); 91 | } 92 | if (swdp_step_no_ints) { 93 | // set MASKINTS if not already set 94 | if (!(x & CDBG_C_MASKINTS)) { 95 | x |= CDBG_C_MASKINTS; 96 | mem_wr_32(CDBG_CSR, x); 97 | } 98 | } else { 99 | // clear MASKINTs if not already clear 100 | if (x & CDBG_C_MASKINTS) { 101 | x &= (~CDBG_C_MASKINTS); 102 | mem_wr_32(CDBG_CSR, x); 103 | } 104 | } 105 | // STEP 106 | x &= (~CDBG_C_HALT); 107 | return mem_wr_32(CDBG_CSR, x | CDBG_C_STEP); 108 | } 109 | 110 | int swdp_core_resume(void) { 111 | u32 x; 112 | if (mem_rd_32(CDBG_CSR, &x)) return -1; 113 | x &= (CDBG_C_HALT | CDBG_C_DEBUGEN | CDBG_C_MASKINTS); 114 | x |= CDBG_CSR_KEY | CDBG_C_DEBUGEN; 115 | 116 | if (swdp_step_no_ints > 1) { 117 | // not just on during step, but always 118 | if (!(x & CDBG_C_MASKINTS)) { 119 | x |= CDBG_C_MASKINTS; 120 | mem_wr_32(CDBG_CSR, x); 121 | } 122 | } else { 123 | if (x & CDBG_C_MASKINTS) { 124 | x &= (~CDBG_C_MASKINTS); 125 | mem_wr_32(CDBG_CSR, x); 126 | } 127 | } 128 | 129 | x &= ~(CDBG_C_HALT | CDBG_C_STEP); 130 | return mem_wr_32(CDBG_CSR, x); 131 | } 132 | 133 | int swdp_core_wait_for_halt(void) { 134 | int last = ATTN; 135 | u32 csr; 136 | for (;;) { 137 | if (mem_rd_32(CDBG_CSR, &csr)) 138 | return -1; 139 | if (csr & CDBG_S_HALT) 140 | return 0; 141 | if (ATTN != last) 142 | return -2; 143 | } 144 | } 145 | 146 | int swdp_ahb_wait_for_change(u32 addr, u32 oldval) { 147 | int last = ATTN; 148 | u32 val; 149 | do { 150 | if (mem_rd_32(addr, &val)) 151 | return -1; 152 | if (ATTN != last) 153 | return -2; 154 | } while (val == oldval); 155 | return 0; 156 | } 157 | 158 | int swdp_watchpoint(unsigned n, u32 addr, u32 func) { 159 | int r; 160 | if (n > 3) 161 | return -1; 162 | 163 | /* enable DWT, enable all exception traps */ 164 | r = mem_wr_32(DEMCR, DEMCR_TRCENA | DEMCR_VC_CORERESET); 165 | r |= mem_wr_32(DWT_FUNC(n), DWT_FN_DISABLED); 166 | if (func != DWT_FN_DISABLED) { 167 | r |= mem_wr_32(DWT_COMP(n), addr); 168 | r |= mem_wr_32(DWT_MASK(n), 0); 169 | r |= mem_wr_32(DWT_FUNC(n), func); 170 | } 171 | return r; 172 | } 173 | 174 | int swdp_watchpoint_pc(unsigned n, u32 addr) { 175 | return swdp_watchpoint(n, addr, DWT_FN_WATCH_PC); 176 | } 177 | 178 | int swdp_watchpoint_rd(unsigned n, u32 addr) { 179 | return swdp_watchpoint(n, addr, DWT_FN_WATCH_RD); 180 | } 181 | 182 | int swdp_watchpoint_wr(unsigned n, u32 addr) { 183 | return swdp_watchpoint(n, addr, DWT_FN_WATCH_WR); 184 | } 185 | 186 | int swdp_watchpoint_rw(unsigned n, u32 addr) { 187 | return swdp_watchpoint(n, addr, DWT_FN_WATCH_RW); 188 | } 189 | 190 | int swdp_watchpoint_disable(unsigned n) { 191 | return swdp_watchpoint(n, 0, DWT_FN_DISABLED); 192 | } 193 | 194 | -------------------------------------------------------------------------------- /tools/arm-v7m.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARM_V7M_H_ 2 | #define _ARM_V7M_H_ 3 | 4 | // ---- debug registers ----------------- 5 | #define DHCSR 0xE000EDF0 // Debug Halting Ctrl/Stat 6 | #define DCRSR 0xE000EDF4 // Debug Core Reg Select 7 | #define DCRDR 0xE000EDF8 // Debug Core Reg Data 8 | #define DEMCR 0xE000EDFC // Debug Exception & Monitor Ctrl 9 | 10 | #define DHCSR_DBGKEY 0xA05F0000 11 | #define DHCSR_S_RESET_ST (1 << 25) // CPU Reset Since Last Read (CoR) 12 | #define DHCSR_S_RETIRE_ST (1 << 24) // Inst Retired Since Last Read (CoR) 13 | #define DHCSR_S_LOCKUP (1 << 19) // CPU is locked up / unrecov excpt 14 | #define DHCSR_S_SLEEP (1 << 18) // CPU is Sleeping 15 | #define DHCSR_S_HALT (1 << 17) // CPU is Halted 16 | #define DHCSR_S_REGRDY (1 << 16) // 0:DCRSR Written 1:DCRSR TXN Done 17 | #define DHCSR_C_SNAPSTALL (1 << 5) // Allow Imprecise Debug Entry 18 | #define DHCSR_C_MASKINTS (1 << 3) // Mask PendSV, SysTick, and Ext IRQs 19 | // C_HALT must already be and remain 1 20 | #define DHCSR_C_STEP (1 << 2) // Enable Single Step 21 | #define DHCSR_C_HALT (1 << 1) // Halt CPU 22 | #define DHCSR_C_DEBUGEN (1 << 0) // Enable Halting Debug 23 | 24 | #define DCRSR_REG_WR (1 << 16) // Write 25 | 26 | #define DEMCR_TRCENA (1 << 24) // Enable DWT and ITM 27 | #define DEMCR_MON_REQ (1 << 19) // HW does not use, SW Sem Bit 28 | #define DEMCR_MON_STEP (1 << 18) // Set Step Request Pending (in Mon Mode) 29 | #define DEMCR_MON_PEND (1 << 17) // Set DebugMonitor Exception Pending 30 | #define DEMCR_MON_EN (1 << 16) // Enable DebugMonitor Exception 31 | 32 | #define DEMCR_VC_HARDERR (1 << 10) // Vector Catch: HardFault Exception 33 | #define DEMCR_VC_INTERR (1 << 9) // Vector Catch: Exception Entry / Return 34 | #define DEMCR_VC_BUSERR (1 << 8) // Vector Catch: BusFault Exception 35 | #define DEMCR_VC_STATERR (1 << 7) // Vector Catch: UsageFault State Error 36 | #define DEMCR_VC_CHKERR (1 << 6) // Vector Catch: UsageFault Check Error 37 | #define DEMCR_VC_NOCPERR (1 << 5) // Vector Catch: Coprocessor Access 38 | #define DEMCR_VC_MMERR (1 << 4) // Vector Catch: MemManage Exception 39 | #define DEMCR_VC_CORERESET (1 << 0) // Vector Catch: Core Reset 40 | 41 | // ---- fault status registers ----------- 42 | #define CFSR 0xE000ED28 // Configurable Fault Status Register 43 | #define HFSR 0xE000ED2C // Hard Fault Status Register 44 | #define DFSR 0xE000ED30 // Debug Fault Status Register 45 | #define MMFAR 0xE000ED34 // MM Fault Address Register 46 | #define BFAR 0xE000ED38 // Bus Fault Address Register 47 | #define AFSR 0xE000ED3C // Aux Fault Status Register (Impl Defined) 48 | 49 | #define CFSR_IACCVIOL (1 << 0) // Inst Access Violation 50 | #define CFSR_DACCVIOL (1 << 1) // Data Access Violation 51 | #define CFSR_MUNSTKERR (1 << 3) // Derived MM Fault on Exception Return 52 | #define CFSR_MSTKERR (1 << 4) // Derived MM Fault on Exception Entry 53 | #define CFSR_MLSPERR (1 << 5) // MM Fault During Lazy FP Save 54 | #define CFSR_MMARVALID (1 << 7) // MMFAR has valid contents 55 | 56 | #define CFSR_IBUSERR (1 << 8) // Bus Fault on Instruction Prefetch 57 | #define CFSR_PRECISERR (1 << 9) // Precise Data Access Error, Addr in BFAR 58 | #define CFSR_IMPRECISERR (1 << 10) // Imprecise Data Access Error 59 | #define CFSR_UNSTKERR (1 << 11) // Derived Bus Fault on Exception Return 60 | #define CFSR_STKERR (1 << 12) // Derived Bus Fault on Exception Entry 61 | #define CFSR_LSPERR (1 << 13) // Bus Fault During Lazy FP Save 62 | #define CFSR_BFARVALID (1 << 15) // BFAR has valid contents 63 | 64 | #define CFSR_UNDEFINSTR (1 << 16) // Undefined Instruction Usage Fault 65 | #define CFSR_INVSTATE (1 << 17) // EPSR.T or ESPR.IT invalid 66 | #define CFSR_INVPC (1 << 18) // Integrity Check Error on EXC_RETURN 67 | #define CFSR_NOCP (1 << 19) // Coprocessor Error 68 | #define CFSR_UNALIGNED (1 << 24) // Unaligned Access Error 69 | #define CFSR_DIVBYZERO (1 << 25) // Divide by Zero (when CCR.DIV_0_TRP set) 70 | 71 | #define CFSR_ALL 0x030FBFBD // all fault bits 72 | 73 | // Write 1 to Clear Status Bits 74 | #define DFSR_HALTED (1 << 0) // DHCSR C_HALT or C_STEP Request 75 | #define DFSR_BKPT (1 << 1) // BKPT instruction or FPB match 76 | #define DFSR_DWTTRAP (1 << 2) // DWT Debug Event 77 | #define DFSR_VCATCH (1 << 3) // Vector Catch Event 78 | #define DFSR_EXTERNAL (1 << 4) // External Debug Event 79 | 80 | #define DFSR_ALL 0x0000001F // all fault bits 81 | 82 | 83 | #define HFSR_VECTTBL (1 << 1) // Vector Table Read Fault 84 | #define HFSR_FORCED (1 << 30) // Configurable-Priority Exception Escalated 85 | #define HFSR_DEBUGEVT (1 << 31) // Debug Event Occurred (and halting debug off) 86 | 87 | #define HFSR_ALL 0xC0000002 // all fault bits 88 | 89 | // ---- Data Watchpoint and Trace -------- 90 | #define DWT_CTRL 0xE0001000 // Control Register 91 | #define DWT_CYCCNT 0xE0001004 // Cycle Count Register 92 | #define DWT_CPICNT 0xE0001008 // CPI Count Register 93 | #define DWT_EXCCNT 0xE000100C // Exception Overhead Count Register 94 | #define DWT_SLEEPCNT 0xE0001010 // Sleep Count Register 95 | #define DWT_LSUCNT 0xE0001014 // LSU Count Register 96 | #define DWT_FOLDCNT 0xE0001018 // Folded Instruction Count Register 97 | #define DWT_PCSR 0xE000101C // Program Counter Sample Register 98 | #define DWT_COMP(n) (0xE0001020 + (n) * 0x10) 99 | #define DWT_MASK(n) (0xE0001024 + (n) * 0x10) 100 | #define DWT_FUNC(n) (0xE0001028 + (n) * 0x10) 101 | 102 | // ---- DWT_CTRL bits --------- 103 | #define DWT_CYCCNTENA (1 << 0) // Enable Cycle Counter 104 | #define DWT_POSTPRESET(n) (((n) & 15) << 1) 105 | #define DWT_POSTINIT(n) (((n) & 15) << 5) 106 | #define DWT_CYCTAP (1 << 9) // 0: POSTCNT tap at CYCCNT[6], 1: at [10] 107 | #define DWT_SYNCTAP_DISABLE (0 << 10) 108 | #define DWT_SYNCTAP_BIT24 (1 << 10) 109 | #define DWT_SYNCTAP_BIT26 (2 << 10) 110 | #define DWT_SYNCTAP_BIT28 (3 << 10) 111 | #define DWT_PCSAMPLENA (1 << 12) // Enable POSTCNT as timer for PC Sample Pkts 112 | #define DWT_EXCTRCENA (1 << 16) // Enable Exception Trace 113 | #define DWT_CPIEVTENA (1 << 17) // Enable CPI Counter Overflow Events 114 | #define DWT_EXCEVTENA (1 << 18) // Enable Exception Overhead Counter Ovf Evt 115 | #define DWT_SLEEPEVTENA (1 << 19) // Enable Sleep Counter Ovf Evt 116 | #define DWT_LSUEVTENA (1 << 20) // Enable LSU Counter Ovf Evt 117 | #define DWT_FOLDEVTENA (1 << 21) // Enable Folded Instruction Counter Ovf Evt 118 | #define DWT_CYCEVTENA (1 << 22) // Enable POSTCNT Undererflow Packets 119 | #define DWT_NOPRFCNT (1 << 24) // 1: No Profiling Counters 120 | #define DWT_NOCYCCNT (1 << 25) // 1: No Cycle Counter 121 | #define DWT_NOEXTTRIG (1 << 26) // 1: No External Match Signals 122 | #define DWT_NOTRCPKT (1 << 27) // 1: No Trace Sampling and Exception Tracing 123 | #define DWT_NUMCOMP(v) ((v) >> 28) 124 | 125 | // ---- DWT_FUNC(n) bits ------ 126 | 127 | #define DWT_FN_DISABLED 0x0 128 | 129 | #define DWT_FN_WATCH_PC 0x4 130 | #define DWT_FN_WATCH_RD 0x5 131 | #define DWT_FN_WATCH_WR 0x6 132 | #define DWT_FN_WATCH_RW 0x7 133 | 134 | #define DWT_EMITRANGE (1 << 5) // 1: Enable Data Trace Address Packet Gen 135 | #define DWT_CYCMATCH (1 << 7) // 1: Cycle Count Comparison (only for COMP0) 136 | #define DWT_DATAVMATCH (1 << 8) // 0: Address Comparison 1: Value Comparison 137 | #define DWT_LNK1ENA (1 << 9) // RO: 1: Linked Comparator Supported 138 | #define DWT_DATAVSIZE_BYTE (0 << 10) 139 | #define DWT_DATAVSIZE_HALF (1 << 10) 140 | #define DWT_DATAVSIZE_WORD (2 << 10) 141 | #define DWT_DATAVADDR0(n) (((n) & 15) << 12) 142 | #define DWT_DATAVADDR1(n) (((n) & 15) << 16) 143 | #define DWT_MATCHED (1 << 24) // Matched since last read. Cleared on read. 144 | 145 | #endif 146 | 147 | -------------------------------------------------------------------------------- /tools/base64.c: -------------------------------------------------------------------------------- 1 | /* base64.h 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | typedef uint8_t u8; 25 | typedef uint32_t u32; 26 | 27 | #define OP_MASK 0xC0 28 | #define OP_BITS 0x00 29 | #define OP_END 0x40 30 | #define OP_SKIP 0x80 31 | #define OP_BAD 0xC0 32 | 33 | static u8 DTABLE[256] = 34 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x80\x80\xc0\xc0\x80\xc0\xc0" 35 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 36 | "\x80\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x3e\xc0\xc0\xc0\x3f" 37 | "\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\xc0\xc0\xc0\x40\xc0\xc0" 38 | "\xc0\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" 39 | "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\xc0\xc0\xc0\xc0\xc0" 40 | "\xc0\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28" 41 | "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\xc0\xc0\xc0\xc0\xc0" 42 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 43 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 44 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 45 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 46 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 47 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 48 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0" 49 | "\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0"; 50 | 51 | static u8 ETABLE[64] = 52 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 53 | "abcdefghijklmnopqrstuvwxyz" 54 | "0123456789+/"; 55 | 56 | int base64_decode(u8 *data, u32 len, u8 *out) 57 | { 58 | u8 *start = out; 59 | u32 tmp = 0, pos = 0; 60 | 61 | while (len-- > 0) { 62 | u8 x = DTABLE[*data++]; 63 | switch (x & OP_MASK) { 64 | case OP_BITS: 65 | tmp = (tmp << 6) | x; 66 | if (++pos == 4) { 67 | *out++ = tmp >> 16; 68 | *out++ = tmp >> 8; 69 | *out++ = tmp; 70 | tmp = 0; 71 | pos = 0; 72 | } 73 | break; 74 | case OP_SKIP: 75 | break; 76 | case OP_END: 77 | if (pos == 2) { 78 | if (*data != '=') 79 | return -1; 80 | *out++ = (tmp >> 4); 81 | } else if (pos == 3) { 82 | *out++ = (tmp >> 10); 83 | *out++ = (tmp >> 2); 84 | } else { 85 | return -1; 86 | } 87 | return out - start; 88 | case OP_BAD: 89 | return -1; 90 | } 91 | } 92 | 93 | if (pos != 0) 94 | return -1; 95 | 96 | return out - start; 97 | } 98 | 99 | int base64_encode(u8 *data, u32 len, u8 *out) 100 | { 101 | u8 *start = out; 102 | u32 n; 103 | 104 | while (len >= 3) { 105 | n = (data[0] << 16) | (data[1] << 8) | data[2]; 106 | data += 3; 107 | len -= 3; 108 | *out++ = ETABLE[(n >> 18) & 63]; 109 | *out++ = ETABLE[(n >> 12) & 63]; 110 | *out++ = ETABLE[(n >> 6) & 63]; 111 | *out++ = ETABLE[n & 63]; 112 | } 113 | if (len == 2) { 114 | *out++ = ETABLE[(data[0] >> 2) & 63]; 115 | *out++ = ETABLE[((data[0] << 4) | (data[1] >> 4)) & 63]; 116 | *out++ = ETABLE[(data[1] << 2) & 63]; 117 | *out++ = '='; 118 | } else if (len == 1) { 119 | *out++ = ETABLE[(data[0] >> 2) & 63]; 120 | *out++ = ETABLE[(data[0] << 4) & 63]; 121 | *out++ = '='; 122 | *out++ = '='; 123 | } 124 | 125 | return out - start; 126 | } 127 | -------------------------------------------------------------------------------- /tools/bless-lpc.c: -------------------------------------------------------------------------------- 1 | /* debugger.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | int main(int argc, char *argv[]) { 25 | int fd; 26 | uint32_t tmp, chk, n; 27 | 28 | chk = 0; 29 | 30 | if (argc != 2) 31 | return -1; 32 | if ((fd = open(argv[1], O_RDWR)) < 0) 33 | return -1; 34 | for (n = 0; n < 7; n++) { 35 | if (read(fd, &tmp, 4) != 4) 36 | return -1; 37 | chk += tmp; 38 | } 39 | tmp = - chk; 40 | n = write(fd, &tmp, 4); 41 | close(fd); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tools/builtins.c: -------------------------------------------------------------------------------- 1 | /* this file is machine-generated by mkbuiltins -- do not modify */ 2 | 3 | #include 4 | #include 5 | 6 | static struct { 7 | const char *name; 8 | size_t size; 9 | void *data; 10 | } files[] = { 11 | { "agent-lpclink2.bin", 576, 12 | "\x66\x61\x77\x42\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x08\x10" 13 | "\x00\x08\x08\x10\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00" 14 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 15 | "\x71\x04\x08\x10\x9D\x05\x08\x10\xC1\x04\x08\x10\xB9\x04\x08\x10" 16 | "\x07\x49\x0B\x68\x06\x4A\x13\xF0\x02\x0F\xFA\xD1\x05\x49\x06\x4B" 17 | "\x19\x60\x13\x68\x9B\x07\xFC\xD4\x04\x4B\x1B\x78\x70\x47\x00\xBF" 18 | "\x1C\x30\x00\x40\x00\x40\x20\x05\x04\x30\x00\x40\x14\x30\x00\x40" 19 | "\x0C\x4B\x0D\x49\x13\x22\x1A\x60\x53\x23\x0B\x60\x4B\x60\x8B\x60" 20 | "\xCB\x60\x0A\x4B\x1A\x60\xA3\xF5\x03\x23\xA3\xF5\xC2\x73\x10\x22" 21 | "\x1A\x60\x18\x68\x10\xF0\x10\x00\xFB\xD1\x05\x4A\x05\x4B\x1A\x60" 22 | "\x70\x47\x00\xBF\x8C\x61\x08\x40\x90\x61\x08\x40\xA0\x61\x08\x40" 23 | "\xFF\xFF\x0F\x00\x00\x30\x00\x40\x6F\xF0\x01\x00\x70\x47\x00\x00" 24 | "\xC0\xF3\x0B\x03\x2D\xE9\xF0\x47\x15\x46\x00\x2B\x4F\xD1\xDF\xF8" 25 | "\xC4\x80\x01\xF5\x80\x74\xC2\x46\xA4\xF5\x80\x76\x00\x2D\x3A\xD0" 26 | "\xFF\x2D\x04\xD9\x26\x4F\x4F\xF0\xC4\x63\x3B\x60\x06\xE0\x73\x19" 27 | "\x00\x22\x03\xF8\x01\x2B\xA3\x42\xFB\xD1\xF3\xE7\xD8\xF8\x00\x30" 28 | "\x99\x07\xFB\xD4\x1F\x4B\xDF\xF8\x90\x90\x1F\x4A\xC9\xF8\x00\x00" 29 | "\x3B\x60\x33\x46\x9C\x42\x03\xD0\x53\xF8\x04\x1B\x11\x60\xF9\xE7" 30 | "\xFF\xF7\x8E\xFF\x19\x4B\x18\x4A\xC9\xF8\x00\x00\x3B\x60\x00\x23" 31 | "\xA6\x42\x07\xD0\x17\x68\x56\xF8\x04\x1B\x8F\x42\x18\xBF\x4F\xF0" 32 | "\xFF\x33\xF5\xE7\xDA\xF8\x00\x20\x92\x07\xFB\xD4\x9B\xB9\xFF\x2D" 33 | "\x04\xF5\x80\x74\x06\xD8\x0E\x4B\x4F\xF0\x60\x72\x1A\x60\x00\x20" 34 | "\xBD\xE8\xF0\x87\xA5\xF5\x80\x75\x00\xF5\x80\x70\xB4\xE7\x6F\xF0" 35 | "\x02\x00\xBD\xE8\xF0\x87\x4F\xF0\xFF\x30\xBD\xE8\xF0\x87\x00\xBF" 36 | "\x04\x30\x00\x40\x00\x81\x80\x02\x14\x30\x00\x40\x00\x01\x80\x03" 37 | "\x18\x30\x00\x40\x1C\x30\x00\x40\x08\x30\x00\x40\x2D\xE9\xF8\x4F" 38 | "\xC0\xF3\x0B\x03\x88\x46\x00\x2B\x37\xD1\xDF\xF8\x8C\x90\x0D\x46" 39 | "\xCA\x46\x00\xEB\x08\x06\x76\x1B\x4D\xB3\x1C\x4F\x4F\xF0\xC4\x63" 40 | "\x3B\x60\xD9\xF8\x00\x30\x13\xF0\x02\x04\xFA\xD1\xDF\xF8\x6C\xB0" 41 | "\x4F\xF0\x02\x53\xCB\xF8\x00\x60\x3B\x60\xFF\xF7\x31\xFF\x14\x4B" 42 | "\xCB\xF8\x00\x60\x40\xF2\x01\x42\x3B\x60\x23\x46\x11\x49\x01\x3A" 43 | "\x05\xD0\x0C\x68\x01\x34\x18\xBF\x4F\xF0\xFF\x33\xF7\xE7\xDA\xF8" 44 | "\x00\x20\x92\x07\xFB\xD4\x63\xB9\xB5\xF5\x80\x5F\x02\xD2\x00\x20" 45 | "\xBD\xE8\xF8\x8F\xA5\xF5\x80\x55\xCB\xE7\x6F\xF0\x02\x00\xBD\xE8" 46 | "\xF8\x8F\x4F\xF0\xFF\x30\xBD\xE8\xF8\x8F\x00\xBF\x04\x30\x00\x40" 47 | "\x00\x10\x80\x03\x14\x30\x00\x40\x1C\x30\x00\x40\x08\x30\x00\x40" 48 | }, 49 | { "agent-stm32f4xx.bin", 328, 50 | "\x66\x61\x77\x42\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x00\x20" 51 | "\x00\x08\x00\x20\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00" 52 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 53 | "\x41\x04\x00\x20\x5D\x04\x00\x20\xC9\x04\x00\x20\xC1\x04\x00\x20" 54 | "\x04\x4B\x05\x4A\x1A\x60\x02\xF1\x88\x32\x1A\x60\xD8\x68\xC0\x17" 55 | "\x70\x47\x00\xBF\x04\x3C\x02\x40\x23\x01\x67\x45\xF0\xB5\x04\x46" 56 | "\x14\x4B\x00\x22\x53\xF8\x22\x00\x12\x4E\xA0\x42\x05\xD0\x01\x32" 57 | "\x0C\x2A\xF7\xD1\x6F\xF0\x02\x00\xF0\xBD\x0F\x4D\x0F\x4F\xD3\x00" 58 | "\x43\xF0\x02\x00\x43\xF4\x80\x33\x43\xF0\x02\x03\x28\x60\x2B\x60" 59 | "\x3B\x68\xD8\x03\xFC\xD4\x13\xF0\xF2\x00\x08\xD1\x01\x32\x0C\x2A" 60 | "\x07\xD0\x56\xF8\x22\x30\x1B\x1B\x8B\x42\xE8\xD3\xF0\xBD\x4F\xF0" 61 | "\xFF\x30\xF0\xBD\x14\x05\x00\x20\x10\x3C\x02\x40\x0C\x3C\x02\x40" 62 | "\x6F\xF0\x01\x00\x70\x47\x00\x00\x40\xEA\x02\x03\x9B\x07\xF0\xB5" 63 | "\x19\xD1\x40\xF2\x01\x24\x0D\x4B\x0D\x4E\x1C\x60\x0C\x46\x45\x1A" 64 | "\x10\x1B\x08\x18\x0D\xD0\x20\x68\x60\x51\x04\x34\x30\x68\x10\xF4" 65 | "\x80\x37\xFB\xD1\x10\xF0\xF2\x0F\xF2\xD0\x1F\x60\x4F\xF0\xFF\x30" 66 | "\xF0\xBD\x18\x60\xF0\xBD\x6F\xF0\x02\x00\xF0\xBD\x10\x3C\x02\x40" 67 | "\x0C\x3C\x02\x40\x00\x00\x00\x00\x00\x40\x00\x00\x00\x80\x00\x00" 68 | "\x00\xC0\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x04\x00" 69 | "\x00\x00\x06\x00\x00\x00\x08\x00\x00\x00\x0A\x00\x00\x00\x0C\x00" 70 | "\x00\x00\x0E\x00\x00\x00\x10\x00" 71 | }, 72 | { "agent-stm32f0xx.bin", 408, 73 | "\x66\x61\x77\x42\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x00\x20" 74 | "\x00\x08\x00\x20\x00\x10\x00\x00\x00\x00\x00\x08\x00\x40\x00\x00" 75 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 76 | "\x41\x04\x00\x20\xAD\x04\x00\x20\x29\x05\x00\x20\x8D\x05\x00\x20" 77 | "\x12\x4B\x13\x4A\x1B\x68\x1B\x05\x1B\x0D\x9B\x18\x08\x2B\x1A\xD8" 78 | "\x01\x22\x9A\x40\x13\x00\x31\x22\x13\x42\x06\xD1\xD3\x32\x13\x42" 79 | "\x11\xD0\x80\x22\x0B\x4B\x12\x01\x1A\x60\x0B\x4B\x0B\x4A\x1B\x88" 80 | "\x9B\x02\xC3\x61\x0A\x4B\x1A\x60\x0A\x4A\x1A\x60\x0A\x4B\x18\x68" 81 | "\x00\x06\xC0\x17\x01\xE0\x02\x20\x40\x42\x70\x47\x00\x58\x01\x40" 82 | "\xC0\xFB\xFF\xFF\x94\x05\x00\x20\xCC\xF7\xFF\x1F\x23\x01\x67\x45" 83 | "\x04\x20\x02\x40\xAB\x89\xEF\xCD\x10\x20\x02\x40\xF7\xB5\x19\x4A" 84 | "\x13\x68\x01\x3B\x18\x42\x2A\xD1\x17\x4C\x18\x4B\x25\x68\x42\x26" 85 | "\x2B\x40\x02\x25\x1D\x43\x33\x43\x01\x93\x00\x29\x1D\xD0\x16\x68" 86 | "\xB1\x42\x01\xD9\x89\x1B\x00\xE0\x00\x21\x11\x4E\x25\x60\x30\x60" 87 | "\x10\x4E\x01\x9B\xB4\x46\x01\x26\x23\x60\x67\x46\x3F\x68\x37\x42" 88 | "\xFB\xD1\x06\x00\x17\x68\x33\x1A\x9F\x42\x04\xD9\x08\xCE\x01\x33" 89 | "\xF9\xD0\x01\x20\x04\xE0\xC0\x19\xDF\xE7\x08\x00\x01\xE0\x03\x20" 90 | "\x40\x42\xFE\xBD\x94\x05\x00\x20\x10\x20\x02\x40\x08\xC9\xFF\xFF" 91 | "\x14\x20\x02\x40\x0C\x20\x02\x40\x03\x00\x13\x43\xF7\xB5\x9B\x07" 92 | "\x22\xD1\x01\x26\x12\x4B\x13\x4C\x1D\x68\x37\x00\x25\x40\x34\x00" 93 | "\x2C\x43\x1C\x60\x0C\x00\x40\x1A\x01\x90\x10\x1B\x08\x18\x00\x28" 94 | "\x10\xD0\x01\x98\x26\x88\x20\x18\x06\x80\x0B\x4E\x36\x68\x3E\x42" 95 | "\xFB\xD1\x00\x88\x26\x88\x86\x42\x02\xD0\x1D\x60\x01\x20\x04\xE0" 96 | "\x02\x34\xEA\xE7\x1D\x60\x01\xE0\x03\x20\x40\x42\xFE\xBD\xC0\x46" 97 | "\x10\x20\x02\x40\x08\xC9\xFF\xFF\x0C\x20\x02\x40\x02\x20\x40\x42" 98 | "\x70\x47\x00\x00\x00\x04\x00\x00" 99 | }, 100 | { "agent-lpc13xx.bin", 284, 101 | "\x66\x61\x77\x42\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x00\x10" 102 | "\x00\x08\x00\x10\x00\x10\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00" 103 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 104 | "\x41\x04\x00\x10\x45\x04\x00\x10\x9D\x04\x00\x10\x15\x05\x00\x10" 105 | "\x00\x20\x70\x47\x70\xB5\x01\x39\x05\x0B\xC0\xF3\x0B\x00\x8A\xB0" 106 | "\x05\xEB\x11\x34\xC8\xB9\x32\x23\x05\x93\x06\x95\x07\x94\x0E\x4E" 107 | "\x01\xA9\x05\xA8\xB0\x47\x01\x9B\x93\xB9\x34\x23\x05\x93\x42\xF6" 108 | "\xE0\x63\x05\xA8\x06\x95\x07\x94\x08\x93\x01\xA9\xB0\x47\x01\x98" 109 | "\x00\x30\x18\xBF\x01\x20\x40\x42\x04\xE0\x6F\xF0\x02\x00\x01\xE0" 110 | "\x4F\xF0\xFF\x30\x0A\xB0\x70\xBD\xF1\x1F\xFF\x1F\x70\xB5\x14\x46" 111 | "\xC0\xF3\x0B\x02\x8A\xB0\x05\x46\x0E\x46\x03\x0B\x42\xBB\x32\x22" 112 | "\x06\x93\x07\x93\x05\x92\x16\x4B\x01\xA9\x05\xA8\x98\x47\x01\x9B" 113 | "\x0B\xBB\xB4\xF5\x80\x5F\x13\xD1\x33\x23\x05\x93\x4F\xF4\x80\x53" 114 | "\x08\x93\x42\xF6\xE0\x63\x05\xA8\x09\x93\x06\x95\x07\x96\x01\xA9" 115 | "\x0B\x4B\x98\x47\x01\x98\x00\x30\x18\xBF\x01\x20\x40\x42\x0C\xE0" 116 | "\x32\x19\x91\x1B\xB1\xF5\x80\x5F\xE6\xDA\x02\xF8\x01\x3B\xF8\xE7" 117 | "\x6F\xF0\x02\x00\x01\xE0\x4F\xF0\xFF\x30\x0A\xB0\x70\xBD\x00\xBF" 118 | "\xF1\x1F\xFF\x1F\x6F\xF0\x01\x00\x70\x47\x00\x00" 119 | }, 120 | { "agent-lpc15xx.bin", 284, 121 | "\x66\x61\x77\x42\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x00\x02" 122 | "\x00\x08\x00\x02\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" 123 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 124 | "\x41\x04\x00\x02\x45\x04\x00\x02\x9D\x04\x00\x02\x15\x05\x00\x02" 125 | "\x00\x20\x70\x47\x70\xB5\x01\x39\x05\x0B\xC0\xF3\x0B\x00\x8A\xB0" 126 | "\x05\xEB\x11\x34\xC8\xB9\x32\x23\x05\x93\x06\x95\x07\x94\x0E\x4E" 127 | "\x01\xA9\x05\xA8\xB0\x47\x01\x9B\x93\xB9\x34\x23\x05\x93\x42\xF6" 128 | "\xE0\x63\x05\xA8\x06\x95\x07\x94\x08\x93\x01\xA9\xB0\x47\x01\x98" 129 | "\x00\x30\x18\xBF\x01\x20\x40\x42\x04\xE0\x6F\xF0\x02\x00\x01\xE0" 130 | "\x4F\xF0\xFF\x30\x0A\xB0\x70\xBD\x05\x02\x00\x03\x70\xB5\x14\x46" 131 | "\xC0\xF3\x0B\x02\x8A\xB0\x05\x46\x0E\x46\x03\x0B\x42\xBB\x32\x22" 132 | "\x06\x93\x07\x93\x05\x92\x16\x4B\x01\xA9\x05\xA8\x98\x47\x01\x9B" 133 | "\x0B\xBB\xB4\xF5\x80\x5F\x13\xD1\x33\x23\x05\x93\x4F\xF4\x80\x53" 134 | "\x08\x93\x42\xF6\xE0\x63\x05\xA8\x09\x93\x06\x95\x07\x96\x01\xA9" 135 | "\x0B\x4B\x98\x47\x01\x98\x00\x30\x18\xBF\x01\x20\x40\x42\x0C\xE0" 136 | "\x32\x19\x91\x1B\xB1\xF5\x80\x5F\xE6\xDA\x02\xF8\x01\x3B\xF8\xE7" 137 | "\x6F\xF0\x02\x00\x01\xE0\x4F\xF0\xFF\x30\x0A\xB0\x70\xBD\x00\xBF" 138 | "\x05\x02\x00\x03\x6F\xF0\x01\x00\x70\x47\x00\x00" 139 | }, 140 | { "agent-cc13xx.bin", 180, 141 | "\x66\x61\x77\x42\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x00\x20" 142 | "\x00\x10\x00\x20\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00" 143 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 144 | "\x41\x04\x00\x20\x45\x04\x00\x20\x81\x04\x00\x20\xAD\x04\x00\x20" 145 | "\x00\x20\x70\x47\xC0\xF3\x0B\x03\x70\xB5\x83\xB9\x0C\x46\x0B\x4E" 146 | "\x45\x18\x28\x1B\x34\xB1\x33\x68\x5B\x69\x98\x47\x50\xB9\xB4\xF5" 147 | "\x80\x5F\x01\xD8\x00\x20\x70\xBD\xA4\xF5\x80\x54\xF1\xE7\x6F\xF0" 148 | "\x02\x00\x70\xBD\x4F\xF0\xFF\x30\x70\xBD\x00\xBF\xA8\x01\x00\x10" 149 | "\x03\x46\x08\x46\xC3\xF3\x0B\x01\x10\xB5\x49\xB9\x06\x49\x09\x68" 150 | "\x8C\x69\x19\x46\xA0\x47\x00\x30\x18\xBF\x01\x20\x40\x42\x10\xBD" 151 | "\x6F\xF0\x02\x00\x10\xBD\x00\xBF\xA8\x01\x00\x10\x6F\xF0\x01\x00" 152 | "\x70\x47\x00\x00" 153 | }, 154 | { "agent-nrf528xx.bin", 340, 155 | "\x66\x61\x77\x42\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x00\x20" 156 | "\x00\x08\x00\x20\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 157 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 158 | "\x41\x04\x00\x20\x71\x04\x00\x20\xED\x04\x00\x20\x69\x04\x00\x20" 159 | "\x05\x4B\x1A\x68\x05\x4B\x1A\x60\x05\x4B\x1B\x68\x53\x43\x05\x4A" 160 | "\xC3\x61\x13\x60\x00\x20\x70\x47\x10\x00\x00\x10\x4C\x05\x00\x20" 161 | "\x14\x00\x00\x10\x50\x05\x00\x20\x6F\xF0\x01\x00\x70\x47\x00\x00" 162 | "\x19\x4B\xF0\xB5\x1B\x68\x83\x42\x27\xD3\x18\x4B\x1A\x68\x01\x3A" 163 | "\x02\x42\x25\xD1\x02\x24\x16\x4A\x16\x4E\x17\x4F\x14\x60\x19\xB9" 164 | "\x08\x46\x00\x23\x13\x60\xF0\xBD\x1C\x68\x30\x60\x8C\x42\x2C\xBF" 165 | "\x00\x21\x09\x1B\x3C\x68\x01\x2C\xFC\xD1\x00\x24\x1D\x68\xAC\x42" 166 | "\x01\xD3\x28\x44\xEB\xE7\x50\xF8\x04\xE0\xBE\xF1\xFF\x3F\x01\xD1" 167 | "\x04\x34\xF4\xE7\x4F\xF0\xFF\x30\xE3\xE7\x6F\xF0\x01\x00\xF0\xBD" 168 | "\x6F\xF0\x02\x00\xF0\xBD\x00\xBF\x50\x05\x00\x20\x4C\x05\x00\x20" 169 | "\x04\xE5\x01\x40\x08\xE5\x01\x40\x00\xE4\x01\x40\x14\x4B\xF0\xB5" 170 | "\x1B\x68\x83\x42\x1E\xD3\x40\xEA\x02\x03\x9B\x07\x1D\xD1\x01\x23" 171 | "\x10\x4D\x11\x4E\x2B\x60\x0B\x46\x44\x1A\xD0\x1A\x08\x18\x02\xD1" 172 | "\x00\x23\x2B\x60\xF0\xBD\xE0\x18\x53\xF8\x04\x7B\x07\x60\x37\x68" 173 | "\x01\x2F\xFC\xD1\x07\x68\x53\xF8\x04\x0C\x87\x42\xED\xD0\x4F\xF0" 174 | "\xFF\x30\xED\xE7\x6F\xF0\x01\x00\xF0\xBD\x6F\xF0\x02\x00\xF0\xBD" 175 | "\x50\x05\x00\x20\x04\xE5\x01\x40\x00\xE4\x01\x40\x00\x04\x00\x00" 176 | "\x00\x00\x03\x00" 177 | }, 178 | { "agent-pico.bin", 484, 179 | "\x66\x61\x77\x42\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x00\x20" 180 | "\x00\x08\x00\x20\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 181 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 182 | "\x69\x05\x00\x20\x41\x04\x00\x20\xC9\x04\x00\x20\x51\x05\x00\x20" 183 | "\x80\x23\x70\xB5\xDB\x03\x05\x00\x0C\x00\x98\x42\x2C\xD8\x03\x05" 184 | "\x2D\xD1\x0B\x05\x04\xD0\x80\x23\x0C\x0B\x24\x03\x5B\x01\xE4\x18" 185 | "\x14\x4B\x1B\x68\x98\x47\x14\x4B\x1B\x68\x98\x47\x80\x22\x13\x4B" 186 | "\x28\x00\x21\x00\x52\x02\x1E\x68\xD8\x23\xB0\x47\x10\x4B\x1B\x68" 187 | "\x98\x47\x10\x4B\x1B\x68\x98\x47\x80\x23\xF0\x20\x5B\x05\x00\x06" 188 | "\xEB\x18\x45\x1B\x5A\x19\xA2\x42\x01\xD3\x00\x20\x70\xBD\x04\xCB" 189 | "\x01\x32\xF7\xD0\x01\x20\x00\xE0\x02\x20\x40\x42\xF6\xE7\x03\x20" 190 | "\xFB\xE7\xC0\x46\xE4\x05\x00\x20\xF0\x05\x00\x20\xEC\x05\x00\x20" 191 | "\xF4\x05\x00\x20\xE8\x05\x00\x20\xF8\xB5\x80\x23\x05\x00\x0F\x00" 192 | "\x14\x00\xDB\x03\x98\x42\x29\xD8\xFF\x23\x06\x00\x1E\x40\x18\x42" 193 | "\x27\xD1\x1A\x42\x02\xD0\x9C\x43\x01\x34\xFF\x34\x13\x4B\x1B\x68" 194 | "\x98\x47\x13\x4B\x1B\x68\x98\x47\x12\x4B\x28\x00\x22\x00\x39\x00" 195 | "\x1B\x68\x98\x47\x10\x4B\x1B\x68\x98\x47\x10\x4B\x1B\x68\x98\x47" 196 | "\x80\x23\x5B\x05\xED\x18\xAB\x19\xB4\x42\x01\xD8\x00\x20\xF8\xBD" 197 | "\x1B\x68\xBA\x59\x93\x42\x06\xD1\x04\x36\xF4\xE7\x02\x20\x40\x42" 198 | "\xF5\xE7\x03\x20\xFB\xE7\x01\x20\xF9\xE7\xC0\x46\xE4\x05\x00\x20" 199 | "\xF0\x05\x00\x20\xF8\x05\x00\x20\xF4\x05\x00\x20\xE8\x05\x00\x20" 200 | "\x02\x20\x40\x42\x70\x47\x14\x23\x10\xB5\x01\x00\x18\x88\x04\x33" 201 | "\x1B\x88\x98\x47\x10\xBD\x00\x00\x10\xB5\x04\x00\x11\x48\xFF\xF7" 202 | "\xF2\xFF\x11\x4B\x18\x60\x11\x48\xFF\xF7\xED\xFF\x10\x4B\x18\x60" 203 | "\x10\x48\xFF\xF7\xE8\xFF\x10\x4B\x18\x60\x10\x48\xFF\xF7\xE3\xFF" 204 | "\x0F\x4B\x18\x60\x0F\x48\xFF\xF7\xDE\xFF\x0F\x4B\x18\x60\x0F\x48" 205 | "\xFF\xF7\xD9\xFF\x0E\x4B\x18\x60\x80\x23\xDB\x03\x00\x20\xE3\x61" 206 | "\x10\xBD\xC0\x46\x49\x46\x00\x00\xE4\x05\x00\x20\x45\x58\x00\x00" 207 | "\xF0\x05\x00\x20\x52\x45\x00\x00\xEC\x05\x00\x20\x52\x50\x00\x00" 208 | "\xF8\x05\x00\x20\x46\x43\x00\x00\xF4\x05\x00\x20\x43\x58\x00\x00" 209 | "\xE8\x05\x00\x20" 210 | }, 211 | }; 212 | 213 | void *get_builtin_file(const char *name, size_t *sz) { 214 | int n; 215 | for (n = 0; n < (sizeof(files)/sizeof(files[0])); n++) { 216 | if (!strcmp(name, files[n].name)) { 217 | *sz = files[n].size; 218 | return files[n].data; 219 | } 220 | } 221 | return NULL; 222 | } 223 | 224 | const char *get_builtin_filename(unsigned n) { 225 | if (n >= (sizeof(files)/sizeof(files[0]))) { 226 | return NULL; 227 | } 228 | return files[n].name; 229 | } 230 | -------------------------------------------------------------------------------- /tools/dap-registers.h: -------------------------------------------------------------------------------- 1 | #ifndef _DAP_REGISTERS_H_ 2 | #define _DAP_REGISTERS_H_ 3 | 4 | /* ARM DAP Controller (4bit IR) */ 5 | #define DAP_IR_SIZE 4 6 | 7 | #define DAP_IR_ABORT 0x08 8 | #define DAP_IR_DPACC 0x0A 9 | #define DAP_IR_APACC 0x0B 10 | #define DAP_IR_IDCODE 0x0E 11 | #define DAP_IR_BYPASS 0x0F 12 | 13 | /* DPACC/APACC DR bits */ 14 | #define XPACC_STATUS(n) ((n) & 0x3) 15 | #define XPACC_WAIT 0x1 16 | #define XPACC_OK 0x2 17 | #define XPACC_RD(a) (0x1 | (((a) >> 1) & 6)) 18 | #define XPACC_WR(a,v) ((((u64)(v)) << 3) | (0x0 | (((a) >> 1) & 6))) 19 | 20 | /* DP addresses */ 21 | #define DPACC_RESERVED 0x0 22 | #define DPACC_CSW 0x4 23 | #define DPACC_SELECT 0x8 24 | #define DPACC_RDBUFF 0xC 25 | 26 | #define DPCSW_CSYSPWRUPACK (1 << 31) 27 | #define DPCSW_CSYSPWRUPREQ (1 << 30) 28 | #define DPCSW_CDBGPWRUPACK (1 << 29) 29 | #define DPCSW_CDBGPWRUPREQ (1 << 28) 30 | #define DPCSW_CDBGRSTACK (1 << 27) 31 | #define DPCSW_CDBGRSTREQ (1 << 26) 32 | #define DPCSW_TRNCNT(n) (((n) & 0x3FF) << 12) 33 | #define DPCSW_MASKLANE(n) (((n) & 0xF) << 8) // pushed verify or compare 34 | #define DPCSW_WDATAERR (1 << 7) // reserved on jtag 35 | #define DPCSW_READOK (1 << 6) // reserved on jtag 36 | #define DPCSW_STICKYERR (1 << 5) 37 | #define DPCSW_STICKYCMP (1 << 4) 38 | #define DPCSW_TRNMODE_NORMAL (0 << 2) 39 | #define DPCSW_TRNMODE_PUSH_VRFY (1 << 2) 40 | #define DPCSW_TRNMODE_PUSH_CMP (2 << 2) 41 | #define DPCSW_STICKYORUN (1 << 1) 42 | #define DPCSW_ORUNDETECT (1 << 0) 43 | 44 | #define DPSEL_APSEL(n) (((n) & 0xFF) << 24) 45 | #define DPSEL_APBANKSEL(a) ((a) & 0xF0) 46 | #define DPSEL_CTRLSEL (1 << 0) // reserved on jtag 47 | 48 | /* Reading RDBUFF returns 0, has no side effects */ 49 | /* Can be used to obtain final read result and ack values at end of seq */ 50 | 51 | /* AP addresses */ 52 | #define APACC_CSW 0x00 53 | #define APACC_TAR 0x04 54 | #define APACC_DRW 0x0C 55 | #define APACC_BD0 0x10 56 | #define APACC_BD1 0x14 57 | #define APACC_BD2 0x18 58 | #define APACC_BD3 0x1C 59 | #define APACC_CFG 0xF4 60 | #define APACC_BASE 0xF8 61 | #define APACC_IDR 0xFC 62 | 63 | #define APCSW_DBGSWEN (1 << 31) 64 | #define APCSW_PROT_MASK 0x7F000000 65 | #define APCSW_SPIDEN (1 << 23) // ro 66 | #define APCSW_TRBUSY (1 << 7) // ro 67 | #define APCSW_DEVICEEN (1 << 6) // ro 68 | #define APCSW_INCR_NONE (0 << 4) 69 | #define APCSW_INCR_SINGLE (1 << 4) 70 | #define APCSW_INCR_PACKED (2 << 4) // may not be supported 71 | #define APCSW_SIZE8 (0 << 0) // may not be supported 72 | #define APCSW_SIZE16 (1 << 0) // may not be supported 73 | #define APCSW_SIZE32 (2 << 0) 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /tools/debugger.c: -------------------------------------------------------------------------------- 1 | /* debugger.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include "rswdp.h" 29 | 30 | #include "linenoise.h" 31 | #include "debugger.h" 32 | 33 | unsigned log_flags = 0; 34 | 35 | void linenoiseInit(void); 36 | 37 | static const char *scriptfile = NULL; 38 | 39 | void gdb_console_puts(const char *msg); 40 | 41 | void xprintf(xpchan ch, const char *fmt, ...) { 42 | char line[256]; 43 | va_list ap; 44 | va_start(ap, fmt); 45 | vsnprintf(line, 256, fmt, ap); 46 | va_end(ap); 47 | linenoisePause(); 48 | if (write(1, line, strlen(line)) < 0) ; 49 | linenoiseResume(); 50 | gdb_console_puts(line); 51 | } 52 | 53 | static void handler(int n) { 54 | swdp_interrupt(); 55 | } 56 | 57 | static void usage(int argc, char **argv) { 58 | fprintf(stderr, "usage: %s [-h] [-f script]\n", argv[0]); 59 | 60 | exit(1); 61 | } 62 | 63 | int main(int argc, char **argv) { 64 | char lastline[1024]; 65 | char *line; 66 | 67 | /* args */ 68 | for(;;) { 69 | int c; 70 | int option_index = 0; 71 | 72 | static struct option long_options[] = { 73 | {"help", 0, 0, 'h'}, 74 | {"script", 1, 0, 'f'}, 75 | {"pico", 0, 0, 'p'}, 76 | {0, 0, 0, 0}, 77 | }; 78 | 79 | c = getopt_long(argc, argv, "f:h", long_options, &option_index); 80 | if(c == -1) 81 | break; 82 | 83 | switch(c) { 84 | case 'f': 85 | scriptfile = optarg; 86 | break; 87 | case 'h': 88 | usage(argc, argv); 89 | break; 90 | case 'p': 91 | debug_target("pico"); 92 | break; 93 | default: 94 | usage(argc, argv); 95 | break; 96 | } 97 | } 98 | 99 | lastline[0] = 0; 100 | 101 | if (swdp_open()) { 102 | fprintf(stderr,"could not find device\n"); 103 | return -1; 104 | } 105 | 106 | signal(SIGINT, handler); 107 | 108 | // swdp_enable_tracing(1); 109 | 110 | /* 111 | * if the user passed in a script file, pass it to the debug 112 | * command handler before starting the main loop 113 | */ 114 | if (scriptfile != NULL) { 115 | char *buf = malloc(sizeof("script ") + strlen(scriptfile) + 1); 116 | 117 | strcpy(buf, "script "); 118 | strcat(buf, scriptfile); 119 | 120 | debugger_command(buf); 121 | 122 | free(buf); 123 | } 124 | 125 | linenoiseInit(); 126 | debugger_init(); 127 | 128 | while ((line = linenoise("debugger> ")) != NULL) { 129 | if (line[0] == 0) { 130 | strcpy(line, lastline); 131 | } else { 132 | linenoiseHistoryAdd(line); 133 | strcpy(lastline, line); 134 | } 135 | debugger_command(line); 136 | } 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /tools/debugger.h: -------------------------------------------------------------------------------- 1 | /* debugger.h 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef _DEBUGGER_H_ 19 | #define _DEBUGGER_H_ 20 | 21 | typedef enum { 22 | XDEFAULT, 23 | XSWD, // SWD transport & engine 24 | XCORE, // debugger core 25 | XDATA, // debugger command response 26 | XGDB, // messages from GDB bridge 27 | XREMOTE, // remote console messages 28 | } xpchan; 29 | 30 | #define printf __use_xprintf_in_debugger__ 31 | extern void xprintf(xpchan ch, const char *fmt, ...); 32 | 33 | #define ERROR -1 34 | #define ERROR_UNKNOWN -2 35 | 36 | #define LF_SWD 1 37 | #define LF_GDB 2 38 | 39 | extern unsigned log_flags; 40 | 41 | struct funcline { 42 | struct funcline *next; 43 | char text[0]; 44 | }; 45 | 46 | struct funcinfo { 47 | struct funcinfo *next; 48 | struct funcline *lines; 49 | char name[0]; 50 | }; 51 | 52 | struct varinfo { 53 | struct varinfo *next; 54 | u32 value; 55 | char name[0]; 56 | }; 57 | 58 | typedef struct { 59 | const char *s; 60 | unsigned n; 61 | } param; 62 | 63 | struct debugger_command { 64 | const char *name; 65 | const char *args; 66 | int (*func)(int argc, param *argv); 67 | const char *help; 68 | }; 69 | 70 | /* provided by debugger-core.c */ 71 | int debugger_command(char *line); 72 | int debugger_invoke(const char *cmd, unsigned argc, ...); 73 | int debugger_variable(const char *name, u32 *value); 74 | 75 | /* lock to protect underlying rswdp state */ 76 | void debugger_init(); 77 | void debugger_lock(); 78 | void debugger_unlock(); 79 | 80 | /* provided by debugger-commands.c */ 81 | extern struct debugger_command debugger_commands[]; 82 | int read_register(const char *name, u32 *value); 83 | int read_memory_word(u32 addr, u32 *value); 84 | 85 | typedef struct debug_transport { 86 | // attempt to establish connection to target 87 | int (*attach)(void); 88 | 89 | // returns nonzero if target is in error state 90 | // (one or more transactions have failed, attach needed) 91 | int (*error)(void); 92 | 93 | // if target is in error, clear error flag 94 | // return nonzero if target was in error (attach needed) 95 | int (*clear_error)(void); 96 | 97 | // single 32bit memory access 98 | int (*mem_rd_32)(u32 addr, u32 *value); 99 | int (*mem_wr_32)(u32 addr, u32 value); 100 | 101 | // multiple 32bit memory access 102 | int (*mem_rd_32_c)(u32 addr, u32 *data, int count); 103 | int (*mem_wr_32_c)(u32 addr, u32 *data, int count); 104 | } debug_transport; 105 | 106 | extern debug_transport *ACTIVE_TRANSPORT; 107 | 108 | static inline int debug_attach(void) { 109 | return ACTIVE_TRANSPORT->attach(); 110 | } 111 | static inline int debug_error(void) { 112 | return ACTIVE_TRANSPORT->error(); 113 | } 114 | static inline int debug_clear_error(void) { 115 | return ACTIVE_TRANSPORT->clear_error(); 116 | } 117 | static inline int mem_rd_32(u32 addr, u32 *value) { 118 | return ACTIVE_TRANSPORT->mem_rd_32(addr, value); 119 | } 120 | static inline int mem_wr_32(u32 addr, u32 value) { 121 | return ACTIVE_TRANSPORT->mem_wr_32(addr, value); 122 | } 123 | static inline int mem_rd_32_c(u32 addr, u32 *data, int count) { 124 | return ACTIVE_TRANSPORT->mem_rd_32_c(addr, data, count); 125 | } 126 | static inline int mem_wr_32_c(u32 addr, u32 *data, int count) { 127 | return ACTIVE_TRANSPORT->mem_wr_32_c(addr, data, count); 128 | } 129 | 130 | extern debug_transport DUMMY_TRANSPORT; 131 | extern debug_transport SWDP_TRANSPORT; 132 | extern debug_transport JTAG_TRANSPORT; 133 | 134 | int debug_target(const char* name); 135 | 136 | #endif 137 | 138 | -------------------------------------------------------------------------------- /tools/jtag.c: -------------------------------------------------------------------------------- 1 | /* jtag transport 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | #include "debugger.h" 24 | #include "rswdp.h" 25 | #include "jtag.h" 26 | 27 | static const char *JSTATE[17] = { 28 | "RESET", "IDLE", "DRSELECT", "DRCAPTURE", 29 | "DRSHIFT", "DREXIT1", "DRPAUSE", "DREXIT2", 30 | "DRUPDATE", "IRSELECT", "IRCAPTURE", "IRSHIFT", 31 | "IREXIT1", "IRPAUSE", "IREXIT1", "IRUPDATE", 32 | "UNKNOWN" 33 | }; 34 | 35 | static u64 ONES = 0xFFFFFFFFFFFFFFFFUL; 36 | 37 | void jtag_txn_init(jtag_txn *tx) { 38 | memset(tx, 0, sizeof(jtag_txn)); 39 | tx->state = JTAG_UNKNOWN; 40 | } 41 | 42 | int jtag_txn_exec(jtag_txn *t) { 43 | unsigned n, off = 0; 44 | int r; 45 | if (t->status) { 46 | return t->status; 47 | } 48 | //xprintf(XCORE, "jtag exec %d bits\n", t->txc); 49 | r = jtag_io(t->txc, t->tms, t->tdi, t->tdo); 50 | for (n = 0; n < t->rxc; n++) { 51 | unsigned count = t->bits[n]; 52 | if (t->ptr[n]) { 53 | unsigned bit = 0; 54 | u64 x = 0; 55 | while (count > 0) { 56 | x |= ((u64) ((t->tdo[off >> 5] >> (off & 31)) & 1)) << bit; 57 | off++; 58 | bit++; 59 | count--; 60 | } 61 | *t->ptr[n] = x; 62 | } else { 63 | off += count; 64 | } 65 | } 66 | return r; 67 | } 68 | 69 | void jtag_txn_append(jtag_txn *t, unsigned count, u64 tms, u64 tdi, u64 *tdo) { 70 | unsigned txc = t->txc; 71 | 72 | if (txc == JTAG_MAX_RESULTS) { 73 | xprintf(XCORE, "jtag append txn overflow\n"); 74 | t->status = -1; 75 | return; 76 | } 77 | if ((count > 64) || ((JTAG_MAX_BITS - t->bitcount) < count)) { 78 | xprintf(XCORE, "jtag append bits overflow\n"); 79 | t->status = -1; 80 | return; 81 | } 82 | t->bitcount += count; 83 | 84 | // xprintf(XCORE, "jtag append %2d bits %016lx %016lx\n", count, tms, tdi); 85 | 86 | t->ptr[t->rxc] = tdo; 87 | t->bits[t->rxc] = count; 88 | t->rxc++; 89 | 90 | while (count > 0) { 91 | t->tms[txc >> 5] |= (tms & 1) << (txc & 31); 92 | t->tdi[txc >> 5] |= (tdi & 1) << (txc & 31); 93 | tms >>= 1; 94 | tdi >>= 1; 95 | count--; 96 | txc++; 97 | } 98 | t->txc = txc; 99 | } 100 | 101 | void jtag_txn_move(jtag_txn *t, unsigned dst) { 102 | if (t->state == dst) { 103 | // nothing to do 104 | return; 105 | } 106 | switch (t->state) { 107 | case JTAG_IDLE: 108 | if (dst == JTAG_IRSHIFT) { 109 | // Idle -> SelDR -> SelIR -> CapIR -> ShiftIR 110 | // 1 1 0 0 111 | jtag_txn_append(t, 4, 0b0011, 0b1111, NULL); 112 | } else if (dst == JTAG_DRSHIFT) { 113 | // Idle -> SelDR -> CapDR -> ShiftDR 114 | // 1 0 0 115 | jtag_txn_append(t, 3, 0b001, 0b111, NULL); 116 | } else { 117 | goto oops; 118 | } 119 | break; 120 | case JTAG_DRPAUSE: 121 | case JTAG_IRPAUSE: 122 | if (dst == JTAG_IRSHIFT) { 123 | // PauseDR -> Exit2DR -> UpDR -> SelDR -> SelIR -> CapIR -> ShiftIR 124 | // PauseIR -> Exit2IR -> UpIR -> SelDR -> SelIR -> CapIR -> ShiftIR 125 | // 1 1 1 1 0 0 126 | jtag_txn_append(t, 6, 0b001111, 0b111111, NULL); 127 | } else if (dst == JTAG_DRSHIFT) { 128 | // PauseDR -> Exit2DR -> UpDR -> SelDR -> CapDR -> ShiftDR 129 | // PauseIR -> Exit2IR -> UpIR -> SelDR -> CapDR -> ShiftDR 130 | // 1 1 1 0 0 131 | jtag_txn_append(t, 5, 0b00111, 0b11111, NULL); 132 | } else if (dst == JTAG_IDLE) { 133 | // PauseDR -> Exit2DR -> UpDR -> Idle 134 | // PauseIR -> Exit2IR -> UpIR -> Idle 135 | // 1 1 0 136 | jtag_txn_append(t, 3, 0b011, 0b111, NULL); 137 | } else { 138 | goto oops; 139 | } 140 | break; 141 | case JTAG_DREXIT1: 142 | case JTAG_IREXIT1: 143 | if (dst == JTAG_IRSHIFT) { 144 | // Exit1DR -> UpDR -> SelDR -> SelIR -> CapIR -> ShiftIR 145 | // Exit1IR -> UpIR -> SelDR -> SelIR -> CapIR -> ShiftIR 146 | // 1 1 1 0 0 147 | jtag_txn_append(t, 5, 0b00111, 0b11111, NULL); 148 | } else if (dst == JTAG_DRSHIFT) { 149 | // Exit1DR -> UpDR -> SelDR -> CapDR -> ShiftDR 150 | // Exit1IR -> UpIR -> SelDR -> CapDR -> ShiftDR 151 | // 1 1 0 0 152 | jtag_txn_append(t, 4, 0b0011, 0b1111, NULL); 153 | } else if (dst == JTAG_IDLE) { 154 | // Exit1DR -> UpDR -> Idle 155 | // Exit1IR -> UpIR -> Idle 156 | // 1 0 157 | jtag_txn_append(t, 2, 0b01, 0b11, NULL); 158 | } else if (dst == JTAG_DRPAUSE) { 159 | // Exit1DR -> PauseDR 160 | // Exit1IR -> PauseIR 161 | // 0 162 | jtag_txn_append(t, 1, 0b0, 0b1, NULL); 163 | } else { 164 | goto oops; 165 | } 166 | break; 167 | default: 168 | oops: 169 | xprintf(XCORE, "jtag move from %s to %s unsupported\n", 170 | JSTATE[t->state], JSTATE[dst]); 171 | t->status = -1; 172 | t->state = JTAG_UNKNOWN; 173 | return; 174 | } 175 | t->state = dst; 176 | } 177 | 178 | void jtag_cjtag_open(jtag_txn *t) { 179 | jtag_txn_move(t, JTAG_IDLE); 180 | // Idle -> SelDR -> CapDR -> Exit1DR -> UpDR ZBS#1 181 | // 1 0 1 1 182 | // UpDR -> SelDR -> CapDR -> Exit1DR -> UpDR ZBS#2 183 | // 1 0 1 1 184 | // UpDR -> SelDR -> CapDR -> ShiftDR -> Exit1DR -> UpDR -> Idle One Bit Scan 185 | // 1 0 0 1 1 0 186 | jtag_txn_append(t, 14, 0b01100111011101, 0, NULL); 187 | } 188 | 189 | void jtag_cjtag_cmd(jtag_txn *t, unsigned cp0, unsigned cp1) { 190 | jtag_txn_move(t, JTAG_IDLE); 191 | if ((cp0 > 15) || (cp1 > 15)) { 192 | xprintf(XCORE, "jtag invalid cjtag parameters %d %d\n", cp0, cp1); 193 | t->status = -1; 194 | return; 195 | } 196 | if (cp0 == 0) { 197 | // Idle -> SelDR -> CapDR -> Exit1DR -> UpDR -> Idle 198 | // 1 0 1 1 0 199 | jtag_txn_append(t, 5, 0b01101, 0, NULL); 200 | } else { 201 | // Idle -> SelDR -> CapDR -> ShiftDR (xN) -> Exit1DR -> UpDR -> Idle 202 | // 1 0 0 1 1 0 203 | jtag_txn_append(t, 5 + cp0, ((0b011 << cp0) << 2) | 0b01, 0, NULL); 204 | } 205 | if (cp1 == 0) { 206 | // Idle -> SelDR -> CapDR -> Exit1DR -> UpDR -> Idle 207 | // 1 0 1 1 0 208 | jtag_txn_append(t, 5, 0b01101, 0, NULL); 209 | } else { 210 | // Idle -> SelDR -> CapDR -> ShiftDR (xN) -> Exit1DR -> UpDR -> Idle 211 | // 1 0 0 1 1 0 212 | jtag_txn_append(t, 5 + cp1, ((0b011 << cp1) << 2) | 0b01, 0, NULL); 213 | } 214 | } 215 | 216 | void jtag_any_to_rti(jtag_txn *t) { 217 | // 5x TMS=1 is sufficient, but throw a couple more in for luck 218 | jtag_txn_append(t, 9, 0xFF, 0x1FF, NULL); 219 | t->state = JTAG_IDLE; 220 | } 221 | 222 | static void _jtag_shiftir(jtag_txn *t, unsigned count, u64 tx, u64 *rx) { 223 | // all bits but last, tms=0 (stay in ShiftIR), last tms=1 (goto Exit1IR) 224 | if (t->state != JTAG_IRSHIFT) { 225 | xprintf(XCORE, "jtag invalid state (%s) in shiftir\n", JSTATE[t->state]); 226 | t->status = -1; 227 | } 228 | if (t->ir_pre) { 229 | jtag_txn_append(t, t->ir_pre, 0, ONES, NULL); 230 | } 231 | if (t->ir_post) { 232 | u64 tms = 1UL << (t->ir_post - 1); 233 | jtag_txn_append(t, count, 0, tx, rx); 234 | jtag_txn_append(t, t->ir_post, tms, ONES, NULL); 235 | } else { 236 | u64 tms = 1UL << (count - 1); 237 | jtag_txn_append(t, count, tms, tx, rx); 238 | } 239 | t->state = JTAG_IREXIT1; 240 | } 241 | 242 | static void _jtag_shiftdr(jtag_txn *t, unsigned count, u64 tx, u64 *rx) { 243 | if (t->state != JTAG_DRSHIFT) { 244 | xprintf(XCORE, "jtag invalid state (%s) in shiftir\n", JSTATE[t->state]); 245 | t->status = -1; 246 | } 247 | // all bits but last, tms=0 (stay in ShiftDR), last tms=1 (goto Exit1DR) 248 | if (t->dr_pre) { 249 | jtag_txn_append(t, t->dr_pre, 0, ONES, NULL); 250 | } 251 | if (t->dr_post) { 252 | u64 tms = 1UL << (t->dr_post - 1); 253 | jtag_txn_append(t, count, 0, tx, rx); 254 | jtag_txn_append(t, t->dr_post, tms, ONES, NULL); 255 | } else { 256 | u64 tms = 1UL << (count - 1); 257 | jtag_txn_append(t, count, tms, tx, rx); 258 | } 259 | t->state = JTAG_DREXIT1; 260 | } 261 | 262 | void jtag_ir(jtag_txn *t, unsigned count, u64 ir) { 263 | jtag_txn_move(t, JTAG_IRSHIFT); 264 | _jtag_shiftir(t, count, ir, NULL); 265 | jtag_txn_move(t, JTAG_IDLE); 266 | } 267 | 268 | void jtag_dr(jtag_txn *t, unsigned count, u64 dr, u64 *out) { 269 | jtag_txn_move(t, JTAG_DRSHIFT); 270 | _jtag_shiftdr(t, count, dr, out); 271 | jtag_txn_move(t, JTAG_IDLE); 272 | } 273 | 274 | void jtag_ir_p(jtag_txn *t, unsigned count, u64 ir) { 275 | jtag_txn_move(t, JTAG_IRSHIFT); 276 | _jtag_shiftir(t, count, ir, NULL); 277 | jtag_txn_move(t, JTAG_IRPAUSE); 278 | } 279 | 280 | void jtag_dr_p(jtag_txn *t, unsigned count, u64 dr, u64 *out) { 281 | jtag_txn_move(t, JTAG_DRSHIFT); 282 | _jtag_shiftdr(t, count, dr, out); 283 | jtag_txn_move(t, JTAG_DRPAUSE); 284 | } 285 | 286 | 287 | -------------------------------------------------------------------------------- /tools/jtag.h: -------------------------------------------------------------------------------- 1 | /* jtag transport 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef _JTAG_H_ 19 | #define _JTAG_H_ 20 | 21 | #define JTAG_RESET 0 22 | #define JTAG_IDLE 1 23 | #define JTAG_DRSELECT 2 24 | #define JTAG_DRCAPTURE 3 25 | #define JTAG_DRSHIFT 4 26 | #define JTAG_DREXIT1 5 27 | #define JTAG_DRPAUSE 6 28 | #define JTAG_DREXIT2 7 29 | #define JTAG_DRUPDATE 8 30 | #define JTAG_IRSELECT 9 31 | #define JTAG_IRCAPTURE 10 32 | #define JTAG_IRSHIFT 11 33 | #define JTAG_IREXIT1 12 34 | #define JTAG_IRPAUSE 13 35 | #define JTAG_IREXIT2 14 36 | #define JTAG_IRUPDATE 15 37 | #define JTAG_UNKNOWN 16 38 | 39 | 40 | #define JTAG_MAX_WORDS 256 41 | #define JTAG_MAX_BITS ((JTAG_MAX_WORDS) * 4) 42 | #define JTAG_MAX_RESULTS 256 43 | 44 | typedef struct jtag_txn { 45 | u32 tms[JTAG_MAX_WORDS]; 46 | u32 tdi[JTAG_MAX_WORDS]; 47 | u32 tdo[JTAG_MAX_WORDS]; 48 | u8 bits[JTAG_MAX_RESULTS]; 49 | u64 *ptr[JTAG_MAX_RESULTS]; 50 | unsigned txc; 51 | unsigned rxc; 52 | unsigned bitcount; 53 | int status; 54 | u32 ir_pre; 55 | u32 ir_post; 56 | u32 dr_pre; 57 | u32 dr_post; 58 | unsigned state; 59 | } jtag_txn; 60 | 61 | 62 | void jtag_txn_init(jtag_txn *tx); 63 | int jtag_txn_exec(jtag_txn *t); 64 | 65 | void jtag_txn_move(jtag_txn *t, unsigned dst); 66 | 67 | // clock out 5+ TMS 1s and get to RESET, then IDLE from anywhere 68 | void jtag_any_to_rti(jtag_txn *t); 69 | 70 | // scan into IR or DR and end in IDLE state 71 | void jtag_ir(jtag_txn *t, unsigned count, u64 ir); 72 | void jtag_dr(jtag_txn *t, unsigned count, u64 dr, u64 *out); 73 | 74 | // scan into IR or DR but end in PauseIR or PauseDR state, not IDLE 75 | void jtag_ir_p(jtag_txn *t, unsigned count, u64 ir); 76 | void jtag_dr_p(jtag_txn *t, unsigned count, u64 dr, u64 *out); 77 | 78 | void jtag_cjtag_open(jtag_txn *t); 79 | void jtag_cjtag_cmd(jtag_txn *t, unsigned cp0, unsigned cp1); 80 | 81 | // clock raw TMS/TDI bit streams, does not check or update t->state 82 | void jtag_txn_append(jtag_txn *t, unsigned count, u64 tms, u64 tdi, u64 *tdo); 83 | 84 | 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /tools/linenoise.h: -------------------------------------------------------------------------------- 1 | /* linenoise.h -- VERSION 1.0 2 | * 3 | * Guerrilla line editing library against the idea that a line editing lib 4 | * needs to be 20,000 lines of C code. 5 | * 6 | * See linenoise.c for more information. 7 | * 8 | * ------------------------------------------------------------------------ 9 | * 10 | * Copyright (c) 2010-2014, Salvatore Sanfilippo 11 | * Copyright (c) 2010-2013, Pieter Noordhuis 12 | * 13 | * All rights reserved. 14 | * 15 | * Redistribution and use in source and binary forms, with or without 16 | * modification, are permitted provided that the following conditions are 17 | * met: 18 | * 19 | * * Redistributions of source code must retain the above copyright 20 | * notice, this list of conditions and the following disclaimer. 21 | * 22 | * * Redistributions in binary form must reproduce the above copyright 23 | * notice, this list of conditions and the following disclaimer in the 24 | * documentation and/or other materials provided with the distribution. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #ifndef __LINENOISE_H 40 | #define __LINENOISE_H 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | typedef struct linenoiseCompletions { 47 | size_t len; 48 | char **cvec; 49 | } linenoiseCompletions; 50 | 51 | typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); 52 | void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); 53 | void linenoiseAddCompletion(linenoiseCompletions *, const char *); 54 | 55 | char *linenoise(const char *prompt); 56 | int linenoiseHistoryAdd(const char *line); 57 | int linenoiseHistorySetMaxLen(int len); 58 | int linenoiseHistorySave(const char *filename); 59 | int linenoiseHistoryLoad(const char *filename); 60 | void linenoiseClearScreen(void); 61 | void linenoiseSetMultiLine(int ml); 62 | void linenoisePrintKeyCodes(void); 63 | 64 | void linenoiseInit(void); 65 | void linenoisePause(void); 66 | void linenoiseResume(void); 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif /* __LINENOISE_H */ 73 | -------------------------------------------------------------------------------- /tools/lkdebug.c: -------------------------------------------------------------------------------- 1 | /* lkdebug.c 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include "rswdp.h" 25 | #include "debugger.h" 26 | #include "lkdebug.h" 27 | 28 | #define DI_MAGIC 0x52474244 29 | #define DI_OFF_MAGIC 32 30 | #define DI_OFF_PTR 36 31 | 32 | #define LK_THREAD_MAGIC 0x74687264 33 | #define LIST_OFF_PREV 0 34 | #define LIST_OFF_NEXT 4 35 | 36 | typedef struct lkdebuginfo { 37 | u32 version; 38 | u32 thread_list_ptr; 39 | u32 current_thread_ptr; 40 | u8 off_list_node; 41 | u8 off_state; 42 | u8 off_saved_sp; 43 | u8 off_was_preempted; 44 | u8 off_name; 45 | u8 off_waitq; 46 | } lkdebuginfo_t; 47 | 48 | #define LK_MAX_STATE 5 49 | static char *lkstate[] = { 50 | "SUSP ", 51 | "READY", 52 | "RUN ", 53 | "BLOCK", 54 | "SLEEP", 55 | "DEAD ", 56 | "?????", 57 | }; 58 | 59 | void dump_lk_thread(lkthread_t *t) { 60 | xprintf(XDATA, "thread: @%08x sp=%08x wq=%08x st=%d name='%s'\n", 61 | t->threadptr, t->saved_sp, t->waitq, t->state, t->name); 62 | xprintf(XDATA, " r0 %08x r4 %08x r8 %08x ip %08x\n", 63 | t->regs[0], t->regs[4], t->regs[8], t->regs[12]); 64 | xprintf(XDATA, " r1 %08x r5 %08x r9 %08x sp %08x\n", 65 | t->regs[1], t->regs[5], t->regs[9], t->regs[13]); 66 | xprintf(XDATA, " r2 %08x r6 %08x 10 %08x lr %08x\n", 67 | t->regs[2], t->regs[6], t->regs[10], t->regs[14]); 68 | xprintf(XDATA, " r3 %08x r7 %08x 11 %08x pc %08x\n", 69 | t->regs[3], t->regs[7], t->regs[11], t->regs[15]); 70 | } 71 | 72 | void dump_lk_threads(lkthread_t *t) { 73 | while (t != NULL) { 74 | dump_lk_thread(t); 75 | t = t->next; 76 | } 77 | } 78 | 79 | #define LT_NEXT_PTR(di,tp) ((tp) + di->off_list_node + LIST_OFF_NEXT) 80 | #define LT_STATE(di,tp) ((tp) + di->off_state) 81 | #define LT_SAVED_SP(di,tp) ((tp) + di->off_saved_sp) 82 | #define LT_NAME(di,tp) ((tp) + di->off_name) 83 | #define LT_WAITQ(di,tp) ((tp) + di->off_waitq) 84 | 85 | #define LIST_TO_THREAD(di,lp) ((lp) - (di)->off_list_node) 86 | 87 | static lkthread_t *read_lk_thread(lkdebuginfo_t *di, u32 ptr, int active) { 88 | lkthread_t *t = calloc(1, sizeof(lkthread_t)); 89 | u32 x; 90 | int n; 91 | if (t == NULL) goto fail; 92 | t->threadptr = ptr; 93 | if (swdp_ahb_read(ptr, &x)) goto fail; 94 | if (x != LK_THREAD_MAGIC) goto fail; 95 | if (swdp_ahb_read(LT_NEXT_PTR(di,ptr), &t->nextptr)) goto fail; 96 | if (swdp_ahb_read(LT_STATE(di,ptr), &t->state)) goto fail; 97 | if (swdp_ahb_read(LT_SAVED_SP(di,ptr), &t->saved_sp)) goto fail; 98 | if (swdp_ahb_read(LT_WAITQ(di,ptr), &t->waitq)) goto fail; 99 | if (swdp_ahb_read32(LT_NAME(di,ptr), (void*) t->name, 32 / 4)) goto fail; 100 | t->name[31] = 0; 101 | for (n = 0; n < 31; n++) { 102 | if ((t->name[n] < ' ') || (t->name[n] > 127)) { 103 | if (t->name[n] == 0) break; 104 | t->name[n] = '.'; 105 | } 106 | } 107 | if (t->state > LK_MAX_STATE) t->state = LK_MAX_STATE + 1; 108 | memset(t->regs, 0xee, sizeof(t->regs)); 109 | // lk arm-m context frame: R4 R5 R6 R7 R8 R9 R10 R11 LR 110 | // if LR is FFFFFFxx then: R0 R1 R2 R3 R12 LR PC PSR 111 | t->active = active; 112 | if (!active) { 113 | u32 fr[9]; 114 | if (swdp_ahb_read32(t->saved_sp, (void*) fr, 9)) goto fail; 115 | memcpy(t->regs + 4, fr, 8 * sizeof(u32)); 116 | if ((fr[8] & 0xFFFFFF00) == 0xFFFFFF00) { 117 | if (swdp_ahb_read32(t->saved_sp + 9 * sizeof(u32), (void*) fr, 8)) goto fail; 118 | memcpy(t->regs + 0, fr, 4 * sizeof(u32)); 119 | t->regs[12] = fr[4]; 120 | t->regs[13] = t->saved_sp + 17 * sizeof(u32); 121 | t->regs[14] = fr[5]; 122 | t->regs[15] = fr[6]; 123 | t->regs[16] = fr[7]; 124 | } else { 125 | t->regs[13] = t->saved_sp + 9 * sizeof(u32); 126 | t->regs[15] = fr[8]; 127 | t->regs[16] = 0x10000000; 128 | } 129 | } 130 | return t; 131 | fail: 132 | free(t); 133 | return NULL; 134 | } 135 | 136 | void free_lk_threads(lkthread_t *list) { 137 | lkthread_t *t, *next; 138 | for (t = list; t != NULL; t = next) { 139 | next = t->next; 140 | free(t); 141 | } 142 | } 143 | 144 | static int load_debuginfo(lkdebuginfo_t *di, int verbose) { 145 | u32 x; 146 | u32 vtbl; 147 | //read Vector Table Offset Register 148 | if (swdp_ahb_read(0xE000ED08, &vtbl)) vtbl = 0; 149 | if (swdp_ahb_read((DI_OFF_MAGIC + vtbl), &x)) return -1; 150 | if (x != DI_MAGIC) { 151 | if (verbose) xprintf(XCORE, "debuginfo: bad magic\n"); 152 | return -1; 153 | } 154 | if (swdp_ahb_read((DI_OFF_PTR + vtbl), &x)) return -1; 155 | if (x & 3) return -1; 156 | if (verbose) xprintf(XCORE, "debuginfo @ %08x\n", x); 157 | if (swdp_ahb_read32(x, (void*) di, sizeof(lkdebuginfo_t) / 4)) return -1; 158 | if (verbose) { 159 | xprintf(XDATA, "di %08x %08x %08x %d %d %d %d %d %d\n", 160 | di->version, di->thread_list_ptr, di->current_thread_ptr, 161 | di->off_list_node, di->off_state, di->off_saved_sp, 162 | di->off_was_preempted, di->off_name, di->off_waitq); 163 | } 164 | if (di->version != 0x0100) { 165 | if (verbose) xprintf(XCORE, "debuginfo: unsupported version\n"); 166 | return -1; 167 | } 168 | return 0; 169 | } 170 | 171 | void clear_lk_threads(void) { 172 | lkdebuginfo_t di; 173 | if (load_debuginfo(&di, 0)) return; 174 | swdp_ahb_write(di.current_thread_ptr, 0xffffffff); 175 | swdp_ahb_write(di.thread_list_ptr + 0, 0xffffffff); 176 | swdp_ahb_write(di.thread_list_ptr + 4, 0xffffffff); 177 | } 178 | 179 | lkthread_t *find_lk_threads(int verbose) { 180 | lkdebuginfo_t di; 181 | lkthread_t *list = NULL; 182 | lkthread_t *current = NULL; 183 | lkthread_t *t; 184 | u32 x; 185 | u32 rtp; 186 | if (load_debuginfo(&di, verbose)) goto fail; 187 | if (swdp_ahb_read(di.current_thread_ptr, &x)) goto fail; 188 | current = read_lk_thread(&di, x, 1); 189 | if (current == NULL) goto fail; 190 | rtp = di.thread_list_ptr; 191 | for (;;) { 192 | if (swdp_ahb_read(rtp + LIST_OFF_NEXT, &rtp)) goto fail; 193 | if (rtp == di.thread_list_ptr) break; 194 | x = LIST_TO_THREAD(&di, rtp); 195 | if (current->threadptr == x) continue; 196 | t = read_lk_thread(&di, x, 0); 197 | if (t == NULL) goto fail; 198 | t->next = list; 199 | list = t; 200 | } 201 | current->next = list; 202 | return current; 203 | fail: 204 | if (current) free(current); 205 | free_lk_threads(list); 206 | return NULL; 207 | } 208 | 209 | lkthread_t *find_lk_thread(lkthread_t *list, u32 tptr) { 210 | lkthread_t *t; 211 | for (t = list; t != NULL; t = t->next) { 212 | if (t->threadptr == tptr) { 213 | return t; 214 | } 215 | } 216 | return NULL; 217 | } 218 | 219 | void get_lk_thread_name(lkthread_t *t, char *out, size_t max) { 220 | snprintf(out, max, "%s - %s", lkstate[t->state], t->name); 221 | } 222 | -------------------------------------------------------------------------------- /tools/lkdebug.h: -------------------------------------------------------------------------------- 1 | /* lkdebug.h 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef _LKDEBUG_H_ 19 | #define _LKDEBUG_H_ 20 | 21 | typedef struct lkthread { 22 | struct lkthread *next; 23 | int active; 24 | u32 threadptr; 25 | u32 nextptr; 26 | u32 state; 27 | u32 saved_sp; 28 | u32 preempted; 29 | u32 waitq; 30 | char name[32]; 31 | u32 regs[17]; 32 | } lkthread_t; 33 | 34 | // probe target for lk thread info 35 | lkthread_t *find_lk_threads(int verbose); 36 | 37 | void dump_lk_thread(lkthread_t *t); 38 | void dump_lk_threads(lkthread_t *t); 39 | void free_lk_threads(lkthread_t *list); 40 | lkthread_t *find_lk_thread(lkthread_t *list, u32 tptr); 41 | void get_lk_thread_name(lkthread_t *t, char *out, size_t max); 42 | 43 | // Invalidate current thread and threadlist 44 | // Intended for use after target reset, etc. 45 | // Will corrupt a running image. 46 | void clear_lk_threads(void); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /tools/lpcboot.c: -------------------------------------------------------------------------------- 1 | /* lpcboot.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "usb.h" 26 | 27 | int usage(void) { 28 | fprintf(stderr, 29 | "lpcboot usage\n-------------\n" 30 | " lpcboot query display information about target\n" 31 | " lpcboot boot download app to ram and execute\n" 32 | " lpcboot flash write app image to flash\n" 33 | " lpcboot erase erase app image\n" 34 | " lpcboot reboot reboot the bootloader\n" 35 | " lpcboot app reboot into the app in flash\n"); 36 | return -1; 37 | } 38 | 39 | struct device_info { 40 | char part[16]; 41 | char board[16]; 42 | uint32_t version; 43 | uint32_t ram_base; 44 | uint32_t ram_size; 45 | uint32_t rom_base; 46 | uint32_t rom_size; 47 | uint32_t ununsed0; 48 | uint32_t ununsed1; 49 | uint32_t ununsed2; 50 | }; 51 | 52 | #define DFU_DETACH 0 53 | #define DFU_DNLOAD 1 54 | #define DFU_UPLOAD 2 55 | #define DFU_GETSTATUS 3 56 | #define DFU_CLRSTATUS 4 57 | #define DFU_GETSTATE 5 58 | #define DFU_ABORT 6 59 | 60 | #define STATE_APP_IDLE 0x00 61 | #define STATE_APP_DETACH 0x01 62 | #define STATE_DFU_IDLE 0x02 63 | #define STATE_DFU_DOWNLOAD_SYNC 0x03 64 | #define STATE_DFU_DOWNLOAD_BUSY 0x04 65 | #define STATE_DFU_DOWNLOAD_IDLE 0x05 66 | #define STATE_DFU_MANIFEST_SYNC 0x06 67 | #define STATE_DFU_MANIFEST 0x07 68 | #define STATE_DFU_MANIFEST_WAIT_RESET 0x08 69 | #define STATE_DFU_UPLOAD_IDLE 0x09 70 | #define STATE_DFU_ERROR 0x0a 71 | 72 | // 0xA1 getstatus: status[1] pollms[3] state[1] stridx[1] 73 | int dfu_status(usb_handle *usb, unsigned *state) { 74 | uint8_t io[6]; 75 | if (usb_ctrl(usb, io, 0xA1, DFU_GETSTATUS, 0, 0, 6) != 6) { 76 | fprintf(stderr, "dfu status: io error\n"); 77 | return -1; 78 | } 79 | if (io[0]) { 80 | fprintf(stderr, "dfu status: 0x%02x\n", io[0]); 81 | return io[0]; 82 | } 83 | *state = io[4]; 84 | return 0; 85 | } 86 | 87 | static uint8_t lpcheader[16] = { 88 | 0xda, 0xff, 0x40, 0x00, 0xff, 0xff, 0xff, 0xff, 89 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 90 | }; 91 | 92 | int dfu_download(void *_data, unsigned sz) { 93 | int once = 1; 94 | uint8_t *data = _data; 95 | usb_handle *usb; 96 | unsigned state; 97 | unsigned xfer; 98 | uint16_t count = 0; 99 | for (;;) { 100 | usb = usb_open(0x1fc9, 0x000c, 0); 101 | if (usb == 0) { 102 | if (once) { 103 | fprintf(stderr,"waiting for DFU device...\n"); 104 | once = 0; 105 | } 106 | } else { 107 | break; 108 | } 109 | } 110 | if (dfu_status(usb, &state)) return -1; 111 | if (state != STATE_DFU_IDLE) { 112 | fprintf(stderr, "dfu state not idle (0x%02x)?\n", state); 113 | return -1; 114 | } 115 | 116 | // prepend isp header 117 | data -= 16; 118 | sz += 16; 119 | memcpy(data, lpcheader, 16); 120 | 121 | // send binary 122 | while (sz > 0) { 123 | fprintf(stderr,"."); 124 | xfer = (sz > 2048) ? 2048 : sz; 125 | if (usb_ctrl(usb, data, 0x21, DFU_DNLOAD, count, 0, xfer) != xfer) { 126 | fprintf(stderr,"\ndfu dnload: io error\n"); 127 | return -1; 128 | } 129 | count++; 130 | data += xfer; 131 | sz -= xfer; 132 | if (dfu_status(usb, &state)) return -1; 133 | if (state != STATE_DFU_DOWNLOAD_IDLE) { 134 | fprintf(stderr,"\ndfu dnload state 0x%02x?!\n", state); 135 | return -1; 136 | } 137 | } 138 | if (usb_ctrl(usb, NULL, 0x21, DFU_DNLOAD, 0, 0, 0) != 0) { 139 | fprintf(stderr,"\ndfu dnload2: io error\n"); 140 | return -1; 141 | } 142 | fprintf(stderr,"\ndone\n"); 143 | if (dfu_status(usb, &state)) return -1; 144 | if (state == STATE_DFU_MANIFEST_WAIT_RESET) return 0; 145 | fprintf(stderr,"dfu dnload2: state 0x%02x?!\n", state); 146 | return -1; 147 | } 148 | 149 | int main(int argc, char **argv) { 150 | usb_handle *usb; 151 | char buf[1024*1024+256]; 152 | int fd, once = 1, sz = 0, dl = 0, dfu = 0; 153 | uint32_t cmd[3]; 154 | uint32_t rep[2]; 155 | struct device_info di; 156 | 157 | if (argc < 2) 158 | return usage(); 159 | 160 | cmd[0] = 0xDB00A5A5; 161 | if (!strcmp(argv[1],"flash")) { 162 | dl = 1; 163 | cmd[1] = 'W'; 164 | } else if (!strcmp(argv[1],"flash:boot")) { 165 | dl = 1; 166 | cmd[1] = 'w'; 167 | } else if (!strcmp(argv[1],"boot")) { 168 | dl = 1; 169 | cmd[1] = 'X'; 170 | } else if (!strcmp(argv[1],"erase")) { 171 | cmd[1] = 'E'; 172 | } else if (!strcmp(argv[1],"query")) { 173 | cmd[1] = 'Q'; 174 | } else if (!strcmp(argv[1],"reboot")) { 175 | cmd[1] = 'R'; 176 | } else if (!strcmp(argv[1],"app")) { 177 | cmd[1] = 'A'; 178 | } else if (!strcmp(argv[1],"dfu")) { 179 | dl = 1; 180 | dfu = 1; 181 | } else { 182 | return usage(); 183 | } 184 | 185 | if (dl) { 186 | if (argc < 3) 187 | return usage(); 188 | fd = open(argv[2], O_RDONLY); 189 | sz = read(fd, buf + 256, sizeof(buf) - 256); 190 | close(fd); 191 | if ((fd < 0) || (sz < 1)) { 192 | fprintf(stderr,"error: cannot read '%s'\n", argv[2]); 193 | return -1; 194 | } 195 | } 196 | cmd[2] = sz; 197 | 198 | if (dfu) { 199 | return dfu_download(buf + 256, sz); 200 | } 201 | for (;;) { 202 | usb = usb_open(0x1209, 0x5039, 0); 203 | if (usb == 0) { 204 | usb = usb_open(0x18d1, 0xdb00, 0); 205 | } 206 | if (usb == 0) { 207 | if (once) { 208 | fprintf(stderr,"waiting for device...\n"); 209 | once = 0; 210 | } 211 | } else { 212 | break; 213 | } 214 | } 215 | 216 | if (usb_write(usb, cmd, 12) != 12) { 217 | fprintf(stderr,"io error\n"); 218 | return -1; 219 | } 220 | for (;;) { 221 | if (usb_read(usb, rep, 8) != 8) { 222 | fprintf(stderr,"io error\n"); 223 | return -1; 224 | } 225 | if (rep[0] != 0xDB00A5A5) { 226 | fprintf(stderr,"protocol error\n"); 227 | return -1; 228 | } 229 | if (rep[1] != 0) { 230 | fprintf(stderr,"%s failure\n", argv[1]); 231 | return -1; 232 | } 233 | if (!strcmp(argv[1],"query")) { 234 | if (usb_read(usb, &di, sizeof(di)) != sizeof(di)) { 235 | fprintf(stderr,"io error\n"); 236 | return -1; 237 | } 238 | fprintf(stderr,"Part: %s\n", di.part); 239 | fprintf(stderr,"Board: %s\n", di.board); 240 | fprintf(stderr,"RAM: @%08x (%dKB)\n", 241 | di.ram_base, di.ram_size / 1024); 242 | fprintf(stderr,"Flash: @%08x (%dKB)\n", 243 | di.rom_base, di.rom_size / 1024); 244 | return 0; 245 | } 246 | if (!dl) 247 | break; 248 | fprintf(stderr,"sending %d bytes...\n", sz); 249 | if (usb_write(usb, buf + 256, sz) != sz) { 250 | fprintf(stderr,"download failure %d\n", sz); 251 | return -1; 252 | } 253 | dl = 0; 254 | } 255 | fprintf(stderr,"OKAY\n"); 256 | return 0; 257 | } 258 | -------------------------------------------------------------------------------- /tools/mkbuiltins.c: -------------------------------------------------------------------------------- 1 | /* mkbuiltin.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | void *load_file(const char *fn, size_t *_sz) { 25 | int fd; 26 | off_t sz; 27 | void *data = NULL; 28 | fd = open(fn, O_RDONLY); 29 | if (fd < 0) goto fail; 30 | sz = lseek(fd, 0, SEEK_END); 31 | if (sz < 0) goto fail; 32 | if (lseek(fd, 0, SEEK_SET)) goto fail; 33 | if ((data = malloc(sz + 4)) == NULL) goto fail; 34 | if (read(fd, data, sz) != sz) goto fail; 35 | *_sz = sz; 36 | return data; 37 | fail: 38 | if (data) free(data); 39 | if (fd >= 0) close(fd); 40 | return NULL; 41 | } 42 | 43 | typedef struct entry { 44 | struct entry *next; 45 | const char *fn; 46 | void *data; 47 | size_t sz; 48 | } entry; 49 | 50 | entry *first = NULL, *last = NULL; 51 | 52 | int import(const char *fn) { 53 | char *x; 54 | entry *e = malloc(sizeof(entry)); 55 | if (e == NULL) return -1; 56 | e->data = load_file(fn, &e->sz); 57 | if (e->data == NULL) return -1; 58 | if ((x = strrchr(fn, '/'))) { 59 | e->fn = x + 1; 60 | } else { 61 | e->fn = fn; 62 | } 63 | e->next = NULL; 64 | if (last) { 65 | last->next = e; 66 | } else { 67 | first = e; 68 | } 69 | last = e; 70 | return 0; 71 | } 72 | 73 | void exportline(unsigned char *x, int len) { 74 | printf("\t\""); 75 | while (len > 0) { 76 | printf("\\x%02X", *x++); 77 | len--; 78 | } 79 | printf("\"\n"); 80 | } 81 | 82 | void export(entry *e) { 83 | unsigned char *x = e->data; 84 | size_t len = e->sz; 85 | printf("\t{ \"%s\", %zu,\n", e->fn, e->sz); 86 | while (len > 0) { 87 | int xfer = (len > 16) ? 16 : len; 88 | exportline(x, xfer); 89 | x += xfer; 90 | len -= xfer; 91 | } 92 | printf("\t},\n"); 93 | } 94 | 95 | int main(int argc, char **argv) { 96 | entry *e; 97 | 98 | while (argc > 1) { 99 | if (import(argv[1])) return -1; 100 | argc--; 101 | argv++; 102 | } 103 | 104 | printf( 105 | "/* this file is machine-generated by mkbuiltins -- do not modify */\n\n" 106 | "#include \n" 107 | "#include \n\n" 108 | "static struct {\n" 109 | " const char *name;\n" 110 | " size_t size;\n" 111 | " void *data;\n" 112 | "} files[] = {\n" 113 | ); 114 | for (e = first; e != NULL; e = e->next) { 115 | export(e); 116 | } 117 | printf( 118 | "};\n\n" 119 | "void *get_builtin_file(const char *name, size_t *sz) {\n" 120 | " int n;\n" 121 | " for (n = 0; n < (sizeof(files)/sizeof(files[0])); n++) {\n" 122 | " if (!strcmp(name, files[n].name)) {\n" 123 | " *sz = files[n].size;\n" 124 | " return files[n].data;\n" 125 | " }\n" 126 | " }\n" 127 | " return NULL;\n" 128 | "}\n" 129 | "\n" 130 | "const char *get_builtin_filename(unsigned n) {\n" 131 | " if (n >= (sizeof(files)/sizeof(files[0]))) {\n" 132 | " return NULL;\n" 133 | " }\n" 134 | " return files[n].name;\n" 135 | "}\n" 136 | ); 137 | 138 | return 0; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /tools/picoboot.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020, Brian Swetland 2 | // Licensed under the Apache License, Version 2.0. 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #define ERASE_MASK (4096 - 1) 14 | #define BLOCK_MASK (256 - 1) 15 | 16 | void *load_file(const char *fn, size_t *_sz) { 17 | int fd; 18 | off_t sz; 19 | void *data = NULL; 20 | fd = open(fn, O_RDONLY); 21 | if (fd < 0) goto fail; 22 | sz = lseek(fd, 0, SEEK_END); 23 | if (sz < 0) goto fail; 24 | if (lseek(fd, 0, SEEK_SET)) goto fail; 25 | if ((data = malloc(sz)) == NULL) goto fail; 26 | if (read(fd, data, sz) != sz) goto fail; 27 | *_sz = sz; 28 | return data; 29 | fail: 30 | if (data) free(data); 31 | if (fd >= 0) close(fd); 32 | return NULL; 33 | } 34 | 35 | #define PB_VID 0x2e8a 36 | #define PB_PID 0x0003 37 | 38 | #define PB_IFC 1 39 | #define PB_EP_IN 0x84 40 | #define PB_EP_OUT 0x03 41 | 42 | #define PB_MAGIC 0x431fd10b 43 | 44 | typedef struct { 45 | uint32_t magic; 46 | uint32_t token; 47 | uint8_t cmdid; 48 | uint8_t argslen; 49 | uint16_t reserved; 50 | uint32_t xferlen; 51 | union { 52 | uint8_t u8[16]; 53 | uint32_t u32[4]; 54 | }; 55 | } pbcmd_t; 56 | 57 | typedef struct { 58 | uint32_t token; 59 | uint32_t status; 60 | uint8_t cmd; 61 | uint8_t busy; 62 | uint8_t reserved[6]; 63 | } pbstatus_t; 64 | 65 | #define CMD_EXCLUSIVE_ACCESS 0x01 // excl:u8 66 | #define CMD_REBOOT 0x02 // pc:u32 sp:u32 delay:u32 67 | #define CMD_FLASH_ERASE 0x03 // addr:u32 size:u32 68 | #define CMD_READ 0x04 // addr:u32 size:u32 69 | #define CMD_WRITE 0x05 // addr:u32 size:u32 70 | #define CMD_EXIT_XIP 0x06 71 | #define CMD_ENTER_XIP 0x07 72 | #define CMD_EXEC 0x08 // addr:u32 73 | #define CMD_VECTORIZE_FLASH 0x09 // addr:u32 74 | 75 | #define EA_NOT 0 76 | #define EA_EXCLUSIVE 1 77 | #define EA_EXCLUSIVE_AND_EJECT 2 78 | 79 | static libusb_context* usbctx = NULL; 80 | static libusb_device_handle* usbdev = NULL; 81 | static uint32_t token = 0; 82 | 83 | int pb_status(void) { 84 | pbstatus_t pbs; 85 | int r = libusb_control_transfer(usbdev, 86 | LIBUSB_REQUEST_TYPE_VENDOR | 87 | LIBUSB_RECIPIENT_INTERFACE | 88 | LIBUSB_ENDPOINT_IN, 89 | 0x42, 0, 1, (void*) &pbs, sizeof(pbs), 1000); 90 | if (r != sizeof(pbs)) { 91 | fprintf(stderr, "picoboot: cannot read status %d\n", r); 92 | return -1; 93 | } 94 | fprintf(stderr, "picoboot: status: tok=%08x sts=%08x cmd=%02x busy=%02x\n", 95 | pbs.token, pbs.status, pbs.cmd, pbs.busy); 96 | return pbs.status; 97 | } 98 | 99 | int TRACE = 0; 100 | 101 | int pb_txn(pbcmd_t* cmd, void* data, int tx) { 102 | cmd->magic = PB_MAGIC; 103 | cmd->token = token++; 104 | int xfer; 105 | int r; 106 | uint8_t tmp[64]; 107 | 108 | if (TRACE) fprintf(stderr, "picoboot: txn cmd=%02x len=%u\n", cmd->cmdid, cmd->xferlen); 109 | if ((r = libusb_bulk_transfer(usbdev, PB_EP_OUT, (void*) cmd, sizeof(pbcmd_t), &xfer, 0)) < 0) { 110 | fprintf(stderr, "picoboot: usb error sending command %d\n", r); 111 | pb_status(); 112 | return r; 113 | } 114 | if (TRACE) pb_status(); 115 | 116 | if (tx && (cmd->xferlen > 0)) { 117 | xfer = 0; 118 | if ((r = libusb_bulk_transfer(usbdev, PB_EP_OUT, data, cmd->xferlen, &xfer, 5000)) < 0) { 119 | fprintf(stderr, "xfer %u\n", xfer); 120 | fprintf(stderr, "picoboot: usb error sending payload %d\n", r); 121 | pb_status(); 122 | return r; 123 | } 124 | } 125 | 126 | xfer = 0; 127 | if ((r = libusb_bulk_transfer(usbdev, PB_EP_IN, tmp, 64, &xfer, 0)) < 0) { 128 | fprintf(stderr, "xfer %u\n", xfer); 129 | fprintf(stderr, "picoboot: usb error receiving ack %d\n", r); 130 | pb_status(); 131 | return -1; 132 | } 133 | 134 | if (TRACE) pb_status(); 135 | return 0; 136 | } 137 | 138 | void usage(void) { 139 | fprintf(stderr, 140 | "usage: picoboot ( cmd )*\n" 141 | "\n" 142 | "commands: -flash ( @hex ) write file to flash\n" 143 | " -reboot reboot device\n" 144 | " -help show this\n" 145 | ); 146 | } 147 | 148 | int pb_io(uint8_t _cmd, uint32_t addr, uint32_t size, void* data) { 149 | pbcmd_t cmd; 150 | memset(&cmd, 0, sizeof(cmd)); 151 | cmd.cmdid = _cmd; 152 | cmd.argslen = 8; 153 | cmd.u32[0] = addr; 154 | cmd.u32[1] = size; 155 | if (data) cmd.xferlen = size; 156 | return pb_txn(&cmd, data, 1); 157 | } 158 | 159 | int pb_cmd(uint8_t _cmd) { 160 | pbcmd_t cmd; 161 | memset(&cmd, 0, sizeof(cmd)); 162 | cmd.cmdid = _cmd; 163 | switch (_cmd) { 164 | case CMD_EXCLUSIVE_ACCESS: 165 | cmd.argslen = 1; 166 | cmd.u8[0] = EA_EXCLUSIVE; 167 | break; 168 | case CMD_REBOOT: 169 | cmd.argslen = 12; 170 | cmd.u32[2] = 100; // ms 171 | break; 172 | } 173 | return pb_txn(&cmd, NULL, 0); 174 | } 175 | 176 | int main(int argc, char** argv) { 177 | if (argc == 1) { 178 | usage(); 179 | return 0; 180 | } 181 | 182 | if (libusb_init(&usbctx) < 0) return -1; 183 | if ((usbdev = libusb_open_device_with_vid_pid(usbctx, PB_VID, PB_PID)) == NULL) { 184 | fprintf(stderr, "picoboot: cannot find compatible device\n"); 185 | return -1; 186 | } 187 | if ((libusb_claim_interface(usbdev, PB_IFC)) < 0) { 188 | fprintf(stderr, "picoboot: cannot claim interface\n"); 189 | return -1; 190 | } 191 | libusb_clear_halt(usbdev, PB_EP_IN); 192 | libusb_clear_halt(usbdev, PB_EP_OUT); 193 | 194 | size_t sz; 195 | void* data; 196 | for (argc--, argv++; argc > 0; argc--, argv++) { 197 | if (!strcmp(argv[0], "-reboot")) { 198 | if (pb_cmd(CMD_REBOOT)) { 199 | fprintf(stderr, "picoboot: REBOOT failed\n"); 200 | return -1; 201 | } 202 | } else if (!strcmp(argv[0], "-flash")) { 203 | const char *fn = argv[1]; 204 | if (argc < 2) { 205 | fprintf(stderr, "picoboot: missing argument\n"); 206 | return -1; 207 | } 208 | if ((data = load_file(fn, &sz)) == NULL) { 209 | fprintf(stderr, "picoboot: failed to load '%s'\n", fn); 210 | return -1; 211 | } 212 | argc--; argv++; 213 | uint32_t addr = 0x10000000; 214 | if ((argc > 1) && (argv[1][0] == '@')) { 215 | addr = strtoul(argv[1] + 1, NULL, 16); 216 | argc--; argv++; 217 | } 218 | if ((addr < 0x10000000) || (addr >= 0x11000000) || (addr & ERASE_MASK)) { 219 | fprintf(stderr, "picoboot: bad flash start address 0x%08x\n", addr); 220 | return -1; 221 | } 222 | if (pb_cmd(CMD_EXCLUSIVE_ACCESS)) { 223 | fprintf(stderr, "picoboot: EXCLUSIVE ACCESS failed\n"); 224 | return -1; 225 | } 226 | if (pb_cmd(CMD_EXIT_XIP)) { 227 | fprintf(stderr, "picoboot: EXIT XIP failed\n"); 228 | return -1; 229 | } 230 | fprintf(stderr, "picoboot: erase flash @ 0x%08x\n", addr); 231 | if (pb_io(CMD_FLASH_ERASE, addr, (sz + ERASE_MASK) & (~ERASE_MASK), NULL)) { 232 | fprintf(stderr, "picoboot: ERASE failed\n"); 233 | return -1; 234 | } 235 | fprintf(stderr, "picoboot: write '%s' to flash @ 0x%08x\n", fn, addr); 236 | if (pb_io(CMD_WRITE, addr, sz, data)) { 237 | fprintf(stderr, "picoboot: WRITE failed\n"); 238 | return -1; 239 | } 240 | } else if (!strcmp(argv[0], "-help")) { 241 | usage(); 242 | return 0; 243 | } else { 244 | fprintf(stderr, "picoboot: unknown command '%s'\n", argv[0]); 245 | usage(); 246 | return -1; 247 | } 248 | } 249 | 250 | return 0; 251 | } 252 | -------------------------------------------------------------------------------- /tools/rswdp.h: -------------------------------------------------------------------------------- 1 | /* rswdp.h 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef _RSWDP_H__ 19 | #define _RSWDP_H__ 20 | 21 | int swdp_open(void); 22 | 23 | void swdp_enable_tracing(int yes); 24 | 25 | void swdp_target_reset(int enable); 26 | 27 | int swdp_bootloader(void); 28 | int swdp_set_clock(unsigned khz); 29 | int swo_set_clock(unsigned khz); 30 | 31 | int jtag_io(unsigned count, u32 *tms, u32 *tdi, u32 *tdo); 32 | 33 | void swdp_interrupt(void); 34 | 35 | /* these are now above the transport layer and should be renamed... */ 36 | 37 | /* return 0 when *addr != oldval, -1 on error, -2 on interrupt */ 38 | int swdp_ahb_wait_for_change(u32 addr, u32 oldval); 39 | 40 | int swdp_core_halt(void); 41 | int swdp_core_step(void); 42 | int swdp_core_resume(void); 43 | 44 | /* return 0 when CPU halts, -1 if an error occurs, or -2 if interrupted */ 45 | int swdp_core_wait_for_halt(void); 46 | 47 | /* access to CPU registers */ 48 | int swdp_core_read(u32 n, u32 *v); 49 | int swdp_core_read_all(u32 *v); 50 | int swdp_core_write(u32 n, u32 v); 51 | 52 | int swdp_watchpoint_pc(unsigned n, u32 addr); 53 | int swdp_watchpoint_rd(unsigned n, u32 addr); 54 | int swdp_watchpoint_wr(unsigned n, u32 addr); 55 | int swdp_watchpoint_rw(unsigned n, u32 addr); 56 | int swdp_watchpoint_disable(unsigned n); 57 | 58 | void swdp_targetsel(u32 val, unsigned on); 59 | 60 | /* these are now provided by the transport layer */ 61 | //int swdp_reset(void); 62 | //int swdp_error(void); 63 | //int swdp_clear_error(void); 64 | //int swdp_ahb_read(u32 addr, u32 *value); 65 | //int swdp_ahb_write(u32 addr, u32 value); 66 | // bulk reads/writes (more efficient after ~3-4 words 67 | // int swdp_ahb_read32(u32 addr, u32 *out, int count); 68 | // int swdp_ahb_write32(u32 addr, u32 *out, int count); 69 | #define swdp_reset debug_attach 70 | #define swdp_error debug_error 71 | #define swdp_clear_error debug_clear_error 72 | #define swdp_ahb_read mem_rd_32 73 | #define swdp_ahb_write mem_wr_32 74 | #define swdp_ahb_read32 mem_rd_32_c 75 | #define swdp_ahb_write32 mem_wr_32_c 76 | 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /tools/sha1.c: -------------------------------------------------------------------------------- 1 | /* sha.c 2 | ** 3 | ** Copyright 2008, The Android Open Source Project 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are met: 7 | ** * Redistributions of source code must retain the above copyright 8 | ** notice, this list of conditions and the following disclaimer. 9 | ** * Redistributions in binary form must reproduce the above copyright 10 | ** notice, this list of conditions and the following disclaimer in the 11 | ** documentation and/or other materials provided with the distribution. 12 | ** * Neither the name of Google Inc. nor the names of its contributors may 13 | ** be used to endorse or promote products derived from this software 14 | ** without specific prior written permission. 15 | ** 16 | ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 17 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "sha1.h" 29 | 30 | // Some machines lack byteswap.h and endian.h. These have to use the 31 | // slower code, even if they're little-endian. 32 | 33 | #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN) 34 | 35 | #include 36 | #include 37 | 38 | // This version is about 28% faster than the generic version below, 39 | // but assumes little-endianness. 40 | 41 | static inline uint32_t ror27(uint32_t val) { 42 | return (val >> 27) | (val << 5); 43 | } 44 | static inline uint32_t ror2(uint32_t val) { 45 | return (val >> 2) | (val << 30); 46 | } 47 | static inline uint32_t ror31(uint32_t val) { 48 | return (val >> 31) | (val << 1); 49 | } 50 | 51 | static void SHA1_Transform(SHA_CTX* ctx) { 52 | uint32_t W[80]; 53 | register uint32_t A, B, C, D, E; 54 | int t; 55 | 56 | A = ctx->state[0]; 57 | B = ctx->state[1]; 58 | C = ctx->state[2]; 59 | D = ctx->state[3]; 60 | E = ctx->state[4]; 61 | 62 | #define SHA_F1(A,B,C,D,E,t) \ 63 | E += ror27(A) + \ 64 | (W[t] = bswap_32(ctx->buf.w[t])) + \ 65 | (D^(B&(C^D))) + 0x5A827999; \ 66 | B = ror2(B); 67 | 68 | for (t = 0; t < 15; t += 5) { 69 | SHA_F1(A,B,C,D,E,t + 0); 70 | SHA_F1(E,A,B,C,D,t + 1); 71 | SHA_F1(D,E,A,B,C,t + 2); 72 | SHA_F1(C,D,E,A,B,t + 3); 73 | SHA_F1(B,C,D,E,A,t + 4); 74 | } 75 | SHA_F1(A,B,C,D,E,t + 0); // 16th one, t == 15 76 | 77 | #undef SHA_F1 78 | 79 | #define SHA_F1(A,B,C,D,E,t) \ 80 | E += ror27(A) + \ 81 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ 82 | (D^(B&(C^D))) + 0x5A827999; \ 83 | B = ror2(B); 84 | 85 | SHA_F1(E,A,B,C,D,t + 1); 86 | SHA_F1(D,E,A,B,C,t + 2); 87 | SHA_F1(C,D,E,A,B,t + 3); 88 | SHA_F1(B,C,D,E,A,t + 4); 89 | 90 | #undef SHA_F1 91 | 92 | #define SHA_F2(A,B,C,D,E,t) \ 93 | E += ror27(A) + \ 94 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ 95 | (B^C^D) + 0x6ED9EBA1; \ 96 | B = ror2(B); 97 | 98 | for (t = 20; t < 40; t += 5) { 99 | SHA_F2(A,B,C,D,E,t + 0); 100 | SHA_F2(E,A,B,C,D,t + 1); 101 | SHA_F2(D,E,A,B,C,t + 2); 102 | SHA_F2(C,D,E,A,B,t + 3); 103 | SHA_F2(B,C,D,E,A,t + 4); 104 | } 105 | 106 | #undef SHA_F2 107 | 108 | #define SHA_F3(A,B,C,D,E,t) \ 109 | E += ror27(A) + \ 110 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ 111 | ((B&C)|(D&(B|C))) + 0x8F1BBCDC; \ 112 | B = ror2(B); 113 | 114 | for (; t < 60; t += 5) { 115 | SHA_F3(A,B,C,D,E,t + 0); 116 | SHA_F3(E,A,B,C,D,t + 1); 117 | SHA_F3(D,E,A,B,C,t + 2); 118 | SHA_F3(C,D,E,A,B,t + 3); 119 | SHA_F3(B,C,D,E,A,t + 4); 120 | } 121 | 122 | #undef SHA_F3 123 | 124 | #define SHA_F4(A,B,C,D,E,t) \ 125 | E += ror27(A) + \ 126 | (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ 127 | (B^C^D) + 0xCA62C1D6; \ 128 | B = ror2(B); 129 | 130 | for (; t < 80; t += 5) { 131 | SHA_F4(A,B,C,D,E,t + 0); 132 | SHA_F4(E,A,B,C,D,t + 1); 133 | SHA_F4(D,E,A,B,C,t + 2); 134 | SHA_F4(C,D,E,A,B,t + 3); 135 | SHA_F4(B,C,D,E,A,t + 4); 136 | } 137 | 138 | #undef SHA_F4 139 | 140 | ctx->state[0] += A; 141 | ctx->state[1] += B; 142 | ctx->state[2] += C; 143 | ctx->state[3] += D; 144 | ctx->state[4] += E; 145 | } 146 | 147 | void SHA_update(SHA_CTX* ctx, const void* data, int len) { 148 | int i = ctx->count % sizeof(ctx->buf); 149 | const uint8_t* p = (const uint8_t*)data; 150 | 151 | ctx->count += len; 152 | 153 | while (len > sizeof(ctx->buf) - i) { 154 | memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i); 155 | len -= sizeof(ctx->buf) - i; 156 | p += sizeof(ctx->buf) - i; 157 | SHA1_Transform(ctx); 158 | i = 0; 159 | } 160 | 161 | while (len--) { 162 | ctx->buf.b[i++] = *p++; 163 | if (i == sizeof(ctx->buf)) { 164 | SHA1_Transform(ctx); 165 | i = 0; 166 | } 167 | } 168 | } 169 | 170 | 171 | const uint8_t* SHA_final(SHA_CTX* ctx) { 172 | uint64_t cnt = ctx->count * 8; 173 | int i; 174 | 175 | SHA_update(ctx, (uint8_t*)"\x80", 1); 176 | while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) { 177 | SHA_update(ctx, (uint8_t*)"\0", 1); 178 | } 179 | for (i = 0; i < 8; ++i) { 180 | uint8_t tmp = cnt >> ((7 - i) * 8); 181 | SHA_update(ctx, &tmp, 1); 182 | } 183 | 184 | for (i = 0; i < 5; i++) { 185 | ctx->buf.w[i] = bswap_32(ctx->state[i]); 186 | } 187 | 188 | return ctx->buf.b; 189 | } 190 | 191 | #else // #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN) 192 | 193 | #define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits)))) 194 | 195 | static void SHA1_transform(SHA_CTX *ctx) { 196 | uint32_t W[80]; 197 | uint32_t A, B, C, D, E; 198 | uint8_t *p = ctx->buf; 199 | int t; 200 | 201 | for(t = 0; t < 16; ++t) { 202 | uint32_t tmp = *p++ << 24; 203 | tmp |= *p++ << 16; 204 | tmp |= *p++ << 8; 205 | tmp |= *p++; 206 | W[t] = tmp; 207 | } 208 | 209 | for(; t < 80; t++) { 210 | W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 211 | } 212 | 213 | A = ctx->state[0]; 214 | B = ctx->state[1]; 215 | C = ctx->state[2]; 216 | D = ctx->state[3]; 217 | E = ctx->state[4]; 218 | 219 | for(t = 0; t < 80; t++) { 220 | uint32_t tmp = rol(5,A) + E + W[t]; 221 | 222 | if (t < 20) 223 | tmp += (D^(B&(C^D))) + 0x5A827999; 224 | else if ( t < 40) 225 | tmp += (B^C^D) + 0x6ED9EBA1; 226 | else if ( t < 60) 227 | tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC; 228 | else 229 | tmp += (B^C^D) + 0xCA62C1D6; 230 | 231 | E = D; 232 | D = C; 233 | C = rol(30,B); 234 | B = A; 235 | A = tmp; 236 | } 237 | 238 | ctx->state[0] += A; 239 | ctx->state[1] += B; 240 | ctx->state[2] += C; 241 | ctx->state[3] += D; 242 | ctx->state[4] += E; 243 | } 244 | 245 | void SHA_update(SHA_CTX *ctx, const void *data, int len) { 246 | int i = ctx->count % sizeof(ctx->buf); 247 | const uint8_t* p = (const uint8_t*)data; 248 | 249 | ctx->count += len; 250 | 251 | while (len--) { 252 | ctx->buf[i++] = *p++; 253 | if (i == sizeof(ctx->buf)) { 254 | SHA1_transform(ctx); 255 | i = 0; 256 | } 257 | } 258 | } 259 | const uint8_t *SHA_final(SHA_CTX *ctx) { 260 | uint8_t *p = ctx->buf; 261 | uint64_t cnt = ctx->count * 8; 262 | int i; 263 | 264 | SHA_update(ctx, (uint8_t*)"\x80", 1); 265 | while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) { 266 | SHA_update(ctx, (uint8_t*)"\0", 1); 267 | } 268 | for (i = 0; i < 8; ++i) { 269 | uint8_t tmp = cnt >> ((7 - i) * 8); 270 | SHA_update(ctx, &tmp, 1); 271 | } 272 | 273 | for (i = 0; i < 5; i++) { 274 | uint32_t tmp = ctx->state[i]; 275 | *p++ = tmp >> 24; 276 | *p++ = tmp >> 16; 277 | *p++ = tmp >> 8; 278 | *p++ = tmp >> 0; 279 | } 280 | 281 | return ctx->buf; 282 | } 283 | 284 | #endif // endianness 285 | 286 | void SHA_init(SHA_CTX* ctx) { 287 | ctx->state[0] = 0x67452301; 288 | ctx->state[1] = 0xEFCDAB89; 289 | ctx->state[2] = 0x98BADCFE; 290 | ctx->state[3] = 0x10325476; 291 | ctx->state[4] = 0xC3D2E1F0; 292 | ctx->count = 0; 293 | } 294 | 295 | /* Convenience function */ 296 | const uint8_t* SHA(const void *data, int len, uint8_t *digest) { 297 | const uint8_t *p; 298 | int i; 299 | SHA_CTX ctx; 300 | SHA_init(&ctx); 301 | SHA_update(&ctx, data, len); 302 | p = SHA_final(&ctx); 303 | for (i = 0; i < SHA_DIGEST_SIZE; ++i) { 304 | digest[i] = *p++; 305 | } 306 | return digest; 307 | } 308 | -------------------------------------------------------------------------------- /tools/sha1.h: -------------------------------------------------------------------------------- 1 | /* sha.h 2 | ** 3 | ** Copyright 2008, The Android Open Source Project 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are met: 7 | ** * Redistributions of source code must retain the above copyright 8 | ** notice, this list of conditions and the following disclaimer. 9 | ** * Redistributions in binary form must reproduce the above copyright 10 | ** notice, this list of conditions and the following disclaimer in the 11 | ** documentation and/or other materials provided with the distribution. 12 | ** * Neither the name of Google Inc. nor the names of its contributors may 13 | ** be used to endorse or promote products derived from this software 14 | ** without specific prior written permission. 15 | ** 16 | ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 17 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _EMBEDDED_SHA_H_ 29 | #define _EMBEDDED_SHA_H_ 30 | 31 | #include 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | typedef struct SHA_CTX { 38 | uint64_t count; 39 | uint32_t state[5]; 40 | #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN) 41 | union { 42 | uint8_t b[64]; 43 | uint32_t w[16]; 44 | } buf; 45 | #else 46 | uint8_t buf[64]; 47 | #endif 48 | } SHA_CTX; 49 | 50 | void SHA_init(SHA_CTX* ctx); 51 | void SHA_update(SHA_CTX* ctx, const void* data, int len); 52 | const uint8_t* SHA_final(SHA_CTX* ctx); 53 | 54 | /* Convenience method. Returns digest parameter value. */ 55 | const uint8_t* SHA(const void* data, int len, uint8_t* digest); 56 | 57 | #define SHA_DIGEST_SIZE 20 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /tools/socket.c: -------------------------------------------------------------------------------- 1 | /* socket.c 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | int socket_listen_tcp(unsigned port) { 25 | int fd, n = 1; 26 | struct sockaddr_in addr; 27 | 28 | if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 29 | return -1; 30 | } 31 | 32 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); 33 | 34 | memset(&addr, 0, sizeof(addr)); 35 | addr.sin_family = AF_INET; 36 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 37 | addr.sin_port = htons(port); 38 | if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 39 | goto fail; 40 | } 41 | if (listen(fd, 10) < 0) { 42 | goto fail; 43 | } 44 | return fd; 45 | fail: 46 | close(fd); 47 | return -1; 48 | } 49 | -------------------------------------------------------------------------------- /tools/stm32boot.c: -------------------------------------------------------------------------------- 1 | /* stm32boot.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #if 0 35 | int WRITE(int fd, void *ptr, int len) { 36 | int r; 37 | fprintf(stderr,"["); 38 | for (r = 0; r < len; r++) 39 | fprintf(stderr," %02x", ((unsigned char *) ptr)[r]); 40 | fprintf(stderr," ]\n"); 41 | return write(fd, ptr, len); 42 | } 43 | 44 | int READ(int fd, void *ptr, int len) { 45 | int n, r; 46 | r = read(fd, ptr, len); 47 | if (r <= 0) { 48 | fprintf(stderr,"\n"); 49 | return r; 50 | } 51 | fprintf(stderr,"<"); 52 | for (n = 0; n < len; n++) 53 | fprintf(stderr," %02x", ((unsigned char *) ptr)[n]); 54 | fprintf(stderr," >\n"); 55 | return r; 56 | } 57 | 58 | #define read READ 59 | #define write WRITE 60 | #endif 61 | 62 | int openserial(const char *device, int speed) 63 | { 64 | struct termios tio; 65 | int fd; 66 | fd = open(device, O_RDWR | O_NOCTTY);// | O_NDELAY); 67 | 68 | if (fd < 0) 69 | return -1; 70 | 71 | if (tcgetattr(fd, &tio)) 72 | memset(&tio, 0, sizeof(tio)); 73 | 74 | tio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | PARENB; 75 | tio.c_ispeed = B57600; 76 | tio.c_ospeed = B57600; 77 | tio.c_iflag = IGNPAR; 78 | tio.c_oflag = 0; 79 | tio.c_lflag = 0; /* turn of CANON, ECHO*, etc */ 80 | tio.c_cc[VTIME] = 1; 81 | tio.c_cc[VMIN] = 0; 82 | tcsetattr(fd, TCSANOW, &tio); 83 | tcflush(fd, TCIFLUSH); 84 | 85 | #ifdef __APPLE__ 86 | tio.c_cflag = CS8 | CLOCAL | CREAD | PARENB; 87 | #else 88 | tio.c_cflag = speed | CS8 | CLOCAL | CREAD | PARENB; 89 | #endif 90 | tio.c_ispeed = speed; 91 | tio.c_ospeed = speed; 92 | 93 | tcsetattr(fd, TCSANOW, &tio); 94 | tcflush(fd, TCIFLUSH); 95 | return fd; 96 | } 97 | 98 | #define ACK 0x79 99 | #define NAK 0x1F 100 | 101 | int readAck(int fd) { /* 3s timeout */ 102 | int n; 103 | unsigned char x; 104 | for (n = 0; n < 30; n++) { 105 | if (read(fd, &x, 1) == 1) { 106 | if (x == ACK) 107 | return 0; 108 | fprintf(stderr,"?? %02x\n",x); 109 | return -1; 110 | } 111 | } 112 | fprintf(stderr,"*TIMEOUT*\n"); 113 | return -1; 114 | } 115 | 116 | int sendCommand(int fd, unsigned cmd) { 117 | unsigned char data[2]; 118 | data[0] = cmd; 119 | data[1] = cmd ^ 0xFF; 120 | if (write(fd, data, 2) != 2) 121 | return -1; 122 | if (readAck(fd)) 123 | return -1; 124 | return 0; 125 | } 126 | 127 | int sendAddress(int fd, unsigned addr) { 128 | unsigned char data[5]; 129 | data[0] = addr >> 24; 130 | data[1] = addr >> 16; 131 | data[2] = addr >> 8; 132 | data[3] = addr; 133 | data[4] = data[0] ^ data[1] ^ data[2] ^ data[3]; 134 | if (write(fd, data, 5) != 5) 135 | return -1; 136 | if (readAck(fd)) 137 | return -1; 138 | return 0; 139 | } 140 | 141 | int sendLength(int fd, unsigned len) { 142 | unsigned char data[2]; 143 | if ((len < 1) || (len > 256)) 144 | return -1; 145 | len--; 146 | data[0] = len; 147 | data[1] = len ^ 0xFF; 148 | if (write(fd, data, 2) != 2) 149 | return -1; 150 | if (readAck(fd)) 151 | return -1; 152 | return 0; 153 | } 154 | 155 | int sendData(int fd, void *ptr, unsigned len) 156 | { 157 | unsigned char x; 158 | unsigned char check; 159 | unsigned char *data = ptr; 160 | unsigned n; 161 | 162 | if ((len < 1) || (len > 256)) 163 | return -1; 164 | check = x = (len - 1); 165 | for (n = 0; n < len; n++) { 166 | check ^= data[n]; 167 | } 168 | if (write(fd, &x, 1) != 1) 169 | return -1; 170 | if (write(fd, data, len) != len) 171 | return -1; 172 | if (write(fd, &check, 1) != 1) 173 | return -1; 174 | if (readAck(fd)) 175 | return -1; 176 | return 0; 177 | } 178 | 179 | int readData(int fd, void *ptr, int len) 180 | { 181 | unsigned char *data = ptr; 182 | int r; 183 | while (len > 0) { 184 | r = read(fd, data, len); 185 | if (r <= 0) { 186 | fprintf(stderr,"*UNDERFLOW*\n"); 187 | return -1; 188 | } 189 | len -= r; 190 | data += r; 191 | } 192 | return 0; 193 | } 194 | 195 | int readMemory(int fd, unsigned addr, void *ptr, int len) 196 | { 197 | unsigned char *data = ptr; 198 | while (len > 0) { 199 | int xfer = (len > 256) ? 256 : len; 200 | fprintf(stderr,"read %04x at %08x -> %p\n", xfer, addr, data); 201 | if (sendCommand(fd, 0x11)) 202 | return -1; 203 | if (sendAddress(fd, addr)) 204 | return -1; 205 | if (sendLength(fd, xfer)) 206 | return -1; 207 | if (readData(fd, data, xfer)) 208 | return -1; 209 | data += xfer; 210 | len -= xfer; 211 | addr += xfer; 212 | } 213 | return 0; 214 | } 215 | 216 | int writeMemory(int fd, unsigned addr, void *ptr, int len) 217 | { 218 | unsigned char *data = ptr; 219 | while (len > 0) { 220 | int xfer = (len > 256) ? 256 : len; 221 | if (sendCommand(fd, 0x31)) 222 | return -1; 223 | if (sendAddress(fd, addr)) 224 | return -1; 225 | if (sendData(fd, data, xfer)) 226 | return -1; 227 | data += xfer; 228 | len -= xfer; 229 | addr += xfer; 230 | } 231 | return 0; 232 | } 233 | 234 | int eraseFlash(int fd) 235 | { 236 | unsigned data[2] = { 0xFF, 0x00 }; 237 | if (sendCommand(fd, 0x43)) 238 | return -1; 239 | if (write(fd, data, 2) != 2) 240 | return -1; 241 | if (readAck(fd)) 242 | return -1; 243 | return 0; 244 | } 245 | 246 | int jumpToAddress(int fd, unsigned addr) 247 | { 248 | if (sendCommand(fd, 0x21)) 249 | return -1; 250 | if (sendAddress(fd, addr)) 251 | return -1; 252 | return 0; 253 | } 254 | 255 | int usage(void) 256 | { 257 | fprintf(stderr, 258 | "usage: stm32boot [ erase | flash | exec ]\n"); 259 | return -1; 260 | } 261 | int main(int argc, char *argv[]) 262 | { 263 | int speed = B115200; 264 | const char *device = "/dev/ttyUSB0"; 265 | unsigned char x; 266 | int fd, n; 267 | unsigned char buf[32768]; 268 | 269 | unsigned do_erase = 0; 270 | unsigned do_write = 0; 271 | unsigned do_exec = 0; 272 | unsigned addr = 0; 273 | 274 | if (argc < 2) 275 | return usage(); 276 | 277 | if (!strcmp(argv[1],"erase")) { 278 | do_erase = 1; 279 | } else if (!strcmp(argv[1],"flash")) { 280 | do_erase = 1; 281 | do_write = 1; 282 | addr = 0x08000000; 283 | } else if (!strcmp(argv[1],"exec")) { 284 | do_write = 1; 285 | do_exec = 1; 286 | addr = 0x20001000; 287 | } else { 288 | return usage(); 289 | } 290 | 291 | if (do_write && argc != 3) 292 | return usage(); 293 | 294 | fd = openserial(device, speed); 295 | if (fd < 0) { 296 | fprintf(stderr, "stderr open '%s'\n", device); 297 | return -1; 298 | } 299 | 300 | n = TIOCM_DTR; 301 | ioctl(fd, TIOCMBIS, &n); 302 | usleep(2500); 303 | ioctl(fd, TIOCMBIC, &n); 304 | usleep(2500); 305 | 306 | /* If the board just powered up, we need to send an ACK 307 | * to auto-baud and will get an ACK back. If the board 308 | * is already up, two ACKs will get a NAK (invalid cmd). 309 | * Either way, we're talking! 310 | */ 311 | for (n = 0; n < 5; n++) { 312 | unsigned char SYNC = 0x7F; 313 | if (write(fd, &SYNC, 1)) { /* do nothing */ } 314 | if (read(fd, &x, 1) != 1) 315 | continue; 316 | if ((x == 0x79) || (x == 0x1f)) 317 | break; 318 | } 319 | if (n == 5) { 320 | fprintf(stderr,"sync failure\n"); 321 | return -1; 322 | } 323 | 324 | #if 0 325 | readMemory(fd, 0x1FFFF000, buf, 4096); 326 | for (n = 0; n < 1024; n++) 327 | fprintf(stderr,"%02x ", buf[n]); 328 | return 0; 329 | #endif 330 | if (do_write) { 331 | int fd2 = open(argv[2], O_RDONLY); 332 | n = read(fd2, buf, sizeof(buf)); 333 | close(fd2); 334 | if ((fd2 < 0) || (n <= 0)) { 335 | fprintf(stderr,"cannot read '%s'\n", argv[2]); 336 | return -1; 337 | } 338 | n += (n % 4); 339 | 340 | 341 | if (do_erase) { 342 | fprintf(stderr,"erasing flash...\n"); 343 | if (eraseFlash(fd)) { 344 | fprintf(stderr,"erase failed\n"); 345 | return -1; 346 | } 347 | } 348 | 349 | fprintf(stderr,"sending %d bytes...\n", n); 350 | if (writeMemory(fd, addr, buf, n)) { 351 | fprintf(stderr,"write failed\n"); 352 | return -1; 353 | } 354 | fprintf(stderr,"done\n"); 355 | 356 | if (do_exec) { 357 | jumpToAddress(fd, addr); 358 | } else { 359 | return 0; 360 | } 361 | } else if (do_erase) { 362 | if (eraseFlash(fd)) { 363 | fprintf(stderr,"erase failed\n"); 364 | return -1; 365 | } 366 | fprintf(stderr,"flash erased\n"); 367 | return 0; 368 | } 369 | 370 | for (;;) { 371 | if (read(fd, &x, 1) == 1) { 372 | if (x == 27) break; 373 | if ((x < 0x20) || (x > 0x7f)) 374 | if ((x != 10) && (x != 13)) 375 | x = '.'; 376 | fprintf(stderr,"%c", x); 377 | } 378 | } 379 | 380 | return 0; 381 | } 382 | -------------------------------------------------------------------------------- /tools/swo.c: -------------------------------------------------------------------------------- 1 | /* swo.c 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #define TRACE 0 28 | 29 | static char console_data[256]; 30 | static int console_ptr = 0; 31 | 32 | static void handle_swv_src(unsigned id, unsigned val, unsigned n) { 33 | #if TRACE 34 | xprintf(XDATA, "SRC %s %02x %08x\n", (id & 0x100) ? "HW" : "SW", id & 0xFF, val); 35 | #endif 36 | if (id == 0) { 37 | console_data[console_ptr++] = val; 38 | if (val == '\n') { 39 | console_data[console_ptr] = 0; 40 | xprintf(XREMOTE, "[remote] %s", console_data); 41 | console_ptr = 0; 42 | } else if (console_ptr == 254) { 43 | console_data[console_ptr] = 0; 44 | xprintf(XREMOTE, "[remote] %s\n", console_data); 45 | } 46 | } 47 | } 48 | 49 | static void handle_swv_proto(unsigned char *data, unsigned len) { 50 | #if TRACE 51 | switch (len) { 52 | case 1: 53 | xprintf(XDATA, "PRO %02x\n", data[0]); 54 | break; 55 | case 2: 56 | xprintf(XDATA, "PRO %02x %02x\n", data[0], data[1]); 57 | break; 58 | case 3: 59 | xprintf(XDATA, "PRO %02x %02x %02x\n", 60 | data[0], data[1], data[2]); 61 | break; 62 | case 4: 63 | xprintf(XDATA, "PRO %02x %02x %02x %02x\n", 64 | data[0], data[1], data[2], data[3]); 65 | break; 66 | case 5: 67 | xprintf(XDATA, "PRO %02x %02x %02x %02x %02x\n", 68 | data[0], data[1], data[2], data[3], data[4]);; 69 | break; 70 | case 6: 71 | xprintf(XDATA, "PRO %02x %02x %02x %02x %02x %02x\n", 72 | data[0], data[1], data[2], data[3], 73 | data[4], data[5]); 74 | break; 75 | case 7: 76 | xprintf(XDATA, "PRO %02x %02x %02x %02x %02x %02x %02x\n", 77 | data[0], data[1], data[2], data[3], 78 | data[4], data[5], data[6]); 79 | break; 80 | } 81 | #endif 82 | } 83 | 84 | typedef enum { 85 | SWV_SYNC, 86 | SWV_1X1, 87 | SWV_1X2, 88 | SWV_1X4, 89 | SWV_2X2, 90 | SWV_2X4, 91 | SWV_3X4, 92 | SWV_4X4, 93 | SWV_PROTO, 94 | SWV_IDLE, 95 | } swv_state_t; 96 | 97 | typedef struct { 98 | swv_state_t state; 99 | unsigned zcount; 100 | unsigned ccount; 101 | unsigned id; 102 | unsigned val; 103 | unsigned char data[8]; 104 | } swv_t; 105 | 106 | static swv_t swv = { 107 | .state = SWV_SYNC, 108 | .zcount = 0 109 | }; 110 | 111 | static void handle_swv(swv_t *swv, unsigned x) { 112 | // any sequence ending in 00 00 00 00 00 80 is a re-sync 113 | if (x == 0) { 114 | swv->zcount++; 115 | } else { 116 | if ((swv->zcount >= 5) && (x == 0x80)) { 117 | swv->state = SWV_IDLE; 118 | swv->zcount = 0; 119 | #if TRACE 120 | xprintf(XDATA, "SYNC\n"); 121 | #endif 122 | return; 123 | } 124 | swv->zcount = 0; 125 | } 126 | 127 | switch (swv->state) { 128 | case SWV_IDLE: 129 | if (x & 7) { 130 | // AAAAAHSS source packet 131 | swv->id = (x >> 3) | ((x & 4) << 6); 132 | swv->val = 0; 133 | swv->state = (x & 3); 134 | } else if (x != 0) { 135 | // CXXXXX00 protocol packet 136 | swv->data[0] = x; 137 | if (x & 0x80) { 138 | swv->ccount = 1; 139 | swv->state = SWV_PROTO; 140 | } else { 141 | handle_swv_proto(swv->data, 1); 142 | } 143 | } else { 144 | // 00 packets are for sync, ignore 145 | } 146 | break; 147 | case SWV_PROTO: 148 | swv->data[swv->ccount++] = x; 149 | // protocol packets end at 7 total bytes or a byte with bit7 clear 150 | if ((swv->ccount == 7) || (!(x & 0x80))) { 151 | handle_swv_proto(swv->data, swv->ccount); 152 | swv->state = SWV_IDLE; 153 | } 154 | break; 155 | case SWV_1X1: 156 | handle_swv_src(swv->id, x, 1); 157 | swv->state = SWV_IDLE; 158 | break; 159 | case SWV_1X2: 160 | swv->val = x; 161 | swv->state = SWV_2X2; 162 | break; 163 | case SWV_2X2: 164 | handle_swv_src(swv->id, swv->val | (x << 8), 2); 165 | swv->state = SWV_IDLE; 166 | break; 167 | case SWV_1X4: 168 | swv->val = x; 169 | swv->state = SWV_2X4; 170 | break; 171 | case SWV_2X4: 172 | swv->val |= (x << 8); 173 | swv->state = SWV_3X4; 174 | break; 175 | case SWV_3X4: 176 | swv->val |= (x << 16); 177 | swv->state = SWV_4X4; 178 | break; 179 | case SWV_4X4: 180 | handle_swv_src(swv->id, swv->val | (x << 24), 4); 181 | swv->state = SWV_IDLE; 182 | break; 183 | case SWV_SYNC: 184 | break; 185 | default: 186 | // impossible 187 | xprintf(XDATA, "fatal error, bad state %d\n", swv->state); 188 | exit(1); 189 | } 190 | } 191 | 192 | void process_swo_data(void *_data, unsigned count) { 193 | unsigned char *data = _data; 194 | while(count-- > 0) { 195 | handle_swv(&swv, *data++); 196 | } 197 | } 198 | 199 | -------------------------------------------------------------------------------- /tools/ti-icepick.h: -------------------------------------------------------------------------------- 1 | #ifndef _TI_ICEPICK_H_ 2 | #define _TI_ICEPICK_H_ 3 | 4 | #define IP_IR_WIDTH 6 5 | 6 | #define IP_IR_BYPASS 0x3F // W = 1 7 | #define IP_IR_ROUTER 0x02 // W = 32, only when CONNECTED 8 | #define IP_IR_IDCODE 0x04 // W = 32 9 | #define IP_IR_IPCODE 0x05 // W = 32 10 | #define IP_IR_CONNECT 0x07 // W = 8 11 | #define IP_IR_USERCODE 0x08 // W = 32 12 | 13 | #define IP_CONNECT_RD 0x00 14 | #define IP_CONNECT_WR_KEY 0x89 15 | 16 | // scanout returns results from previous scan 17 | // loading IR between scans may result in incorrect readback 18 | #define IP_RTR_WR (1 << 31) 19 | #define IP_RTR_BLK(n) (((n) & 7) << 28) 20 | #define IP_RTR_REG(n) (((n) & 15) << 24) 21 | #define IP_RTR_VAL(n) ((n) & 0x00FFFFFF) 22 | 23 | #define IP_RTR_OK (1 << 31) // last write succeeded 24 | 25 | #define IP_BLK_CONTROL 0 26 | #define IP_BLK_TEST_TLCB 1 // TLCB = TAP Linking Control Block 27 | #define IP_BLK_DEBUG_TLCB 2 28 | 29 | // CONTROL block registers 30 | #define IP_CTL_ZEROS 0 31 | #define IP_CTL_CONTROL 1 32 | #define IP_CTL_BLOCK_SYS_RESET (1 << 6) 33 | #define IP_CTL_SYSTEM_RESET (1 << 0) 34 | 35 | #define IP_CTL_LINKING_MODE 2 36 | #define IP_CTL_ALWAYS_FIRST (0 << 1) // TAP always closest to TDI 37 | #define IP_CTL_DISAPPEAR_FOREVER (3 << 1) // TAP vanishes until power-on-reset 38 | #define IP_CTL_ACTIVATE_MODE (1 << 0) // Commit on next RunTestIdle 39 | 40 | // DEBUG TLCB registers 41 | #define IP_DBG_TAP0 0 42 | #define IP_DBG_INHIBIT_SLEEP (1 << 20) 43 | #define IP_DBG_IN_RESET (1 << 17) // RD 44 | #define IP_DBG_RELEASE_FROM_WIR (1 << 17) // WR release from wait-in-reset 45 | #define IP_DBG_RESET_NORMAL (0 << 14) // reset normally 46 | #define IP_DBG_RESET_WAIT (1 << 14) // wait after reset 47 | #define IP_DBG_RESET_CANCEL (4 << 14) // cancel command lockout 48 | #define IP_DBG_VISIBLE_TAP (1 << 9) // RD 49 | #define IP_DBG_SELECT_TAP (1 << 8) // RW 1 = Make Visible on RTI 50 | #define IP_DBG_FORCE_ACTIVE (1 << 3) // RW 1 = override app power/clock 51 | #define IP_DBG_TAP_ACCESSIBLE (1 << 1) // RO 0 = no TAP (security) 52 | #define IP_DBG_TAP_PRESENT (1 << 0) // RO 0 = no TAP (hw) 53 | 54 | // ICE Melter wakes up JTAG after 8 TCKs -- must wait 200uS 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /tools/uconsole.c: -------------------------------------------------------------------------------- 1 | /* uconsole.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "usb.h" 26 | 27 | int main(int argc, char **argv) { 28 | int r, once; 29 | usb_handle *usb; 30 | char buf[64]; 31 | 32 | once = 1; 33 | for (;;) { 34 | usb = usb_open(0x18d1, 0xdb05, 0); 35 | if (usb == 0) { 36 | usb = usb_open(0x18d1, 0xdb04, 1); 37 | } 38 | if (usb == 0) { 39 | if (once) { 40 | fprintf(stderr,"waiting for device...\n"); 41 | once = 0; 42 | } 43 | } else { 44 | break; 45 | } 46 | } 47 | 48 | fprintf(stderr,"connected\n"); 49 | 50 | for (;;) { 51 | r = usb_read(usb, buf, 64); 52 | if (r < 0) 53 | break; 54 | if (write(1, buf, r)) { /* do nothing */ } 55 | } 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /tools/usb.c: -------------------------------------------------------------------------------- 1 | /* usb.c 2 | * 3 | * Copyright 2014 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | #include "usb.h" 24 | 25 | struct usb_handle { 26 | libusb_device_handle *dev; 27 | unsigned ei; 28 | unsigned eo; 29 | }; 30 | 31 | static libusb_context *usb_ctx = NULL; 32 | 33 | usb_handle *usb_open(unsigned vid, unsigned pid, unsigned ifc) { 34 | usb_handle *usb; 35 | int r; 36 | 37 | if (usb_ctx == NULL) { 38 | if (libusb_init(&usb_ctx) < 0) { 39 | usb_ctx = NULL; 40 | return NULL; 41 | } 42 | } 43 | 44 | usb = malloc(sizeof(usb_handle)); 45 | if (usb == 0) { 46 | return NULL; 47 | } 48 | 49 | /* TODO: extract from descriptors */ 50 | switch (ifc) { 51 | case 0: 52 | usb->ei = 0x81; 53 | usb->eo = 0x01; 54 | break; 55 | case 1: 56 | usb->ei = 0x82; 57 | usb->eo = 0x02; 58 | break; 59 | default: 60 | goto fail; 61 | } 62 | 63 | usb->dev = libusb_open_device_with_vid_pid(usb_ctx, vid, pid); 64 | if (usb->dev == NULL) { 65 | goto fail; 66 | } 67 | // This causes problems on re-attach. Maybe need for OSX? 68 | // On Linux it's completely happy without us explicitly setting a configuration. 69 | //r = libusb_set_configuration(usb->dev, 1); 70 | r = libusb_claim_interface(usb->dev, ifc); 71 | if (r < 0) { 72 | fprintf(stderr, "failed to claim interface #%d\n", ifc); 73 | goto close_fail; 74 | } 75 | 76 | #ifdef __APPLE__ 77 | // make sure everyone's data toggles agree 78 | // makes things worse on Linux, but happy on OSX 79 | libusb_clear_halt(usb->dev, usb->ei); 80 | libusb_clear_halt(usb->dev, usb->eo); 81 | #endif 82 | 83 | return usb; 84 | 85 | close_fail: 86 | libusb_close(usb->dev); 87 | fail: 88 | free(usb); 89 | return NULL; 90 | } 91 | 92 | void usb_close(usb_handle *usb) { 93 | libusb_close(usb->dev); 94 | free(usb); 95 | } 96 | 97 | int usb_ctrl(usb_handle *usb, void *data, 98 | uint8_t typ, uint8_t req, uint16_t val, uint16_t idx, uint16_t len) { 99 | int r = libusb_control_transfer(usb->dev, typ, req, val, idx, data, len, 5000); 100 | if (r < 0) { 101 | return -1; 102 | } else { 103 | return r; 104 | } 105 | } 106 | 107 | int usb_read(usb_handle *usb, void *data, int len) { 108 | int xfer = len; 109 | int r = libusb_bulk_transfer(usb->dev, usb->ei, data, len, &xfer, 5000); 110 | if (r < 0) { 111 | return -1; 112 | } 113 | return xfer; 114 | } 115 | 116 | int usb_read_forever(usb_handle *usb, void *data, int len) { 117 | int xfer = len; 118 | int r = libusb_bulk_transfer(usb->dev, usb->ei, data, len, &xfer, 0); 119 | if (r < 0) { 120 | return -1; 121 | } 122 | return xfer; 123 | } 124 | 125 | int usb_write(usb_handle *usb, const void *data, int len) { 126 | int xfer = len; 127 | int r = libusb_bulk_transfer(usb->dev, usb->eo, (void*) data, len, &xfer, 5000); 128 | if (r < 0) { 129 | return -1; 130 | } 131 | return xfer; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /tools/usb.h: -------------------------------------------------------------------------------- 1 | /* usb.h 2 | * 3 | * Copyright 2014 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef _USB_H_ 19 | #define _USB_H_ 20 | 21 | #include 22 | 23 | typedef struct usb_handle usb_handle; 24 | 25 | /* simple usb api for devices with bulk in+out interfaces */ 26 | 27 | usb_handle *usb_open(unsigned vid, unsigned pid, unsigned ifc); 28 | void usb_close(usb_handle *usb); 29 | int usb_read(usb_handle *usb, void *data, int len); 30 | int usb_read_forever(usb_handle *usb, void *data, int len); 31 | int usb_write(usb_handle *usb, const void *data, int len); 32 | int usb_ctrl(usb_handle *usb, void *data, 33 | uint8_t typ, uint8_t req, uint16_t val, uint16_t idx, uint16_t len); 34 | #endif 35 | -------------------------------------------------------------------------------- /tools/usbmon.c: -------------------------------------------------------------------------------- 1 | /* usbmon.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | typedef unsigned long long u64; 29 | typedef signed long long s64; 30 | typedef int s32; 31 | typedef unsigned short u16; 32 | 33 | #include "usbmon.h" 34 | 35 | static char _xfer[4] = "SICB"; 36 | 37 | int main(int argc, char **argv) 38 | { 39 | unsigned char data[4096]; 40 | struct usbmon_packet hdr; 41 | struct usbmon_get arg; 42 | unsigned char filter_dev[128]; 43 | int fd, r, n; 44 | 45 | memset(filter_dev, 0, sizeof(filter_dev)); 46 | 47 | fd = open("/dev/usbmon0", O_RDONLY); 48 | if (fd < 0) 49 | return -1; 50 | 51 | argc--; 52 | argv++; 53 | while (argc--) { 54 | if (argv[0][0] == '-') { 55 | switch(argv[0][1]) { 56 | case 'x': 57 | r = atoi(argv[0] + 2); 58 | if ((r < 0) || (r > 127)) 59 | continue; 60 | filter_dev[r] = 1; 61 | break; 62 | } 63 | } 64 | argv++; 65 | } 66 | 67 | arg.hdr = &hdr; 68 | arg.data = data; 69 | for (;;) { 70 | arg.alloc = sizeof(data); 71 | r = ioctl(fd, MON_IOCX_GET, &arg); 72 | if (r < 0) 73 | break; 74 | if (filter_dev[hdr.devnum]) 75 | continue; 76 | printf("%d.%03d.%03d %c %c%c %04x", 77 | hdr.busnum, hdr.devnum, hdr.epnum & 0x7F, 78 | hdr.type, 79 | _xfer[hdr.xfer], (hdr.epnum & 0x80) ? 'i' : 'o', 80 | #if 0 81 | hdr.flag_setup ? hdr.flag_setup : ' ', 82 | hdr.flag_data ? hdr.flag_data : ' ', 83 | #endif 84 | hdr.length); 85 | if (hdr.type == 'S') { 86 | if (hdr.xfer == 2) { 87 | printf(" %02x %02x %02x%02x %02x%02x %02x%02x\n", 88 | hdr.s.setup[0], hdr.s.setup[1], 89 | hdr.s.setup[3], hdr.s.setup[2], 90 | hdr.s.setup[5], hdr.s.setup[4], 91 | hdr.s.setup[7], hdr.s.setup[6]); 92 | } else { 93 | goto dumpdata; 94 | } 95 | 96 | } else { 97 | switch (hdr.status) { 98 | case 0: 99 | printf(" OK\n"); 100 | break; 101 | case -EPIPE: 102 | printf(" STALLED\n"); 103 | break; 104 | case -ENODEV: 105 | printf(" DISCONNECTED\n"); 106 | break; 107 | case -ETIMEDOUT: 108 | printf(" TIMEDOUT\n"); 109 | break; 110 | default: 111 | printf(" %s\n", strerror(-hdr.status)); 112 | } 113 | } 114 | if (!hdr.len_cap) 115 | continue; 116 | printf(" "); 117 | dumpdata: 118 | if (hdr.len_cap > sizeof(data)) 119 | hdr.len_cap = sizeof(data); 120 | for (n = 0; n < hdr.len_cap; n++) 121 | printf((n & 3) ? "%02x" : " %02x",data[n]); 122 | printf(" "); 123 | for (n = 0; n < hdr.len_cap; n++) 124 | putchar(((data[n] < 0x20) || (data[n] > 0x7F)) ? '.' : data[n]); 125 | printf("\n"); 126 | } 127 | return 0; 128 | } 129 | 130 | -------------------------------------------------------------------------------- /tools/usbmon.h: -------------------------------------------------------------------------------- 1 | /* Based on Documentation/usbmon.txt in the Linux Kernel */ 2 | 3 | #ifndef _USBMON_H_ 4 | #define _USBMON_H_ 5 | 6 | struct usbmon_packet { 7 | u64 id; /* URB ID */ 8 | unsigned char type; /* 'S'ubmit 'C'allback 'E'rror */ 9 | unsigned char xfer; /* ISO=0 INT=1 CTRL=2 BULK=3 */ 10 | unsigned char epnum; 11 | unsigned char devnum; 12 | u16 busnum; 13 | char flag_setup; 14 | char flag_data; 15 | s64 ts_sec; 16 | s32 ts_usec; 17 | int status; 18 | unsigned int length; 19 | unsigned int len_cap; 20 | union { 21 | unsigned char setup[8]; 22 | struct iso_rec { 23 | int error_count; 24 | int numdesc; 25 | } iso; 26 | } s; 27 | int interval; 28 | int start_frame; 29 | unsigned int xfer_flags; 30 | unsigned int ndesc; 31 | }; 32 | 33 | struct usbmon_get { 34 | struct usbmon_packet *hdr; 35 | void *data; 36 | size_t alloc; 37 | }; 38 | 39 | #define MON_IOC_MAGIC 0x92 40 | 41 | #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct usbmon_get) 42 | #define MON_IOCX_GETX _IOW(MON_IOC_MAGIC, 10, struct usbmon_get) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /tools/usbtest.c: -------------------------------------------------------------------------------- 1 | /* rswdp.c 2 | * 3 | * Copyright 2011 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "usb.h" 24 | 25 | int main(int argc, char **argv) { 26 | usb_handle *usb; 27 | char buf[4096]; 28 | int n, sz = 64; 29 | 30 | if (argc > 1) { 31 | sz = atoi(argv[1]); 32 | if ((sz < 1) || (sz > 4096)) 33 | return -1; 34 | } 35 | 36 | usb = usb_open(0x18d1, 0xdb01, 0); 37 | if (usb == 0) { 38 | fprintf(stderr, "cannot find device\n"); 39 | return -1; 40 | } 41 | 42 | for (n = 0; n < sz; n++) 43 | buf[n] = n; 44 | 45 | usb_write(usb, buf, sz); 46 | return 0; 47 | } 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tools/websocket.c: -------------------------------------------------------------------------------- 1 | /* websocket.c 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "sha1.h" 30 | #include "websocket.h" 31 | 32 | struct ws_server { 33 | FILE *fp; 34 | int fd; 35 | ws_callback_t func; 36 | void *cookie; 37 | }; 38 | 39 | int base64_decode(uint8_t *data, uint32_t len, uint8_t *out); 40 | int base64_encode(uint8_t *data, uint32_t len, uint8_t *out); 41 | 42 | static const char *wsmagic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 43 | 44 | #define F_FIN 0x80 45 | #define F_INVAL 0x70 46 | #define OP_NONE 0 47 | #define OP_TEXT 1 48 | #define OP_BINARY 2 49 | #define OP_CLOSE 8 50 | #define OP_PING 9 51 | #define OP_PONG 10 52 | 53 | #define F_MASKED 0x80 54 | #define LEN_16BIT 0x7E 55 | #define LEN_64BIT 0x7F 56 | 57 | static int ws_send(int fd, unsigned op, const void *data, size_t len); 58 | 59 | int ws_send_text(ws_server_t *ws, const void *data, size_t len) { 60 | return ws_send(ws->fd, OP_TEXT, data, len); 61 | } 62 | 63 | int ws_send_binary(ws_server_t *ws, const void *data, size_t len) { 64 | return ws_send(ws->fd, OP_BINARY, data, len); 65 | } 66 | 67 | static int _ws_handshake(ws_server_t *ws) { 68 | FILE *fp = ws->fp; 69 | unsigned check = 0; 70 | char line[8192 + 128]; 71 | uint8_t digest[SHA_DIGEST_SIZE]; 72 | int n; 73 | 74 | for (;;) { 75 | if (fgets(line, sizeof(line), fp) == NULL) { 76 | return -1; 77 | } 78 | if ((n = strlen(line)) == 0) { 79 | return -1; 80 | } 81 | if (line[n-1] == '\n') { 82 | line[n-1] = 0; 83 | if ((n > 1) && (line[n-2] == '\r')) { 84 | line[n-2] = 0; 85 | } 86 | } 87 | if (line[0] == 0) { 88 | //printf(">BREAK<\n"); 89 | break; 90 | } 91 | //printf(">HEADER: %s<\n", line); 92 | if (!strcasecmp(line, "upgrade: websocket")) { 93 | check |= 1; 94 | continue; 95 | } 96 | if (!strcasecmp(line, "connection: upgrade")) { 97 | // may be keep-alive, etc 98 | check |= 2; 99 | continue; 100 | } 101 | if (!strncasecmp(line, "sec-websocket-key: ", 19)) { 102 | check |= 4; 103 | strcat(line, wsmagic); 104 | SHA(line + 19, strlen(line + 19), digest); 105 | } 106 | if (!strcasecmp(line, "sec-websocket-version: 13")) { 107 | check |= 8; 108 | } 109 | // Host: 110 | // Origin: 111 | // Sec-WebSocket-Protocol: 112 | // Sec-WebSocket-Extensions: 113 | } 114 | if ((check & 13) != 13) { 115 | return -1; 116 | } 117 | n = base64_encode((void*) digest, SHA_DIGEST_SIZE, (void*) line); 118 | line[n] = 0; 119 | fprintf(fp, 120 | "HTTP/1.1 101 Switching Protocols\r\n" 121 | "Upgrade: websocket\r\n" 122 | "Connection: Upgrade\r\n" 123 | "Sec-Websocket-Accept: %s\r\n" 124 | "\r\n", line 125 | ); 126 | return 0; 127 | } 128 | 129 | int ws_process_messages(ws_server_t *ws) { 130 | FILE *fp = ws->fp; 131 | unsigned char hdr[2+2+4]; 132 | unsigned char msg[65536]; 133 | unsigned len; 134 | for (;;) { 135 | if (fread(hdr, 2, 1, fp) != 1) break; 136 | // client must not set invalid flags 137 | if (hdr[0] & F_INVAL) break; 138 | // client must mask 139 | if (!(hdr[1] & F_MASKED)) break; 140 | // todo: fragments 141 | if (!(hdr[0] & F_FIN)) break; 142 | // todo: large packets 143 | if ((hdr[1] & 0x7F) == LEN_64BIT) break; 144 | if ((hdr[1] & 0x7F) == LEN_16BIT) { 145 | if (fread(hdr + 2, 6, 1, fp) != 1) break; 146 | len = (hdr[2] << 8) | hdr[3]; 147 | } else { 148 | if (fread(hdr + 4, 4, 1, fp) != 1) break; 149 | len = hdr[1] & 0x7F; 150 | } 151 | #if 0 152 | printf("\n", 153 | hdr[0] & 15, len, hdr[4], hdr[5], hdr[6], hdr[7]); 154 | #endif 155 | if (fread(msg, len, 1, fp) != 1) break; 156 | // op? 157 | #if 0 158 | unsigned i; 159 | for (i = 0; i < len; i++) { 160 | msg[i] ^= hdr[4 + (i & 3)]; 161 | printf("%02x ", msg[i]); 162 | } 163 | printf("\n"); 164 | #endif 165 | switch (hdr[0] & 15) { 166 | case OP_PING: 167 | break; 168 | case OP_PONG: 169 | break; 170 | case OP_CLOSE: 171 | // todo: reply 172 | return 0; 173 | case OP_TEXT: 174 | ws->func(OP_TEXT, msg, len, ws->cookie); 175 | break; 176 | case OP_BINARY: 177 | ws->func(OP_BINARY, msg, len, ws->cookie); 178 | break; 179 | default: 180 | // invalid opcode 181 | return 0; 182 | } 183 | } 184 | return 0; 185 | } 186 | 187 | static int ws_send(int fd, unsigned op, const void *data, size_t len) { 188 | unsigned char hdr[4]; 189 | struct iovec iov[2]; 190 | if (len > 65535) return -1; 191 | hdr[0] = F_FIN | (op & 15); 192 | if (len < 126) { 193 | hdr[1] = len; 194 | iov[0].iov_len = 2; 195 | } else { 196 | hdr[1] = LEN_16BIT; 197 | hdr[2] = len >> 8; 198 | hdr[3] = len; 199 | iov[0].iov_len = 4; 200 | } 201 | iov[0].iov_base = hdr; 202 | iov[1].iov_base = (void*) data; 203 | iov[1].iov_len = len; 204 | return writev(fd, iov, 2); 205 | } 206 | 207 | ws_server_t *ws_handshake(int fd, ws_callback_t func, void *cookie) { 208 | ws_server_t *ws; 209 | 210 | if ((ws = malloc(sizeof(ws_server_t))) == NULL) { 211 | goto fail; 212 | } 213 | if ((ws->fp = fdopen(fd, "r+")) == NULL) { 214 | goto fail; 215 | } 216 | if (_ws_handshake(ws)) { 217 | goto fail; 218 | } 219 | ws->fd = fd; 220 | ws->func = func; 221 | ws->cookie = cookie; 222 | return ws; 223 | fail: 224 | if (ws != NULL) { 225 | free(ws); 226 | if (ws->fp) { 227 | fclose(ws->fp); 228 | return NULL; 229 | } 230 | } 231 | close(fd); 232 | return NULL; 233 | } 234 | 235 | void ws_close(ws_server_t *ws) { 236 | fclose(ws->fp); 237 | free(ws); 238 | } 239 | -------------------------------------------------------------------------------- /tools/websocket.h: -------------------------------------------------------------------------------- 1 | /* websocket.c 2 | * 3 | * Copyright 2015 Brian Swetland 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #ifndef _WEBSOCKET_SERVER_H_ 19 | #define _WEBSOCKET_SERVER_H_ 20 | 21 | typedef struct ws_server ws_server_t; 22 | 23 | typedef void (*ws_callback_t)(unsigned op, void *msg, size_t len, void *cookie); 24 | 25 | ws_server_t *ws_handshake(int fd, ws_callback_t func, void *cookie); 26 | int ws_process_messages(ws_server_t *ws); 27 | 28 | int ws_send_text(ws_server_t *ws, const void *msg, size_t len); 29 | int ws_send_binary(ws_server_t *ws, const void *msg, size_t len); 30 | 31 | void ws_close(ws_server_t *ws); 32 | 33 | #endif 34 | --------------------------------------------------------------------------------