├── LICENSE ├── README.md ├── alpha_speedup.py ├── firmware ├── brcmfmac43430-sdio.bin └── brcmfmac43430-sdio.c ├── make_join ├── make_join.bat ├── make_scan ├── make_scan.bat ├── run ├── run.bat ├── run_lin.gdb ├── run_win.gdb ├── sdk ├── Alpha.specs ├── CPU_init.c ├── CPU_init.o ├── CPU_init_util.S ├── CPU_init_util.o ├── CPU_start.S ├── CPU_start.o ├── Dockerfile ├── Makefile ├── alpha.gdb ├── armv6-core.xml ├── libalpha.a ├── libalpha │ └── include │ │ ├── alpha │ │ └── fileio.h │ │ └── gdb │ │ └── fileio.h ├── libarm.a ├── libfileio.a ├── libfileio │ └── src │ │ ├── close.c │ │ ├── errno.h │ │ ├── exit.c │ │ ├── fstat.c │ │ ├── gettimeofday.c │ │ ├── isatty.c │ │ ├── lseek.c │ │ ├── open.c │ │ ├── read.c │ │ ├── stat.c │ │ ├── unlink.c │ │ └── write.c └── link.ld ├── srce ├── zjoin.c ├── zscan.c ├── zw_gpio.c ├── zw_gpio.h ├── zw_ioctl.c ├── zw_ioctl.h ├── zw_regs.h ├── zw_sdio.c └── zw_sdio.h ├── whd ├── cy_result.h ├── cyhal_hw_types.h ├── whd.h ├── whd_events.h ├── whd_types.h └── whd_wlioctl.h └── zerowi.elf /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zerowi: bare-metal WiFi driver for the Raspberry Pi 2 | See https://iosoft.blog/zerowi for details 3 | 4 | Copyright (c) Jeremy P Bentham 2020 5 | -------------------------------------------------------------------------------- /alpha_speedup.py: -------------------------------------------------------------------------------- 1 | # Utility for RPi Alpha to increase remote GDB baud rate 2 | # From iosoft.blog, copyright (c) Jeremy P bentham 2020 3 | # Requires pyserial package 4 | 5 | import sys, serial, time 6 | 7 | # Defaults 8 | serport = "COM7" 9 | verbose = False 10 | 11 | # Default settings 12 | OLD_BAUD = 115200 13 | new_baud = 921600 14 | TIMEOUT = 0.2 15 | SYS_CLOCK = 250e6 16 | 17 | # GDB remote commands 18 | high_speed = "mw32 0x20215068 %u" 19 | qsupported = "qSupported" 20 | 21 | # Send command, return response 22 | def cmd_resp(ser, cmd): 23 | txd = frame(cmd) 24 | if verbose: 25 | print("Tx: %s" % txd) 26 | ser.write(txd.encode('latin')) 27 | rxd = str(ser.read(1468)) 28 | if verbose: 29 | print("Rx: %s" % rxd) 30 | resp = rxd.partition('$') 31 | return resp[2].partition('#')[0] 32 | 33 | # Acknowledge a response 34 | def ack_resp(ser): 35 | ser.write('+'.encode('latin')) 36 | if verbose: 37 | print("Tx: +") 38 | 39 | # Return string, given hex values 40 | def hex_str(hex): 41 | return bytearray.fromhex(hex).decode() 42 | 43 | # Return remote hex command string 44 | def cmd_hex(cmd): 45 | return "qRcmd,%s" % "".join([("%02x" % ord(c)) for c in cmd]) 46 | 47 | # Return framed data 48 | def frame(data): 49 | return "$%s#%02x" % ("".join([escape(c) for c in data]), csum(data)) 50 | 51 | # Escape a character in the message 52 | def escape(c): 53 | return c if c not in "#$}" else '}'+chr(ord(c)^0x20) 54 | 55 | # GDB checksum calculation 56 | def csum(data): 57 | return 0xff & sum([ord(c) for c in data]) 58 | 59 | # Open serial port 60 | def ser_open(port, baud): 61 | try: 62 | ser = serial.Serial(port, baud, timeout=TIMEOUT) 63 | except: 64 | print("Can't open serial port %s" % port) 65 | sys.exit(1) 66 | return ser 67 | 68 | # Close serial port 69 | def ser_close(ser): 70 | if ser: 71 | ser.close() 72 | 73 | if __name__ == "__main__": 74 | opt = None 75 | for arg in sys.argv[1:]: 76 | if len(arg)==2 and arg[0]=="-": 77 | opt = arg.lower() 78 | if opt == "-v": 79 | verbose = True 80 | opt = None 81 | elif opt == '-b': 82 | new_baud = int(arg) 83 | opt = None 84 | elif opt == '-c': 85 | serport = arg 86 | opt = None 87 | print("Opening serial port %s at %u baud" % (serport, OLD_BAUD)) 88 | ser = ser_open(serport, OLD_BAUD); 89 | cmd_resp(ser, "") 90 | ack_resp(ser) 91 | if cmd_resp(ser, qsupported): 92 | ack_resp(ser) 93 | print("Setting %u baud" % new_baud) 94 | uart_div = int(round((SYS_CLOCK / (8 * new_baud)) - 1)) 95 | cmd_resp(ser, cmd_hex(high_speed % uart_div)) 96 | time.sleep(0.01) 97 | print("Reopening at %u baud" % new_baud) 98 | ser_close(ser) 99 | ser = ser_open(serport, new_baud); 100 | ack_resp(ser) 101 | if cmd_resp(ser, qsupported): 102 | ack_resp(ser) 103 | print("Target system responding OK") 104 | time.sleep(0.01) 105 | else: 106 | print("No response from target system") 107 | #EOF -------------------------------------------------------------------------------- /firmware/brcmfmac43430-sdio.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/firmware/brcmfmac43430-sdio.bin -------------------------------------------------------------------------------- /make_join: -------------------------------------------------------------------------------- 1 | arm-none-eabi-gcc -specs=./sdk/Alpha.specs -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -g3 -ggdb -Wall -Wl,-T./sdk/link.ld -L./sdk -I./whd -Wl,-umalloc -fpack-struct=1 -o zerowi.elf srce/zjoin.c srce/zw_sdio.c srce/zw_ioctl.c srce/zw_gpio.c -------------------------------------------------------------------------------- /make_join.bat: -------------------------------------------------------------------------------- 1 | arm-none-eabi-gcc -specs=./sdk/Alpha.specs -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -g3 -ggdb -Wall -Wl,-T./sdk/link.ld -I./whd -I./srce -L./sdk -Wl,-umalloc -fpack-struct=1 -o zerowi.elf srce/zjoin.c srce/zw_sdio.c srce/zw_ioctl.c srce/zw_gpio.c 2 | -------------------------------------------------------------------------------- /make_scan: -------------------------------------------------------------------------------- 1 | arm-none-eabi-gcc -specs=./sdk/Alpha.specs -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -g3 -ggdb -Wall -Wl,-T./sdk/link.ld -L./sdk -I./whd -Wl,-umalloc -fpack-struct=1 -o zerowi.elf srce/zscan.c srce/zw_sdio.c srce/zw_ioctl.c srce/zw_gpio.c -------------------------------------------------------------------------------- /make_scan.bat: -------------------------------------------------------------------------------- 1 | arm-none-eabi-gcc -specs=./sdk/Alpha.specs -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -g3 -ggdb -Wall -Wl,-T./sdk/link.ld -L./sdk -I./whd -Wl,-umalloc -fpack-struct=1 -o zerowi.elf srce/zscan.c srce/zw_sdio.c srce/zw_ioctl.c srce/zw_gpio.c 2 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | python alpha_speedup.py -c /dev/ttyUSB0 -b 460800 2 | arm-none-eabi-gdb -x run_lin.gdb zerowi.elf -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | python alpha_speedup.py -c com7 2 | arm-none-eabi-gdb -x run_win.gdb zerowi.elf -------------------------------------------------------------------------------- /run_lin.gdb: -------------------------------------------------------------------------------- 1 | # Connect GDB serial to RPi: pin 5 black, 7 yellow, 9 red 2 | source sdk/alpha.gdb 3 | 4 | #set serial baud 921600 5 | #target remote COM7 6 | 7 | set serial baud 460800 8 | target remote /dev/ttyUSB0 9 | 10 | # Load the executable in the target 11 | # By default, the loaded file is the one GDB debugs, given as argument 12 | # to gdb or using the command file. 13 | load 14 | 15 | # Run untile reaching main 16 | # tbreak main 17 | break gdb_break 18 | commands 1 19 | kill 20 | quit 21 | end 22 | continue 23 | -------------------------------------------------------------------------------- /run_win.gdb: -------------------------------------------------------------------------------- 1 | # Connect GDB serial to RPi: pin 5 black, 7 yellow, 9 red 2 | source sdk/alpha.gdb 3 | 4 | set serial baud 921600 5 | target remote COM7 6 | #target remote /dev/ttyUSB0 7 | 8 | # Load the executable in the target 9 | # By default, the loaded file is the one GDB debugs, given as argument 10 | # to gdb or using the command file. 11 | load 12 | 13 | # Run untile reaching main 14 | # tbreak main 15 | break gdb_break 16 | commands 1 17 | kill 18 | quit 19 | end 20 | continue 21 | -------------------------------------------------------------------------------- /sdk/Alpha.specs: -------------------------------------------------------------------------------- 1 | %rename link_gcc_c_sequence nosys_link_gcc_c_sequence 2 | 3 | *Alpha_libgloss: 4 | -lfileio -lalpha -larm 5 | 6 | *nosys_libc: 7 | %{!specs=nano.specs:-lc} %{specs=nano.specs:-lc_nano} 8 | 9 | *link_gcc_c_sequence: 10 | %(nosys_link_gcc_c_sequence) --start-group %G %(nosys_libc) %(Alpha_libgloss) --end-group 11 | -------------------------------------------------------------------------------- /sdk/CPU_init.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* This function initialise the MMU with the following mapping */ 4 | /* Physical 0x00000000 - 0x20000000, virtual 0x00000000 - 0x20000000, RWX user, RWX super, write-back, no write allocate */ 5 | /* RPI1 Physical 0x20000000 - 0x21000000, virtual 0x20000000 - 0x21000000, RWX user, RWX super, write-back, no-cacheable */ 6 | /* RPI2&3 Physical 0x3F000000 - 0x40000000, virtual 0x20000000 - 0x21000000, RWX user, RWX super, write-back, no-cacheable */ 7 | /* Physical 0x00000000 - 0x40000000, virtual 0x40000000 - 0x80000000, RWX user, RWX super, write-back, no-cacheable */ 8 | 9 | /* The CPU RAM size is limited to 512 to fit almost all raspberry */ 10 | /* The Whole RAM is accessible in non-cacheable mode from 0x40000000 to be able to access video RAM */ 11 | 12 | 13 | #define RPI1_IO_BASE_ADDRESS 0x20000000 14 | #define RPI2_IO_BASE_ADDRESS 0x3F000000 15 | #define RPI3_IO_BASE_ADDRESS 0x3F000000 16 | 17 | 18 | /* number of 1M section in 4 GB address space */ 19 | #define NB_1M_SECTION (0x100000000LL / 0x00100000) 20 | extern unsigned int CPU_init_page_table[NB_1M_SECTION]; 21 | 22 | /* */ 23 | #define ONE_MB (1024 * 1024) 24 | #define K_RAM_SIZE (512 *K_1M) 25 | 26 | extern unsigned int CPU_init_read_main_id(); 27 | extern void CPU_init_stop_mmu(); 28 | extern void CPU_init_start_mmu(unsigned int * page_table,unsigned int control_register_or_mask); 29 | extern void CPU_init_enable_vfp(); 30 | extern void CPU_init_invalidate_tlb(); 31 | extern void CPU_init_clean_and_invalidate_data_cache(); 32 | extern void CPU_init_invalidate_instruction_cache(); 33 | extern void CPU_init_disable_caches(); 34 | 35 | void CPU_init_map_section( 36 | unsigned int *page_table, 37 | unsigned int virtual_address, 38 | unsigned int physical_address, 39 | unsigned int flags) 40 | { 41 | unsigned int *entry; 42 | 43 | entry = &(page_table[virtual_address >> 20]); 44 | *entry = (physical_address & 0xFFF00000) | flags | 2 |0xC00; 45 | return; 46 | } 47 | 48 | 49 | 50 | void CPU_init() 51 | { 52 | unsigned int main_id; 53 | unsigned int physical_io_address; 54 | unsigned int i; 55 | 56 | /* reading CPU id to known RPI version */ 57 | main_id = CPU_init_read_main_id(); 58 | 59 | /* rpi1 armv6 */ 60 | if ((main_id & 0xF000) == 0xB000) 61 | { 62 | physical_io_address = RPI1_IO_BASE_ADDRESS; 63 | } 64 | /* rpi2 armv7 */ 65 | else if ((main_id & 0xF000) == 0xC000) 66 | { 67 | physical_io_address = RPI2_IO_BASE_ADDRESS; 68 | } 69 | /* rpi3 armv8 */ 70 | else if ((main_id & 0xF000) == 0xD000) 71 | { 72 | physical_io_address = RPI3_IO_BASE_ADDRESS; 73 | } 74 | 75 | /* clear page table */ 76 | for (i = 0;i < NB_1M_SECTION; i++) 77 | { 78 | CPU_init_page_table[i] = 0; 79 | } 80 | 81 | /* map Physical 0x00000000 - 0x20000000, virtual 0x00000000 - 0x20000000, RWX user, RWX super, write-back, no write allocate */ 82 | for (i = 0x00000000; i < (512 * ONE_MB); i+= ONE_MB) 83 | { 84 | CPU_init_map_section(CPU_init_page_table,i,i,0x0c); // cacheable no write allocate 85 | } 86 | 87 | /* RPI1 Physical 0x20000000 - 0x21000000, virtual 0x20000000 - 0x21000000, RWX user, RWX super, write-back, no-cacheable */ 88 | /* RPI2&3 Physical 0x3F000000 - 0x40000000, virtual 0x20000000 - 0x21000000, RWX user, RWX super, write-back, no-cacheable */ 89 | for (i = 0; i < (16 * ONE_MB) ; i+= ONE_MB) 90 | { 91 | CPU_init_map_section(CPU_init_page_table,RPI1_IO_BASE_ADDRESS + i,physical_io_address + i,0); // not cacheable 92 | } 93 | 94 | /* Map Physical 0x00000000 - 0x40000000, virtual 0x40000000 - 0x80000000, RWX user, RWX super, write-back, no-cacheable */ 95 | for (i = 0x00000000; i < 0x40000000; i+= ONE_MB) 96 | { 97 | CPU_init_map_section(CPU_init_page_table,0x40000000 + i,i,0x0); // not cacheable 98 | } 99 | 100 | // clean_and_invalidate_data_cache(); 101 | // invalidate_instruction_cache(); 102 | // disable_caches(); 103 | CPU_init_stop_mmu(); 104 | CPU_init_invalidate_tlb(); 105 | CPU_init_start_mmu((unsigned int *)((unsigned int)CPU_init_page_table),0x1005); /* ICACHE DCACHE and MMU ON */ 106 | CPU_init_enable_vfp(); 107 | 108 | return; 109 | } 110 | -------------------------------------------------------------------------------- /sdk/CPU_init.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/sdk/CPU_init.o -------------------------------------------------------------------------------- /sdk/CPU_init_util.S: -------------------------------------------------------------------------------- 1 | .text 2 | 3 | .globl CPU_init_stop_mmu 4 | .globl CPU_init_start_mmu 5 | .globl CPU_init_enable_vfp 6 | .globl CPU_init_invalidate_tlb 7 | .globl CPU_init_clean_and_invalidate_data_cache 8 | .globl CPU_init_invalidate_instruction_cache 9 | .globl CPU_init_disable_caches 10 | .globl CPU_init_read_main_id 11 | 12 | 13 | CPU_init_read_main_id: 14 | MRC p15,0,r0,c0,c0,0 15 | BX lr 16 | 17 | 18 | CPU_init_clean_and_invalidate_data_cache: 19 | // flush data cache 20 | loop: 21 | MOV r2,#0 22 | MCR p15,0,r2,c7,c10,0 23 | MRC p15,0,r2,c7,c10,6 24 | ANDS r2,r2,#01 25 | BEQ done 26 | B loop 27 | done: 28 | // invalidate data cache */ 29 | MCR p15,0,r2,c7,c6,0 30 | MCR p15,0,r2,c7,c10,4 31 | BX lr 32 | 33 | 34 | 35 | CPU_init_invalidate_instruction_cache: 36 | MOV r2,#0 37 | MCR p15,0,r2,c7,c5,0 38 | MCR p15,0,r2,c7,c10,4 39 | BX lr 40 | 41 | 42 | CPU_init_disable_caches: 43 | MRC p15,0,r2,c1,c0,0 44 | BIC r2,#0x1000 45 | BIC r2,#0x0004 46 | MCR p15,0,r2,c1,c0,0 47 | BX lr 48 | 49 | 50 | CPU_init_stop_mmu: 51 | // disable mmu 52 | MRC p15,0,r2,c1,c0,0 53 | BIC r2,#0x01 54 | MCR p15,0,r2,c1,c0,0 55 | BX lr 56 | 57 | CPU_init_start_mmu: 58 | //set domain register to 0x55555555 to allow client access to perform check 59 | LDR r2,=0x55555555 60 | MCR p15,0,r2,c3,c0,0 ;@ domain 61 | // clear TTBC to enable only TTBR0 62 | MOV r2,#0 63 | MCR p15,0,r2,c2,c0,2 ;@ TTBC 64 | // set TTBR0 to pagetable address 65 | MRC p15,0,r4,c2,c0,0 ;@ tlb base 66 | MCR p15,0,r0,c2,c0,0 ;@ tlb base 67 | MCR p15,0,r0,c2,c0,1 ;@ tlb base 68 | MOV r2,#0 69 | MCR p15,0,r2,c7,c10,4 70 | 71 | // write in control register input value 72 | MRC p15,0,r2,c1,c0,0 73 | ORR r2,r2,r1 74 | MCR p15,0,r2,c1,c0,0 75 | BX lr 76 | 77 | 78 | /* enable copro single doucle precision */ 79 | /* enable float */ 80 | /* set fpscr to flush to zero */ 81 | CPU_init_enable_vfp: 82 | //@ en@ enable the FPU 83 | MRC p15, 0, r0, c1, c0, 2 84 | ORR r0, r0, #0x300000 /* single precision */ 85 | ORR r0, r0, #0xC00000 /* double precision */ 86 | MCR p15, 0, r0, c1, c0, 2 87 | MOV r0, #0x40000000 88 | FMXR fpexc,r0 89 | MOV r0,#0x01000000 90 | FMXR fpscr,r0 91 | BX lr 92 | 93 | 94 | CPU_init_invalidate_tlb: 95 | MOV r2,#0 96 | MCR p15,0,r2,c8,c7,0 97 | MCR p15,0,r2,c7,c10,4 98 | BX lr 99 | 100 | .section .page_table,"a" 101 | .align 14 102 | .globl CPU_init_page_table 103 | CPU_init_page_table: 104 | .space (0x1000 * 4) 105 | -------------------------------------------------------------------------------- /sdk/CPU_init_util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/sdk/CPU_init_util.o -------------------------------------------------------------------------------- /sdk/CPU_start.S: -------------------------------------------------------------------------------- 1 | .text 2 | 3 | .globl CPU_start 4 | 5 | CPU_start: 6 | /* read ARM processor implemetation id */ 7 | MRC p15,0,r0,c0,c0,0 8 | MOV r1,#0x0000F000 9 | AND r1,r0,r1 10 | 11 | /* test if RPI1 */ 12 | MOV r2,#0x0000B000 13 | CMP r1,r2 14 | BEQ SKIP_RPI23 15 | 16 | /* read current processsor status */ 17 | /* it should be in hyp so switch supervisor */ 18 | MRS r0,cpsr 19 | BIC r0,r0,#0xFF 20 | ORR r0,r0,#0xD3 21 | MSR spsr_cxsf,r0 22 | ADD r0,pc,#4 23 | .word 0xe12ef300 24 | // MSR ELR_hyp,r0 , this register is not know when ARMv6 compiling 25 | .word 0xe160006e 26 | //ERET this instruction is not know when Armv6 compiling 27 | 28 | SKIP_RPI23: 29 | LDR sp, =__stack 30 | SUB sp,sp,#64 31 | BL CPU_init 32 | B _start 33 | -------------------------------------------------------------------------------- /sdk/CPU_start.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/sdk/CPU_start.o -------------------------------------------------------------------------------- /sdk/Dockerfile: -------------------------------------------------------------------------------- 1 | # Development container base image 2 | 3 | FROM debian:stretch 4 | 5 | RUN apt-get -q update 6 | 7 | # lang settings 8 | RUN apt-get -q install -y --no-install-recommends locales && locale-gen C.UTF-8 9 | ENV LANG C.UTF-8 10 | ENV LC_ALL C.UTF-8 11 | 12 | # Dependencies: 13 | # sudo: for privileged execution 14 | # curl: used to download files 15 | # bzip2: tarball uncompression 16 | # ca-certificates: HTTPS downloads 17 | RUN apt-get update && apt-get install --no-install-recommends -y \ 18 | sudo \ 19 | bzip2 \ 20 | curl \ 21 | make \ 22 | libncurses5 \ 23 | gawk \ 24 | git \ 25 | ca-certificates 26 | 27 | # Official distribution of the ARM Toolchain 28 | COPY ./scripts/ /tmp/scripts/ 29 | RUN /tmp/scripts/install-toolchain.sh --prefix=/opt/arm-none-eabi 30 | ENV PATH="/opt/arm-none-eabi/bin:$PATH" 31 | 32 | # Helper script to generate the markdown Table of Content 33 | RUN curl -sSL https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc > /usr/local/bin/gh-md-toc \ 34 | && chmod +x /usr/local/bin/gh-md-toc 35 | 36 | # Create a non-root user with the same uid as on the host to allow proper file 37 | # permissions created inside the container. Since it is not root, allow calling 38 | # sudo without password when required. 39 | ARG uid 40 | RUN useradd -m --uid $uid --user-group user \ 41 | && echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/user \ 42 | && chmod a=r,o= /etc/sudoers.d/user 43 | USER user 44 | 45 | # man bash explains SIGTERM is ignored and that SIGHUP 46 | # stops and dispatches the signal to running childs 47 | STOPSIGNAL SIGHUP 48 | -------------------------------------------------------------------------------- /sdk/Makefile: -------------------------------------------------------------------------------- 1 | GNU = arm-none-eabi 2 | CFLAGS = -mfloat-abi=hard -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s -Og -g 3 | 4 | all : libCPU.a 5 | 6 | libCPU.a : CPU_start.o CPU_init.o CPU_init_util.o 7 | $(GNU)-ar -r libCPU.a CPU_init.o CPU_init_util.o 8 | 9 | %.o: %.c 10 | $(GNU)-gcc $(CFLAGS) $^ -c 11 | 12 | %.o: %.S 13 | $(GNU)-gcc $(CFLAGS) $^ -c 14 | 15 | 16 | clean : 17 | rm *.o libCPU.a 18 | 19 | 20 | -------------------------------------------------------------------------------- /sdk/alpha.gdb: -------------------------------------------------------------------------------- 1 | # Full set of registers as sent by Alpha 2 | set tdesc filename sdk/armv6-core.xml 3 | 4 | # Maximum exchange size of large packets 5 | set remote memory-read-packet-size 1024 6 | set remote memory-write-packet-size 1024 7 | 8 | # 9 | # Macro to make current function call back Alpha to restore its exception table. 10 | # The macro replaces current function's return address (LR) with a program 11 | # written at 0x2000 which calls Alpha and then returns to the actual current 12 | # function's caller. 13 | # 14 | # Usage: 15 | # ``` 16 | # tbreak *MY_EXCEPTION_TABLE_INIT_FUNCTION 17 | # command 18 | # alpha_hook_write_restore_exception_table 19 | # continue 20 | # end 21 | # ``` 22 | # Note the use of GDB notation `*function` to set a breakpoint at the exact 23 | # entry address of `function`, before its prolog, because the macro must be used at 24 | # the exact entry point of the function that needs to be hooked. 25 | # 26 | define alpha_hook_write_restore_exception_table 27 | set $freemem = (unsigned int*) 0x2000 28 | set $alpha_callback = (unsigned int) 0x07f09200 29 | 30 | # save the return address to the caller 31 | set *$freemem = $lr 32 | set $freemem += 1 33 | # save the callback address 34 | set *$freemem = $alpha_callback 35 | set $freemem += 3 36 | 37 | # Set the return address to current freemem's address to return to it when 38 | # returning from current function. This is where the program will now be 39 | # written. 40 | set $lr = $freemem 41 | 42 | # Write the following program: 43 | # 0x2010: str r0, [pc, #-16] ; 0x2008 44 | # 0x2014: str r1, [pc, #-16] ; 0x200c 45 | # 0x2018: ldr r2, [pc, #-28] ; 0x2004 46 | # 0x201c: blx r2 47 | # 0x2020: ldr r0, [pc, #-32] ; 0x2008 48 | # 0x2024: ldr r1, [pc, #-32] ; 0x200c 49 | # 0x2028: ldr r2, [pc, #-48] ; 0x2000 50 | # 0x202c: bx r2 51 | # 52 | set *$freemem = 0xe50f0010 53 | set $freemem += 1 54 | set *$freemem = 0xe50f1010 55 | set $freemem += 1 56 | set *$freemem = 0xe51f201c 57 | set $freemem += 1 58 | set *$freemem = 0xe12fff32 59 | set $freemem += 1 60 | set *$freemem = 0xe51f0020 61 | set $freemem += 1 62 | set *$freemem = 0xe51f1020 63 | set $freemem += 1 64 | set *$freemem = 0xe51f2030 65 | set $freemem += 1 66 | set *$freemem = 0xe12fff12 67 | set $freemem += 1 68 | end 69 | -------------------------------------------------------------------------------- /sdk/armv6-core.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /sdk/libalpha.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/sdk/libalpha.a -------------------------------------------------------------------------------- /sdk/libalpha/include/alpha/fileio.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is subject to the terms and conditions defined in 3 | // file 'LICENSE', which is part of this source code package. 4 | // 5 | 6 | #ifndef LIBALPHA_FILEIO_H_ 7 | # define LIBALPHA_FILEIO_H_ 8 | 9 | # ifdef __cplusplus 10 | extern "C" { 11 | # endif 12 | 13 | # include 14 | 15 | extern void FILEIO_OPEN (/* in */ const char* path, 16 | /* in */ fio_uint32_t flags, 17 | /* in */ fio_uint32_t mode, 18 | /* out */ fio_uint32_t* errno, 19 | /* out */ fio_int32_t* return_code); 20 | 21 | extern void FILEIO_CLOSE (/* in */ fio_int32_t fd, 22 | /* out */ fio_uint32_t* errno, 23 | /* out */ fio_int32_t* return_code); 24 | 25 | extern void FILEIO_READ (/* in */ fio_int32_t fd, 26 | /* in */ void* dst, 27 | /* in */ fio_uint32_t count, 28 | /* out */ fio_uint32_t* errno, 29 | /* out */ fio_int32_t* return_code); 30 | 31 | extern void FILEIO_WRITE (/* in */ fio_int32_t fd, 32 | /* in */ const void* src, 33 | /* in */ fio_uint32_t count, 34 | /* out */ fio_uint32_t* errno, 35 | /* out */ fio_int32_t* return_code); 36 | 37 | extern void FILEIO_LSEEK (/* in */ fio_int32_t fd, 38 | /* in */ fio_int32_t offset, 39 | /* in */ fio_uint32_t flag, 40 | /* out */ fio_uint32_t* errno, 41 | /* out */ fio_int32_t* return_code); 42 | 43 | extern void FILEIO_RENAME (/* in */ const char* old_name, 44 | /* in */ const char* new_name, 45 | /* out */ fio_uint32_t* errno, 46 | /* out */ fio_int32_t* return_code); 47 | 48 | extern void FILEIO_UNLINK (/* in */ const char* path, 49 | /* out */ fio_uint32_t* errno, 50 | /* out */ fio_int32_t* return_code); 51 | 52 | extern void FILEIO_STAT (/* in */ const char* path, 53 | /* in */ struct fio_stat* stat, 54 | /* out */ fio_uint32_t* errno, 55 | /* out */ fio_int32_t* return_code); 56 | 57 | extern void FILEIO_FSTAT (/* in */ fio_int32_t fd, 58 | /* in */ struct fio_stat* stat, 59 | /* out */ fio_uint32_t* errno, 60 | /* out */ fio_int32_t* return_code); 61 | 62 | extern void FILEIO_GETTIMEOFDAY (/* in */ struct fio_timeval* timeval, 63 | /* in */ void* timezone, 64 | /* out */ fio_uint32_t* errno, 65 | /* out */ fio_int32_t* return_code); 66 | 67 | extern void FILEIO_ISATTY (/* in */ fio_int32_t fd, 68 | /* out */ fio_uint32_t* errno, 69 | /* out */ fio_int32_t* return_code); 70 | 71 | extern void FILEIO_SYSTEM (/* in */ const char* command, 72 | /* out */ fio_uint32_t* errno, 73 | /* out */ fio_int32_t* return_code); 74 | 75 | # ifdef __cplusplus 76 | } 77 | # endif 78 | 79 | #endif /* !LIBALPHA_FILEIO_H_ */ 80 | -------------------------------------------------------------------------------- /sdk/libalpha/include/gdb/fileio.h: -------------------------------------------------------------------------------- 1 | /* Hosted File I/O interface definitions, for GDB, the GNU Debugger. 2 | 3 | Copyright (C) 2003-2018 Free Software Foundation, Inc. 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . */ 17 | 18 | #ifndef GDB_FILEIO_H_ 19 | #define GDB_FILEIO_H_ 20 | 21 | /* The following flags are defined to be independent of the host 22 | as well as the target side implementation of these constants. 23 | All constants are defined with a leading FILEIO_ in the name 24 | to allow the usage of these constants together with the 25 | corresponding implementation dependent constants in one module. */ 26 | 27 | /* open(2) flags */ 28 | #define FILEIO_O_RDONLY 0x0 29 | #define FILEIO_O_WRONLY 0x1 30 | #define FILEIO_O_RDWR 0x2 31 | #define FILEIO_O_APPEND 0x8 32 | #define FILEIO_O_CREAT 0x200 33 | #define FILEIO_O_TRUNC 0x400 34 | #define FILEIO_O_EXCL 0x800 35 | #define FILEIO_O_SUPPORTED (FILEIO_O_RDONLY | FILEIO_O_WRONLY| \ 36 | FILEIO_O_RDWR | FILEIO_O_APPEND| \ 37 | FILEIO_O_CREAT | FILEIO_O_TRUNC| \ 38 | FILEIO_O_EXCL) 39 | 40 | /* mode_t bits */ 41 | #define FILEIO_S_IFREG 0100000 42 | #define FILEIO_S_IFDIR 040000 43 | #define FILEIO_S_IFCHR 020000 44 | #define FILEIO_S_IRUSR 0400 45 | #define FILEIO_S_IWUSR 0200 46 | #define FILEIO_S_IXUSR 0100 47 | #define FILEIO_S_IRWXU 0700 48 | #define FILEIO_S_IRGRP 040 49 | #define FILEIO_S_IWGRP 020 50 | #define FILEIO_S_IXGRP 010 51 | #define FILEIO_S_IRWXG 070 52 | #define FILEIO_S_IROTH 04 53 | #define FILEIO_S_IWOTH 02 54 | #define FILEIO_S_IXOTH 01 55 | #define FILEIO_S_IRWXO 07 56 | #define FILEIO_S_SUPPORTED (FILEIO_S_IFREG|FILEIO_S_IFDIR| \ 57 | FILEIO_S_IRWXU|FILEIO_S_IRWXG| \ 58 | FILEIO_S_IRWXO) 59 | 60 | /* lseek(2) flags */ 61 | #define FILEIO_SEEK_SET 0 62 | #define FILEIO_SEEK_CUR 1 63 | #define FILEIO_SEEK_END 2 64 | 65 | /* errno values */ 66 | #define FILEIO_EPERM 1 67 | #define FILEIO_ENOENT 2 68 | #define FILEIO_EINTR 4 69 | #define FILEIO_EIO 5 70 | #define FILEIO_EBADF 9 71 | #define FILEIO_EACCES 13 72 | #define FILEIO_EFAULT 14 73 | #define FILEIO_EBUSY 16 74 | #define FILEIO_EEXIST 17 75 | #define FILEIO_ENODEV 19 76 | #define FILEIO_ENOTDIR 20 77 | #define FILEIO_EISDIR 21 78 | #define FILEIO_EINVAL 22 79 | #define FILEIO_ENFILE 23 80 | #define FILEIO_EMFILE 24 81 | #define FILEIO_EFBIG 27 82 | #define FILEIO_ENOSPC 28 83 | #define FILEIO_ESPIPE 29 84 | #define FILEIO_EROFS 30 85 | #define FILEIO_ENOSYS 88 86 | #define FILEIO_ENAMETOOLONG 91 87 | #define FILEIO_EUNKNOWN 9999 88 | 89 | /* limits */ 90 | #define FILEIO_INT_MIN -2147483648L 91 | #define FILEIO_INT_MAX 2147483647L 92 | #define FILEIO_UINT_MAX 4294967295UL 93 | #define FILEIO_LONG_MIN -9223372036854775808LL 94 | #define FILEIO_LONG_MAX 9223372036854775807LL 95 | #define FILEIO_ULONG_MAX 18446744073709551615ULL 96 | 97 | /* Integral types as used in protocol. */ 98 | typedef __INT32_TYPE__ fio_int32_t; 99 | typedef __UINT32_TYPE__ fio_uint32_t, fio_mode_t, fio_time_t; 100 | typedef __INT64_TYPE__ fio_int64_t; 101 | typedef __UINT64_TYPE__ fio_uint64_t; 102 | 103 | /* Struct stat as used in protocol. */ 104 | struct fio_stat { 105 | fio_uint32_t fst_dev; 106 | fio_uint32_t fst_ino; 107 | fio_mode_t fst_mode; 108 | fio_uint32_t fst_nlink; 109 | fio_uint32_t fst_uid; 110 | fio_uint32_t fst_gid; 111 | fio_uint32_t fst_rdev; 112 | fio_uint64_t fst_size; 113 | fio_uint64_t fst_blksize; 114 | fio_uint64_t fst_blocks; 115 | fio_time_t fst_atime; 116 | fio_time_t fst_mtime; 117 | fio_time_t fst_ctime; 118 | }; 119 | 120 | /* Struct timeval as used in protocol. */ 121 | struct fio_timeval { 122 | fio_time_t ftv_sec; 123 | fio_int64_t ftv_usec; 124 | }; 125 | 126 | #endif /* GDB_FILEIO_H_ */ 127 | -------------------------------------------------------------------------------- /sdk/libarm.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/sdk/libarm.a -------------------------------------------------------------------------------- /sdk/libfileio.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/sdk/libfileio.a -------------------------------------------------------------------------------- /sdk/libfileio/src/close.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int close(int fd) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_CLOSE(fd, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/errno.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEIO_ERRNO_H_ 2 | # define FILEIO_ERRNO_H_ 3 | 4 | extern int errno; 5 | 6 | #endif /* !FILEIO_ERRNO_H_ */ 7 | -------------------------------------------------------------------------------- /sdk/libfileio/src/exit.c: -------------------------------------------------------------------------------- 1 | #define X_ASM_OPCODE(OPCODE) ASM_OPCODE(OPCODE) 2 | #define ASM_OPCODE(OPCODE) \ 3 | asm(" .int " #OPCODE "\n"); 4 | 5 | void _exit(int rc) 6 | { 7 | (void) rc; 8 | X_ASM_OPCODE( K_GDB_BREAKPOINT_TRAP ); 9 | while (1); 10 | } 11 | -------------------------------------------------------------------------------- /sdk/libfileio/src/fstat.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int fstat(int fd, struct stat *st) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_FSTAT(fd, (t_fileio_stat*) st, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/gettimeofday.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int gettimeofday(struct timeval* tv, void* tz) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | (void) tz; // not implemented 10 | FILEIO_GETTIMEOFDAY((t_fileio_timeval*) tv, FILEIO_NULL, &errnum, &rc); 11 | 12 | if (rc == -1) { 13 | errno = errnum; 14 | } 15 | return rc; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /sdk/libfileio/src/isatty.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int isatty(int fd) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_ISATTY(fd, &errnum, &rc); 10 | 11 | if (rc == 0) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/lseek.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int lseek(int fd, int offset, int dir) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_LSEEK(fd, offset, dir, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/open.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int open(char* file, int flags, int mode) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_OPEN((t_fileio_uchar*) file, flags, mode, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/read.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int read(int fd, char *buf, int count) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_READ(fd, (t_fileio_uchar*) buf, count, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/stat.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int stat(const char* file, struct stat* st) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_STAT((t_fileio_uchar*) file, (t_fileio_stat*) st, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/unlink.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int unlink(char *name) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_UNLINK((t_fileio_uchar*) name, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/libfileio/src/write.c: -------------------------------------------------------------------------------- 1 | #include "alpha/fileio.h" 2 | #include "errno.h" 3 | 4 | int write(int fd, char* buf, int count) 5 | { 6 | t_fileio_errno errnum; 7 | t_fileio_int32 rc; 8 | 9 | FILEIO_WRITE(fd, (t_fileio_uchar*) buf, count, &errnum, &rc); 10 | 11 | if (rc == -1) { 12 | errno = errnum; 13 | } 14 | return rc; 15 | } 16 | -------------------------------------------------------------------------------- /sdk/link.ld: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Free Software Foundation, Inc. 2 | Copying and distribution of this script, with or without modification, 3 | are permitted in any medium without royalty provided the copyright 4 | notice and this notice are preserved. */ 5 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 6 | OUTPUT_ARCH(arm) 7 | ENTRY(_start) 8 | 9 | SECTIONS 10 | { 11 | /* Read-only sections, merged into text segment: */ 12 | PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x8000)); . = SEGMENT_START("text-segment", 0x8000); 13 | .entry : { CPU_start.o } 14 | .text : { *(.text*) } 15 | .interp : { *(.interp) } 16 | .note.gnu.build-id : { *(.note.gnu.build-id) } 17 | .hash : { *(.hash) } 18 | .gnu.hash : { *(.gnu.hash) } 19 | .dynsym : { *(.dynsym) } 20 | .dynstr : { *(.dynstr) } 21 | .gnu.version : { *(.gnu.version) } 22 | .gnu.version_d : { *(.gnu.version_d) } 23 | .gnu.version_r : { *(.gnu.version_r) } 24 | .rel.dyn : 25 | { 26 | *(.rel.init) 27 | *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) 28 | *(.rel.fini) 29 | *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) 30 | *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) 31 | *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) 32 | *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) 33 | *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) 34 | *(.rel.ctors) 35 | *(.rel.dtors) 36 | *(.rel.got) 37 | *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) 38 | PROVIDE_HIDDEN (__rel_iplt_start = .); 39 | *(.rel.iplt) 40 | PROVIDE_HIDDEN (__rel_iplt_end = .); 41 | } 42 | .rela.dyn : 43 | { 44 | *(.rela.init) 45 | *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) 46 | *(.rela.fini) 47 | *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) 48 | *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) 49 | *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) 50 | *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) 51 | *(.rela.ctors) 52 | *(.rela.dtors) 53 | *(.rela.got) 54 | *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) 55 | PROVIDE_HIDDEN (__rela_iplt_start = .); 56 | *(.rela.iplt) 57 | PROVIDE_HIDDEN (__rela_iplt_end = .); 58 | } 59 | .rel.plt : 60 | { 61 | *(.rel.plt) 62 | } 63 | .rela.plt : 64 | { 65 | *(.rela.plt) 66 | } 67 | .init : 68 | { 69 | KEEP (*(SORT_NONE(.init))) 70 | } 71 | .plt : { *(.plt) } 72 | .iplt : { *(.iplt) } 73 | .fini : 74 | { 75 | KEEP (*(SORT_NONE(.fini))) 76 | } 77 | PROVIDE (__etext = .); 78 | PROVIDE (_etext = .); 79 | PROVIDE (etext = .); 80 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 81 | .rodata1 : { *(.rodata1) } 82 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } 83 | PROVIDE_HIDDEN (__exidx_start = .); 84 | .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } 85 | PROVIDE_HIDDEN (__exidx_end = .); 86 | .eh_frame_hdr : { *(.eh_frame_hdr) } 87 | .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } 88 | .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table 89 | .gcc_except_table.*) } 90 | /* These sections are generated by the Sun/Oracle C++ compiler. */ 91 | .exception_ranges : ONLY_IF_RO { *(.exception_ranges 92 | .exception_ranges*) } 93 | /* Adjust the address for the data segment. We want to adjust up to 94 | the same address within the page on the next page up. */ 95 | . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); 96 | /* Exception handling */ 97 | .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } 98 | .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } 99 | .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } 100 | /* Thread Local Storage sections */ 101 | .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } 102 | .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } 103 | .preinit_array : 104 | { 105 | PROVIDE_HIDDEN (__preinit_array_start = .); 106 | KEEP (*(.preinit_array)) 107 | PROVIDE_HIDDEN (__preinit_array_end = .); 108 | } 109 | .init_array : 110 | { 111 | PROVIDE_HIDDEN (__init_array_start = .); 112 | KEEP (*(SORT(.init_array.*))) 113 | KEEP (*(.init_array )) 114 | PROVIDE_HIDDEN (__init_array_end = .); 115 | } 116 | .fini_array : 117 | { 118 | PROVIDE_HIDDEN (__fini_array_start = .); 119 | KEEP (*(SORT(.fini_array.*))) 120 | KEEP (*(.fini_array )) 121 | PROVIDE_HIDDEN (__fini_array_end = .); 122 | } 123 | .ctors : 124 | { 125 | /* gcc uses crtbegin.o to find the start of 126 | the constructors, so we make sure it is 127 | first. Because this is a wildcard, it 128 | doesn't matter if the user does not 129 | actually link against crtbegin.o; the 130 | linker won't look for a file to match a 131 | wildcard. The wildcard also means that it 132 | doesn't matter which directory crtbegin.o 133 | is in. */ 134 | KEEP (*crtbegin.o(.ctors)) 135 | KEEP (*crtbegin?.o(.ctors)) 136 | /* We don't want to include the .ctor section from 137 | the crtend.o file until after the sorted ctors. 138 | The .ctor section from the crtend file contains the 139 | end of ctors marker and it must be last */ 140 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 141 | KEEP (*(SORT(.ctors.*))) 142 | KEEP (*(.ctors)) 143 | } 144 | .dtors : 145 | { 146 | KEEP (*crtbegin.o(.dtors)) 147 | KEEP (*crtbegin?.o(.dtors)) 148 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 149 | KEEP (*(SORT(.dtors.*))) 150 | KEEP (*(.dtors)) 151 | } 152 | .jcr : { KEEP (*(.jcr)) } 153 | .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } 154 | .dynamic : { *(.dynamic) } 155 | .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } 156 | .data : 157 | { 158 | __data_start = . ; 159 | *(.data .data.* .gnu.linkonce.d.*) 160 | SORT(CONSTRUCTORS) 161 | } 162 | .data1 : { *(.data1) } 163 | _edata = .; PROVIDE (edata = .); 164 | . = .; 165 | __bss_start = .; 166 | __bss_start__ = .; 167 | .bss : 168 | { 169 | *(.dynbss) 170 | *(.bss .bss.* .gnu.linkonce.b.*) 171 | *(COMMON) 172 | /* Align here to ensure that the .bss section occupies space up to 173 | _end. Align after .bss to ensure correct alignment even if the 174 | .bss section disappears because there are no input sections. 175 | FIXME: Why do we need it? When there is no .bss section, we don't 176 | pad the .data section. */ 177 | . = ALIGN(. != 0 ? 32 / 8 : 1); 178 | } 179 | _bss_end__ = . ; __bss_end__ = . ; 180 | . = ALIGN(32 / 8); 181 | . = SEGMENT_START("ldata-segment", .); 182 | . = ALIGN(32 / 8); 183 | __end__ = . ; 184 | _end = .; PROVIDE (end = .); 185 | 186 | . = 0x07EFC000; 187 | .page_table (NOLOAD) : { *(.page_table) } 188 | 189 | 190 | 191 | /* Stabs debugging sections. */ 192 | .stab 0 : { *(.stab) } 193 | .stabstr 0 : { *(.stabstr) } 194 | .stab.excl 0 : { *(.stab.excl) } 195 | .stab.exclstr 0 : { *(.stab.exclstr) } 196 | .stab.index 0 : { *(.stab.index) } 197 | .stab.indexstr 0 : { *(.stab.indexstr) } 198 | .comment 0 : { *(.comment) } 199 | /* DWARF debug sections. 200 | Symbols in the DWARF debugging sections are relative to the beginning 201 | of the section so we begin them at 0. */ 202 | /* DWARF 1 */ 203 | .debug 0 : { *(.debug) } 204 | .line 0 : { *(.line) } 205 | /* GNU DWARF 1 extensions */ 206 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 207 | .debug_sfnames 0 : { *(.debug_sfnames) } 208 | /* DWARF 1.1 and DWARF 2 */ 209 | .debug_aranges 0 : { *(.debug_aranges) } 210 | .debug_pubnames 0 : { *(.debug_pubnames) } 211 | /* DWARF 2 */ 212 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } 213 | .debug_abbrev 0 : { *(.debug_abbrev) } 214 | .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } 215 | .debug_frame 0 : { *(.debug_frame) } 216 | .debug_str 0 : { *(.debug_str) } 217 | .debug_loc 0 : { *(.debug_loc) } 218 | .debug_macinfo 0 : { *(.debug_macinfo) } 219 | /* SGI/MIPS DWARF 2 extensions */ 220 | .debug_weaknames 0 : { *(.debug_weaknames) } 221 | .debug_funcnames 0 : { *(.debug_funcnames) } 222 | .debug_typenames 0 : { *(.debug_typenames) } 223 | .debug_varnames 0 : { *(.debug_varnames) } 224 | /* DWARF 3 */ 225 | .debug_pubtypes 0 : { *(.debug_pubtypes) } 226 | .debug_ranges 0 : { *(.debug_ranges) } 227 | /* DWARF Extension. */ 228 | .debug_macro 0 : { *(.debug_macro) } 229 | .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } 230 | .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } 231 | /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } 232 | } 233 | 234 | 235 | __stack = 0x07EFBF00; 236 | -------------------------------------------------------------------------------- /srce/zjoin.c: -------------------------------------------------------------------------------- 1 | // ZeroWi bare-metal WiFi driver, see https://iosoft.blog/zerowi 2 | // Raspberry Pi WiFi network scan 3 | // 4 | // Copyright (c) 2020 Jeremy P Bentham 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | // 18 | #define VERSION "0.75" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "whd_types.h" 26 | #include "whd_wlioctl.h" 27 | #include "whd_events.h" 28 | 29 | #include "zw_gpio.h" 30 | #include "zw_sdio.h" 31 | #include "zw_regs.h" 32 | #include "zw_ioctl.h" 33 | 34 | // SSID 35 | #define SSID "testnet" 36 | #define COUNTRY "GB" 37 | #define COUNTRY_REV -1 38 | wlc_ssid_t ssid={sizeof(SSID)-1, SSID}; 39 | wl_country_t country_struct = {.ccode=COUNTRY, .country_abbrev=COUNTRY, .rev=COUNTRY_REV}; 40 | 41 | // Security settings: 0 for none, 1 for WPA_TKIP, 2 for WPA2 42 | // The hard-coded password is for test purposes only!!! 43 | #define SECURITY 2 44 | #define PASSPHRASE "testpass" 45 | wsec_pmk_t wsec_pmk = {sizeof(PASSPHRASE)-1, WSEC_PASSPHRASE, PASSPHRASE}; 46 | 47 | // Set non-zero to include WiFi firmware in image 48 | #define INCLUDE_FIRMWARE 1 49 | #define FIRMWARE_FNAME "../firmware/brcmfmac43430-sdio.c" 50 | 51 | // Length of firmware file (rounded up to 4-byte value) 52 | #define FIRMWARE_LEN 0x5ee84 53 | #if INCLUDE_FIRMWARE 54 | extern const unsigned char firmware_bin[FIRMWARE_LEN]; 55 | uint32_t firmware_pos; 56 | #endif 57 | 58 | // Configuration for brcmfmac43430-sdio 59 | uint8_t config_data[] = 60 | "manfid=0x2d0\0""prodid=0x0726\0""vendid=0x14e4\0""devid=0x43e2\0" 61 | "boardtype=0x0726\0""boardrev=0x1202\0""boardnum=22\0""macaddr=00:90:4c:c5:12:38\0" 62 | "sromrev=11\0""boardflags=0x00404201\0""boardflags3=0x08000000\0""xtalfreq=37400\0" 63 | "nocrc=1\0""ag0=255\0""aa2g=1\0""ccode=ALL\0""pa0itssit=0x20\0""extpagain2g=0\0" 64 | "pa2ga0=-168,7161,-820\0""AvVmid_c0=0x0,0xc8\0""cckpwroffset0=5\0""maxp2ga0=84\0" 65 | "txpwrbckof=6\0""cckbw202gpo=0\0""legofdmbw202gpo=0x66111111\0" 66 | "mcsbw202gpo=0x77711111\0""propbw202gpo=0xdd\0""ofdmdigfilttype=18\0" 67 | "ofdmdigfilttypebe=18\0""papdmode=1\0""papdvalidtest=1\0""pacalidx2g=32\0" 68 | "papdepsoffset=-36\0""papdendidx=61\0""il0macaddr=00:90:4c:c5:12:38\0" 69 | "wl0id=0x431b\0""deadman_to=0xffffffff\0""muxenab=0x1\0""spurconfig=0x3 \0" 70 | "btc_mode=1\0""btc_params8=0x4e20\0""btc_params1=0x7530\0""\0\0\0\0\xaa\x00\x55\xff"; 71 | int config_len = sizeof(config_data) - 1; 72 | 73 | // SDIO Tx buffer (must be multiple of 256, and less than 32K) 74 | uint8_t txbuffer[0x4000]; 75 | 76 | #define CHECK(f, a, ...) {if (!f(a, __VA_ARGS__)) \ 77 | printf("Error: %s(%s ...)\n", #f, #a);} 78 | 79 | #define DISP_BLOCKLEN 32 80 | uint8_t eventbuff[1600]; 81 | 82 | // State of SDIO clock line 83 | extern uint8_t clkval; 84 | 85 | // Event groups 86 | EVT_STR join_evts[]=JOIN_EVTS, no_evts[]=NO_EVTS; 87 | 88 | // Event field displays 89 | char eth_hdr_fields[] = "6:dest 6:srce 2;type"; 90 | char event_hdr_fields[] = "2;sub 2;len 1: 3;oui 2;usr"; 91 | char event_msg_fields[] = "2;ver 2;flags 4;type 4;status 4;reason 4:auth 4;dlen 6;addr 18:"; 92 | 93 | void disp_ssid(uint8_t *data); 94 | void disp_mac_addr(uint8_t *data); 95 | void disp_block(uint8_t *data, int len); 96 | void gdb_break(void); 97 | int sdio_init(void); 98 | int write_firmware(void); 99 | int write_nvram(void); 100 | void disp_bytes(uint8_t *addr, int len); 101 | void sd_setup(void); 102 | 103 | int main(void) 104 | { 105 | int ticks=0, ledon=0, n, startime=ustime(); 106 | uint8_t resp[128] = {0}, eth[7]={0}; 107 | IOCTL_EVENT_HDR ieh; 108 | ETH_EVENT_FRAME *eep = (ETH_EVENT_FRAME *)eventbuff; 109 | 110 | crc7_init(); 111 | qcrc16r_init(); 112 | ustimeout(&ticks, 0); 113 | printf("\nZerowi network join test v" VERSION "\n"); 114 | fflush(stdout); 115 | osc_init(); 116 | gpio_set(LED_PIN, GPIO_OUT, GPIO_NOPULL); 117 | sd_setup(); 118 | gpio_out(WLAN_ON_PIN, 1); 119 | flash_init(10000); 120 | usdelay(10000); 121 | log_enable(2); 122 | sdio_init(); 123 | sdio_cmd53_read(SD_FUNC_RAD, SB_32BIT_WIN, resp, 64); 124 | n = ioctl_get_data("cur_etheraddr", 0, eth, 6); 125 | printf("MAC address "); 126 | if (n) 127 | disp_mac_addr(eth); 128 | else 129 | printf("unavailable"); 130 | n = ioctl_get_data("ver", 0, resp, sizeof(resp)); 131 | printf("\nFirmware %s\n", (n ? (char *)resp : "not responding")); 132 | if (!ioctl_set_data("country", 100, &country_struct, sizeof(country_struct))) 133 | printf("Can't set country\n"); 134 | if (!ioctl_wr_int32(WLC_UP, 200, 0)) 135 | { 136 | printf("WiFi CPU not running\n"); 137 | fflush(stdout); 138 | gdb_break(); 139 | } 140 | ioctl_enable_evts(no_evts); 141 | CHECK(ioctl_wr_int32, WLC_SET_INFRA, 50, 1); 142 | CHECK(ioctl_wr_int32, WLC_SET_AUTH, 0, 0); 143 | #if SECURITY 144 | CHECK(ioctl_wr_int32, WLC_SET_WSEC, 0, SECURITY==2 ? 6 : 2); 145 | CHECK(ioctl_set_intx2, "bsscfg:sup_wpa", 0, 0, 1); 146 | CHECK(ioctl_set_intx2, "bsscfg:sup_wpa2_eapver", 0, 0, -1); 147 | CHECK(ioctl_set_intx2, "bsscfg:sup_wpa_tmo", 0, 0, 2500); 148 | CHECK(ioctl_wr_data, WLC_SET_WSEC_PMK, 0, &wsec_pmk, sizeof(wsec_pmk)); 149 | CHECK(ioctl_wr_int32, WLC_SET_WPA_AUTH, 0, SECURITY==2 ? 0x80 : 4); 150 | #else 151 | CHECK(ioctl_wr_int32, WLC_SET_WSEC, 0, 0); 152 | CHECK(ioctl_wr_int32, WLC_SET_WPA_AUTH, 0, 0); 153 | #endif 154 | ioctl_enable_evts(join_evts); 155 | CHECK(ioctl_wr_data, WLC_SET_SSID, 100, &ssid, sizeof(ssid)); 156 | 157 | while (1) 158 | { 159 | usdelay(SD_CLK_DELAY); 160 | gpio_out(SD_CLK_PIN, clkval=!clkval); 161 | if (ustimeout(&ticks, 20000)) 162 | { 163 | gpio_out(LED_PIN, ledon = !ledon); 164 | if (!ledon) 165 | { 166 | printf("."); 167 | fflush(stdout); 168 | } 169 | else 170 | { 171 | if ((n=ioctl_get_event(&ieh, eventbuff, sizeof(eventbuff))) > 0) 172 | { 173 | printf("\n%2.3f ", (ustime() - startime) / 1e6); 174 | disp_fields(&ieh, ioctl_event_hdr_fields, n); 175 | printf("\n"); 176 | disp_bytes((uint8_t *)&ieh, sizeof(ieh)); 177 | printf("\n"); 178 | disp_fields(&eep->eth_hdr, eth_hdr_fields, sizeof(eep->eth_hdr)); 179 | if (SWAP16(eep->eth_hdr.ethertype) == 0x886c) 180 | { 181 | disp_fields(&eep->event.hdr, event_hdr_fields, sizeof(eep->event.hdr)); 182 | printf("\n"); 183 | disp_fields(&eep->event.msg, event_msg_fields, sizeof(eep->event.msg)); 184 | printf("%s %s", ioctl_evt_str(SWAP32(eep->event.msg.event_type)), 185 | ioctl_evt_status_str(SWAP32(eep->event.msg.status))); 186 | } 187 | printf("\n"); 188 | disp_block(eventbuff, n); 189 | printf("\n"); 190 | } 191 | } 192 | } 193 | } 194 | } 195 | 196 | // Display SSID, prefixed with length byte 197 | void disp_ssid(uint8_t *data) 198 | { 199 | int i=*data++; 200 | 201 | if (i == 0 || *data == 0) 202 | printf("[hidden]"); 203 | else if (i <= SSID_MAXLEN) 204 | { 205 | while (i-- > 0) 206 | putchar(*data++); 207 | } 208 | else 209 | printf("[invalid length %u]", i); 210 | } 211 | 212 | // Display MAC address 213 | void disp_mac_addr(uint8_t *data) 214 | { 215 | int i; 216 | 217 | for (i=0; i<6; i++) 218 | printf("%s%02X", i?":":"", data[i]); 219 | } 220 | 221 | // Display block of data 222 | void disp_block(uint8_t *data, int len) 223 | { 224 | int i=0, n; 225 | 226 | while (i < len) 227 | { 228 | if (i > 0) 229 | printf("\n"); 230 | n = MIN(len-i, DISP_BLOCKLEN); 231 | disp_bytes(&data[i], n); 232 | i += n; 233 | fflush(stdout); 234 | } 235 | } 236 | 237 | // Dummy function to trigger debug breakpoint 238 | void gdb_break(void) 239 | { 240 | } // Trigger GDB break 241 | 242 | // Initialise SDIO card, return RCA 243 | int sdio_init(void) 244 | { 245 | SDIO_MSG resp; 246 | int rca=0; 247 | U32DATA u32d; 248 | uint8_t data[520]; 249 | 250 | sdio_cmd52(SD_FUNC_BUS, 0x06, 0, SD_RD, 0, 0); 251 | usdelay(20000); 252 | sdio_cmd52(SD_FUNC_BUS, 0x06, 8, SD_WR, 0, 0); 253 | usdelay(20000); 254 | sdio_cmd(0, 0, 0); 255 | sdio_cmd(8, 0x1aa, 0); 256 | // Enable I/O mode 257 | sdio_cmd(5, 0, 0); 258 | sdio_cmd(5, 0x200000, 0); 259 | // Assert SD device 260 | sdio_cmd(3, 0, &resp); 261 | rca = SWAP16(resp.rsp3.rcax); 262 | sdio_cmd7(rca, 0); 263 | // [0.243831] Set bus interface 264 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_SPEED_CTRL_REG, 0x03, 1); 265 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_BI_CTRL_REG, 0x42, 1); 266 | // [17.999101] Set block sizes 267 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_BAK_BLKSIZE_REG, SD_BAK_BLK_BYTES, 2); 268 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_RAD_BLKSIZE_REG, SD_RAD_BLK_BYTES, 2); 269 | // [17.999944] Enable I/O 270 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_IOEN_REG, 1< 0) 425 | { 426 | firm_read(txbuffer, nblocks*SD_BAK_BLK_BYTES); 427 | n = sdio_write_blocks(SD_FUNC_BAK, SB_32BIT_WIN+addr, txbuffer, nblocks); 428 | if (!n) 429 | break; 430 | nbytes += nblocks * SD_BAK_BLK_BYTES; 431 | } 432 | else 433 | { 434 | firm_read(txbuffer, len); 435 | sdio_cmd53_write(SD_FUNC_BAK, SB_32BIT_WIN+addr, txbuffer, len); 436 | nbytes += len; 437 | } 438 | } 439 | firm_close(); 440 | return(nbytes); 441 | } 442 | 443 | // Upload blocks of config data to chip NVRAM 444 | int write_nvram(void) 445 | { 446 | int nbytes=0, len; 447 | 448 | sdio_bak_window(0x078000); 449 | while (nbytes < config_len) 450 | { 451 | len = MIN(config_len-nbytes, SD_BAK_BLK_BYTES); 452 | sdio_cmd53_write(SD_FUNC_BAK, 0xfd54+nbytes, &config_data[nbytes], len); 453 | nbytes += len; 454 | } 455 | return(nbytes); 456 | } 457 | 458 | // Set up SD interface 459 | void sd_setup(void) 460 | { 461 | gpio_set(SD_CLK_PIN, GPIO_OUT, GPIO_NOPULL); 462 | gpio_set(SD_CMD_PIN, GPIO_IN, GPIO_PULLUP); 463 | gpio_set(SD_D0_PIN, GPIO_IN, GPIO_PULLUP); 464 | gpio_set(SD_D1_PIN, GPIO_IN, GPIO_PULLUP); 465 | gpio_set(SD_D2_PIN, GPIO_IN, GPIO_PULLUP); 466 | gpio_set(SD_D3_PIN, GPIO_IN, GPIO_PULLUP); 467 | } 468 | 469 | #if INCLUDE_FIRMWARE 470 | #include FIRMWARE_FNAME 471 | #endif 472 | // EOF 473 | -------------------------------------------------------------------------------- /srce/zscan.c: -------------------------------------------------------------------------------- 1 | // ZeroWi bare-metal WiFi driver, see https://iosoft.blog/zerowi 2 | // Raspberry Pi WiFi network scan 3 | // 4 | // Copyright (c) 2020 Jeremy P Bentham 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | #define VERSION "0.76" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "whd_types.h" 26 | #include "whd_events.h" 27 | #include "whd_wlioctl.h" 28 | 29 | #include "zw_gpio.h" 30 | #include "zw_sdio.h" 31 | #include "zw_regs.h" 32 | #include "zw_ioctl.h" 33 | 34 | // WiFi channel number to scan (0 for all channels) 35 | #define SCAN_CHAN 1 36 | 37 | // Set non-zero to include WiFi firmware in image 38 | #define INCLUDE_FIRMWARE 1 39 | #define FIRMWARE_FNAME "../firmware/brcmfmac43430-sdio.c" 40 | 41 | // Length of firmware file (rounded up to 4-byte value) 42 | #define FIRMWARE_LEN 0x5ee84 43 | #if INCLUDE_FIRMWARE 44 | extern const unsigned char firmware_bin[FIRMWARE_LEN]; 45 | uint32_t firmware_pos; 46 | #endif 47 | 48 | // Configuration for brcmfmac43430-sdio 49 | uint8_t config_data[] = 50 | "manfid=0x2d0\0""prodid=0x0726\0""vendid=0x14e4\0""devid=0x43e2\0" 51 | "boardtype=0x0726\0""boardrev=0x1202\0""boardnum=22\0""macaddr=00:90:4c:c5:12:38\0" 52 | "sromrev=11\0""boardflags=0x00404201\0""boardflags3=0x08000000\0""xtalfreq=37400\0" 53 | "nocrc=1\0""ag0=255\0""aa2g=1\0""ccode=ALL\0""pa0itssit=0x20\0""extpagain2g=0\0" 54 | "pa2ga0=-168,7161,-820\0""AvVmid_c0=0x0,0xc8\0""cckpwroffset0=5\0""maxp2ga0=84\0" 55 | "txpwrbckof=6\0""cckbw202gpo=0\0""legofdmbw202gpo=0x66111111\0" 56 | "mcsbw202gpo=0x77711111\0""propbw202gpo=0xdd\0""ofdmdigfilttype=18\0" 57 | "ofdmdigfilttypebe=18\0""papdmode=1\0""papdvalidtest=1\0""pacalidx2g=32\0" 58 | "papdepsoffset=-36\0""papdendidx=61\0""il0macaddr=00:90:4c:c5:12:38\0" 59 | "wl0id=0x431b\0""deadman_to=0xffffffff\0""muxenab=0x1\0""spurconfig=0x3 \0" 60 | "btc_mode=1\0""btc_params8=0x4e20\0""btc_params1=0x7530\0""\0\0\0\0\xaa\x00\x55\xff"; 61 | int config_len = sizeof(config_data) - 1; 62 | 63 | // SDIO Tx buffer (must be multiple of 256, and less than 32K) 64 | uint8_t txbuffer[0x4000]; 65 | 66 | // Network scan parameters 67 | #define SCAN_CHAN_TIME 40 68 | #define SSID_MAXLEN 32 69 | #define SCANTYPE_ACTIVE 0 70 | #define SCANTYPE_PASSIVE 1 71 | typedef struct { 72 | uint32_t version; 73 | uint16_t action, 74 | sync_id; 75 | uint32_t ssidlen; 76 | uint8_t ssid[SSID_MAXLEN], 77 | bssid[6], 78 | bss_type, 79 | scan_type; 80 | uint32_t nprobes, 81 | active_time, 82 | passive_time, 83 | home_time; 84 | uint16_t nchans, 85 | nssids; 86 | uint8_t chans[14][2], 87 | ssids[1][SSID_MAXLEN]; 88 | } SCAN_PARAMS; 89 | SCAN_PARAMS scan_params = { 90 | .version=1, .action=1, .sync_id=0x1234, .ssidlen=0, .ssid={0}, 91 | .bssid={0xff,0xff,0xff,0xff,0xff,0xff}, .bss_type=2, 92 | .scan_type=SCANTYPE_PASSIVE, .nprobes=~0, .active_time=~0, 93 | .passive_time=~0, .home_time=~0, 94 | #if SCAN_CHAN == 0 95 | .nchans=14, .nssids=0, 96 | .chans={{1,0x2b},{2,0x2b},{3,0x2b},{4,0x2b},{5,0x2b},{6,0x2b},{7,0x2b}, 97 | {8,0x2b},{9,0x2b},{10,0x2b},{11,0x2b},{12,0x2b},{13,0x2b},{14,0x2b}}, 98 | #else 99 | .nchans=1, .nssids=0, .chans={{SCAN_CHAN,0x2b}}, .ssids={{0}} 100 | #endif 101 | }; 102 | 103 | // Escan result event (excluding 12-byte IOCTL header) 104 | typedef struct { 105 | uint8_t pad[10]; 106 | whd_event_t event; 107 | wl_escan_result_t escan; 108 | } escan_result; 109 | 110 | // IOCTL commands 111 | #define IOCTL_UP 2 112 | #define IOCTL_SET_SCAN_CHANNEL_TIME 0xb9 113 | 114 | // Event handling 115 | uint8_t eventbuff[1600]; 116 | EVT_STR escan_evts[]=ESCAN_EVTS; 117 | 118 | // State of SDIO clock line 119 | extern uint8_t clkval; 120 | 121 | void disp_ssid(uint8_t *data); 122 | void disp_mac_addr(uint8_t *data); 123 | void disp_block(uint8_t *data, int len); 124 | void gdb_break(void); 125 | int sdio_init(void); 126 | int write_firmware(void); 127 | int write_nvram(void); 128 | void disp_bytes(uint8_t *addr, int len); 129 | void sd_setup(void); 130 | 131 | int main(void) 132 | { 133 | int ticks=0, ledon=0, n; 134 | uint32_t val=0; 135 | uint8_t resp[256] = {0}, eth[7]={0}; 136 | IOCTL_EVENT_HDR ieh; 137 | escan_result *erp = (escan_result *)eventbuff; 138 | 139 | crc7_init(); 140 | qcrc16r_init(); 141 | ustimeout(&ticks, 0); 142 | printf("\nZerowi scan test v" VERSION "\n"); 143 | fflush(stdout); 144 | osc_init(); 145 | gpio_set(LED_PIN, GPIO_OUT, GPIO_NOPULL); 146 | sd_setup(); 147 | gpio_out(WLAN_ON_PIN, 1); 148 | flash_init(10000); 149 | usdelay(10000); 150 | log_enable(2); 151 | sdio_init(); 152 | sdio_cmd53_read(SD_FUNC_RAD, SB_32BIT_WIN, resp, 64); 153 | n = ioctl_get_data("cur_etheraddr", 0, eth, 6); 154 | printf("MAC address "); 155 | if (n) 156 | disp_mac_addr(eth); 157 | else 158 | printf("unavailable"); 159 | n = ioctl_get_data("ver", 0, resp, sizeof(resp)); 160 | printf("\nFirmware %s\n", (n ? (char *)resp : "not responding")); 161 | ioctl_wr_int32(IOCTL_SET_SCAN_CHANNEL_TIME, 0, SCAN_CHAN_TIME); 162 | if (!ioctl_wr_int32(WLC_UP, 200, 0)) 163 | { 164 | printf("WiFi CPU not running\n"); 165 | fflush(stdout); 166 | gdb_break(); 167 | } 168 | sdio_bak_write32(SB_INT_STATUS_REG, val); 169 | sdio_cmd53_read(SD_FUNC_RAD, SB_32BIT_WIN, (void *)resp, 64); 170 | ioctl_enable_evts(escan_evts); 171 | ioctl_set_data("escan", 0, &scan_params, sizeof(scan_params)); 172 | while (1) 173 | { 174 | usdelay(SD_CLK_DELAY); 175 | gpio_out(SD_CLK_PIN, clkval=!clkval); 176 | if (ustimeout(&ticks, 100000)) 177 | { 178 | gpio_out(LED_PIN, ledon = !ledon); 179 | if (!ledon) 180 | { 181 | n = ioctl_get_event(&ieh, eventbuff, sizeof(eventbuff)); 182 | if (n > sizeof(escan_result)) 183 | { 184 | printf("%u bytes\n", n); 185 | disp_mac_addr((uint8_t *)&erp->event.whd_event.addr); 186 | printf(" %2u ", SWAP16(erp->escan.bss_info->chanspec)); 187 | disp_ssid(&erp->escan.bss_info->SSID_len); 188 | printf("\n"); 189 | fflush(stdout); 190 | } 191 | else 192 | { 193 | printf("."); 194 | fflush(stdout); 195 | } 196 | } 197 | } 198 | } 199 | } 200 | 201 | // Display SSID, prefixed with length byte 202 | void disp_ssid(uint8_t *data) 203 | { 204 | int i=*data++; 205 | 206 | if (i == 0 || *data == 0) 207 | printf("[hidden]"); 208 | else if (i <= SSID_MAXLEN) 209 | { 210 | while (i-- > 0) 211 | putchar(*data++); 212 | } 213 | else 214 | printf("[invalid length %u]", i); 215 | } 216 | 217 | // Display MAC address 218 | void disp_mac_addr(uint8_t *data) 219 | { 220 | int i; 221 | 222 | for (i=0; i<6; i++) 223 | printf("%s%02X", i?":":"", data[i]); 224 | } 225 | 226 | // Display block of data 227 | void disp_block(uint8_t *data, int len) 228 | { 229 | int i=0, n; 230 | 231 | while (i < len) 232 | { 233 | n = MIN(len-i, 32); 234 | disp_bytes(&eventbuff[i], n); 235 | i += n; 236 | printf("\n"); 237 | fflush(stdout); 238 | } 239 | } 240 | 241 | // Dummy function to trigger debug breakpoint 242 | void gdb_break(void) 243 | { 244 | } // Trigger GDB break 245 | 246 | // Initialise SDIO card, return RCA 247 | int sdio_init(void) 248 | { 249 | SDIO_MSG resp; 250 | int rca=0; 251 | U32DATA u32d; 252 | uint8_t data[520]; 253 | 254 | sdio_cmd52(SD_FUNC_BUS, 0x06, 0, SD_RD, 0, 0); 255 | usdelay(20000); 256 | sdio_cmd52(SD_FUNC_BUS, 0x06, 8, SD_WR, 0, 0); 257 | usdelay(20000); 258 | sdio_cmd(0, 0, 0); 259 | sdio_cmd(8, 0x1aa, 0); 260 | // Enable I/O mode 261 | sdio_cmd(5, 0, 0); 262 | sdio_cmd(5, 0x200000, 0); 263 | // Assert SD device 264 | sdio_cmd(3, 0, &resp); 265 | rca = SWAP16(resp.rsp3.rcax); 266 | sdio_cmd7(rca, 0); 267 | // [0.243831] Set bus interface 268 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_SPEED_CTRL_REG, 0x03, 1); 269 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_BI_CTRL_REG, 0x42, 1); 270 | // [17.999101] Set block sizes 271 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_BAK_BLKSIZE_REG, SD_BAK_BLK_BYTES, 2); 272 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_RAD_BLKSIZE_REG, SD_RAD_BLK_BYTES, 2); 273 | // [17.999944] Enable I/O 274 | sdio_cmd52_writes(SD_FUNC_BUS, BUS_IOEN_REG, 1< 0) 429 | { 430 | firm_read(txbuffer, nblocks*SD_BAK_BLK_BYTES); 431 | n = sdio_write_blocks(SD_FUNC_BAK, SB_32BIT_WIN+addr, txbuffer, nblocks); 432 | if (!n) 433 | break; 434 | nbytes += nblocks * SD_BAK_BLK_BYTES; 435 | } 436 | else 437 | { 438 | firm_read(txbuffer, len); 439 | sdio_cmd53_write(SD_FUNC_BAK, SB_32BIT_WIN+addr, txbuffer, len); 440 | nbytes += len; 441 | } 442 | } 443 | firm_close(); 444 | return(nbytes); 445 | } 446 | 447 | // Upload blocks of config data to chip NVRAM 448 | int write_nvram(void) 449 | { 450 | int nbytes=0, len; 451 | 452 | sdio_bak_window(0x078000); 453 | while (nbytes < config_len) 454 | { 455 | len = MIN(config_len-nbytes, SD_BAK_BLK_BYTES); 456 | sdio_cmd53_write(SD_FUNC_BAK, 0xfd54+nbytes, &config_data[nbytes], len); 457 | nbytes += len; 458 | } 459 | return(nbytes); 460 | } 461 | 462 | // Set up SD interface 463 | void sd_setup(void) 464 | { 465 | gpio_set(SD_CLK_PIN, GPIO_OUT, GPIO_NOPULL); 466 | gpio_set(SD_CMD_PIN, GPIO_IN, GPIO_PULLUP); 467 | gpio_set(SD_D0_PIN, GPIO_IN, GPIO_PULLUP); 468 | gpio_set(SD_D1_PIN, GPIO_IN, GPIO_PULLUP); 469 | gpio_set(SD_D2_PIN, GPIO_IN, GPIO_PULLUP); 470 | gpio_set(SD_D3_PIN, GPIO_IN, GPIO_PULLUP); 471 | } 472 | 473 | #if INCLUDE_FIRMWARE 474 | #include FIRMWARE_FNAME 475 | #endif 476 | // EOF 477 | 478 | -------------------------------------------------------------------------------- /srce/zw_gpio.c: -------------------------------------------------------------------------------- 1 | // ZeroWi bare-metal WiFi driver, see https://iosoft.blog/zerowi 2 | // Raspberry Pi GPIO interface 3 | // 4 | // Copyright (c) 2020 Jeremy P Bentham 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "zw_gpio.h" 25 | 26 | #define INCLUDE_MAIN 0 27 | 28 | #if USE_MMAP 29 | #include 30 | #endif 31 | 32 | #define PAGE_SIZE 0x1000 33 | 34 | #define USEC_BASE (REG_BASE + 0x3000) 35 | #define USEC_SIZE PAGE_SIZE 36 | 37 | #define GPIO_BASE (REG_BASE + 0x200000) 38 | #define GPIO_SIZE 0x20000 39 | #define GPIO_MODE0 (uint32_t *)GPIO_BASE 40 | #define GPIO_SET0 (uint32_t *)(GPIO_BASE + 0x1c) 41 | #define GPIO_CLR0 (uint32_t *)(GPIO_BASE + 0x28) 42 | #define GPIO_LEV0 (uint32_t *)(GPIO_BASE + 0x34) 43 | #define GPIO_GPPUD (uint32_t *)(GPIO_BASE + 0x94) 44 | #define GPIO_GPPUDCLK0 (uint32_t *)(GPIO_BASE + 0x98) 45 | 46 | #define SPI0_BASE (REG_BASE + 0x204000) 47 | #define SPI0_CS (uint32_t *)SPI0_BASE 48 | #define SPI0_FIFO (uint32_t *)(SPI0_BASE + 0x04) 49 | #define SPI0_CLK (uint32_t *)(SPI0_BASE + 0x08) 50 | #define SPI0_DLEN (uint32_t *)(SPI0_BASE + 0x0c) 51 | #define SPI0_DC (uint32_t *)(SPI0_BASE + 0x14) 52 | 53 | #if USE_MMAP 54 | #define GPIO_REG(a) ((uint32_t *)((uint32_t)a - GPIO_BASE + (uint32_t)gpio_block)) 55 | #define USEC_REG() ((uint32_t *)(usec_block+4)) 56 | #else 57 | #define GPIO_REG(a) ((uint32_t *)a) 58 | #define USEC_REG() ((uint32_t *)(USEC_BASE+4)) 59 | #endif 60 | 61 | #define GPIO_IN 0 62 | #define GPIO_OUT 1 63 | #define GPIO_ALT0 4 64 | #define GPIO_ALT1 5 65 | #define GPIO_ALT2 6 66 | #define GPIO_ALT3 7 67 | #define GPIO_ALT4 3 68 | #define GPIO_ALT5 2 69 | 70 | #define GPIO_NOPULL 0 71 | #define GPIO_PULLDN 1 72 | #define GPIO_PULLUP 2 73 | 74 | #define LED_PIN 47 75 | #define SPI0_CE0_PIN 8 76 | #define SPI0_MISO_PIN 9 77 | #define SPI0_MOSI_PIN 10 78 | #define SPI0_SCLK_PIN 11 79 | 80 | volatile void *gpio_block, *usec_block; 81 | 82 | #if INCLUDE_MAIN 83 | int main(int argc, char **argv) 84 | { 85 | int ticks=0, ledon=0; 86 | uint8_t rxdata[100]; 87 | 88 | gpio_set(LED_PIN, GPIO_OUT, GPIO_NOPULL); 89 | gpio_out(LED_PIN, 0); 90 | spi0_init(10000); 91 | ustimeout(&ticks, 0); 92 | while (1) 93 | { 94 | if (ustimeout(&ticks, 500000)) 95 | { 96 | gpio_out(LED_PIN, ledon = !ledon); 97 | flash_open_read(4); 98 | flash_read(rxdata, 10); 99 | flash_close(); 100 | disp_mem(rxdata, 10); 101 | printf("\n"); 102 | fflush(stdout); 103 | } 104 | } 105 | return(0); 106 | } 107 | #endif 108 | 109 | // Start a flash read cycle (EN25Q80 device) 110 | void flash_open_read(int addr) 111 | { 112 | uint8_t rxdata[4], txdata[4]={3, (uint8_t)(addr>>16), (uint8_t)(addr>>8), (uint8_t)(addr)}; 113 | 114 | spi0_cs(1); 115 | spi0_xfer(txdata, rxdata, 4); 116 | } 117 | // Read next block 118 | void flash_read(uint8_t *dp, int len) 119 | { 120 | while (len--) 121 | { 122 | *SPI0_FIFO = 0; 123 | while((*SPI0_CS & (1<<17)) == 0) ; 124 | *dp++ = *SPI0_FIFO; 125 | } 126 | } 127 | // End a flash ycle 128 | void flash_close(void) 129 | { 130 | spi0_cs(0); 131 | } 132 | 133 | // Initialise flash interface (SPI0) 134 | void flash_init(int khz) 135 | { 136 | gpio_set(SPI0_CE0_PIN, GPIO_ALT0, GPIO_NOPULL); 137 | gpio_set(SPI0_MISO_PIN, GPIO_ALT0, GPIO_PULLUP); 138 | gpio_set(SPI0_MOSI_PIN, GPIO_ALT0, GPIO_NOPULL); 139 | gpio_set(SPI0_SCLK_PIN, GPIO_ALT0, GPIO_NOPULL); 140 | *SPI0_CS = 0x30; 141 | *SPI0_CLK = CLOCK_KHZ / khz; 142 | } 143 | 144 | // Set / clear SPI chip select 145 | void spi0_cs(int set) 146 | { 147 | *SPI0_CS = set ? *SPI0_CS | 0x80 : *SPI0_CS & ~0x80; 148 | } 149 | 150 | // Transfer 1 SPI byte 151 | void spi0_xfer(uint8_t *txd, uint8_t *rxd, int len) 152 | { 153 | while (len--) 154 | { 155 | *SPI0_FIFO = *txd++; 156 | while((*SPI0_CS & (1<<17)) == 0) ; 157 | *rxd++ = *SPI0_FIFO; 158 | } 159 | } 160 | 161 | // Initialise GPIO and usec I/O blocks 162 | void mmap_init(void) 163 | { 164 | #if USE_MMAP 165 | gpio_block = mmap_regs(GPIO_BASE, GPIO_SIZE); 166 | usec_block = mmap_regs(USEC_BASE, USEC_SIZE); 167 | #endif 168 | } 169 | 170 | // Display memory 171 | void disp_mem(uint8_t *data, int len) 172 | { 173 | int i; 174 | 175 | for (i=0; i> (pin % 32)) & 1); 264 | } 265 | 266 | // Set value on multiple O/P pins (on the same 32-bit port) 267 | void gpio_write(int pin, int npins, uint32_t val) 268 | { 269 | uint32_t *clr=GPIO_REG(GPIO_CLR0)+pin/32, *set=GPIO_REG(GPIO_SET0)+pin/32; 270 | 271 | *set = val << (pin % 32); 272 | *clr = ((~val) & ((1<> (pin % 32)) & ((1 << npins) - 1)); 281 | } 282 | 283 | // Return timer tick value in microseconds 284 | int ustime(void) 285 | { 286 | return(*USEC_REG()); 287 | } 288 | 289 | // Delay given number of microseconds 290 | void usdelay(int usec) 291 | { 292 | int ticks; 293 | 294 | ustimeout(&ticks, 0); 295 | while (!ustimeout(&ticks, usec)) ; 296 | } 297 | 298 | // Return non-zero if timeout 299 | int ustimeout(int *tickp, int usec) 300 | { 301 | int t = *USEC_REG(); 302 | 303 | if (usec == 0 || t - *tickp >= usec) 304 | { 305 | *tickp = t; 306 | return (1); 307 | } 308 | return (0); 309 | } 310 | 311 | // EOF 312 | -------------------------------------------------------------------------------- /srce/zw_gpio.h: -------------------------------------------------------------------------------- 1 | // ZeroWi bare-metal WiFi driver, see https://iosoft.blog/zerowi 2 | // Raspberry Pi GPIO interface definitions 3 | // 4 | // Copyright (c) 2020 Jeremy P Bentham 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | #define USE_MMAP 0 19 | 20 | #define REG_BASE 0x20000000 // Pi Zero 21 | //#define REG_BASE 0x3F000000 // Pi 3 22 | 23 | #define PAGE_SIZE 0x1000 24 | 25 | #define CLOCK_KHZ 250000 26 | 27 | #define GPIO_IN 0 28 | #define GPIO_OUT 1 29 | #define GPIO_ALT0 4 30 | #define GPIO_ALT1 5 31 | #define GPIO_ALT2 6 32 | #define GPIO_ALT3 7 33 | #define GPIO_ALT4 3 34 | #define GPIO_ALT5 2 35 | 36 | #define GPIO_NOPULL 0 37 | #define GPIO_PULLDN 1 38 | #define GPIO_PULLUP 2 39 | 40 | void flash_open_read(int addr); 41 | void flash_read(uint8_t *dp, int len); 42 | void flash_close(void); 43 | 44 | void flash_init(int khz); 45 | void spi0_cs(int set); 46 | void spi0_xfer(uint8_t *txd, uint8_t *rxd, int len); 47 | void mmap_init(void); 48 | void *mmap_regs(uint32_t addr, int len); 49 | void disp_mem(uint8_t *data, int len); 50 | void dump_mem(void *addr, int len); 51 | void gpio_mmap(void); 52 | void gpio_set(int pin, int mode, int pull); 53 | void gpio_mode(int pin, int mode); 54 | void gpio_pull(int pin, int pull); 55 | void gpio_out(int pin, int val); 56 | uint8_t gpio_in(int pin); 57 | uint8_t gpio_read(int pin, int npins); 58 | void gpio_write(int pin, int npins, uint32_t val); 59 | int ustime(void); 60 | void usdelay(int usec); 61 | int ustimeout(int *tickp, int usec); 62 | 63 | // EOF 64 | -------------------------------------------------------------------------------- /srce/zw_ioctl.c: -------------------------------------------------------------------------------- 1 | // ZeroWi bare-metal WiFi driver, see https://iosoft.blog/zerowi 2 | // IOCTL interface 3 | // 4 | // Copyright (c) 2020 Jeremy P Bentham 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "whd_types.h" 24 | #include "whd_wlioctl.h" 25 | #include "whd_events.h" 26 | 27 | #include "zw_sdio.h" 28 | #include "zw_regs.h" 29 | #include "zw_ioctl.h" 30 | #include "zw_gpio.h" 31 | 32 | #define IOCTL_POLL_MSEC 2 33 | 34 | IOCTL_MSG ioctl_txmsg, ioctl_rxmsg; 35 | int txglom; 36 | uint16_t ioctl_reqid=0; 37 | uint8_t event_mask[EVENT_MAX / 8]; 38 | EVT_STR *current_evts; 39 | char ioctl_event_hdr_fields[] = 40 | "2:len 2: 1:seq 1:chan 1: 1:hdrlen 1:flow 1:credit"; 41 | #define MAX_EVENT_STATUS 16 42 | char *event_status[MAX_EVENT_STATUS] = { 43 | "SUCCESS","FAIL","TIMEOUT","NO_NETWORK","ABORT","NO_ACK", 44 | "UNSOLICITED","ATTEMPT","PARTIAL","NEWSCAN","NEWASSOC", 45 | "11HQUIET","SUPPRESS","NOCHANS","CCXFASTRM","CS_ABORT" }; 46 | 47 | // Get event data, return data length excluding header 48 | int ioctl_get_event(IOCTL_EVENT_HDR *hp, uint8_t *data, int maxlen) 49 | { 50 | int n=0, dlen=0, blklen; 51 | 52 | hp->len = 0; 53 | if (sdio_cmd53_read(SD_FUNC_RAD, SB_32BIT_WIN, (void *)hp, sizeof(IOCTL_EVENT_HDR)) && 54 | hp->len>sizeof(IOCTL_EVENT_HDR) && hp->notlen>0 && hp->len==(hp->notlen^0xffff)) 55 | { 56 | dlen = hp->len - sizeof(IOCTL_EVENT_HDR); 57 | while (nlen-n), IOCTL_MAX_BLKLEN); 60 | sdio_cmd53_read(SD_FUNC_RAD, SB_32BIT_WIN, (void *)(&data[n]), blklen); 61 | n += blklen; 62 | } 63 | while (n < dlen) 64 | { 65 | blklen = MIN(hp->len-n, IOCTL_MAX_BLKLEN); 66 | sdio_cmd53_read(SD_FUNC_RAD, SB_32BIT_WIN, 0, blklen); 67 | n += blklen; 68 | } 69 | } 70 | return(dlen > maxlen ? maxlen : dlen); 71 | } 72 | 73 | // Enable events 74 | int ioctl_enable_evts(EVT_STR *evtp) 75 | { 76 | current_evts = evtp; 77 | memset(event_mask, 0, sizeof(event_mask)); 78 | while (evtp->num >= 0) 79 | { 80 | if (evtp->num / 8 < sizeof(event_mask)) 81 | SET_EVENT(event_mask, evtp->num); 82 | evtp++; 83 | } 84 | return(ioctl_set_data("event_msgs", 0, event_mask, sizeof(event_mask))); 85 | } 86 | 87 | // Return string corresponding to event number, without "WLC_E_" prefix 88 | char *ioctl_evt_str(int event) 89 | { 90 | EVT_STR *evtp=current_evts; 91 | 92 | while (evtp && evtp->num>=0 && evtp->num!=event) 93 | evtp++; 94 | return(evtp && evtp->num>=0 && strlen(evtp->str)>6 ? &evtp->str[6] : "?"); 95 | } 96 | 97 | // Return string corresponding to event status 98 | char *ioctl_evt_status_str(int status) 99 | { 100 | return(status>=0 && statusglom_cmd.cmd : &msgp->cmd; 157 | int ret=0, namelen = name ? strlen(name)+1 : 0; 158 | int txdlen = wr ? namelen + dlen : MAX(namelen, dlen); 159 | int hdrlen = cmdp->data - (uint8_t *)&ioctl_txmsg; 160 | int txlen = ((hdrlen + txdlen + 3) / 4) * 4; //, rxlen; 161 | uint32_t val=0; 162 | 163 | // Prepare IOCTL command 164 | memset(msgp, 0, sizeof(ioctl_txmsg)); 165 | memset(rsp, 0, sizeof(ioctl_rxmsg)); 166 | msgp->notlen = ~(msgp->len = hdrlen+txdlen); 167 | if (txglom) 168 | { 169 | msgp->glom_cmd.glom_hdr.len = hdrlen + txdlen - 4; 170 | msgp->glom_cmd.glom_hdr.flags = 1; 171 | } 172 | cmdp->seq = txseq++; 173 | cmdp->hdrlen = txglom ? 20 : 12; 174 | cmdp->cmd = cmd; 175 | cmdp->outlen = txdlen; 176 | cmdp->flags = ((uint32_t)++ioctl_reqid << 16) | (wr ? 2 : 0); 177 | if (namelen) 178 | memcpy(cmdp->data, name, namelen); 179 | if (wr) 180 | memcpy(&cmdp->data[namelen], data, dlen); 181 | // Send IOCTL command 182 | sdio_cmd53_write(SD_FUNC_RAD, SB_32BIT_WIN, (void *)msgp, txlen); 183 | ioctl_wait(IOCTL_WAIT_USEC); 184 | while (wait_msec>=0 && ret==0) 185 | { 186 | // Wait for response to be available 187 | wait_msec -= IOCTL_POLL_MSEC; 188 | sdio_bak_read32(SB_INT_STATUS_REG, &val); 189 | // If response is waiting.. 190 | if (val & 0xff) 191 | { 192 | // ..request response 193 | sdio_bak_write32(SB_INT_STATUS_REG, val); 194 | // Fetch response 195 | ret = sdio_cmd53_read(SD_FUNC_RAD, SB_32BIT_WIN, (void *)rsp, txlen); 196 | // Discard response if not matching request 197 | if ((rsp->cmd.flags>>16) != ioctl_reqid) 198 | ret = 0; 199 | // Exit if error response 200 | if (ret && (rsp->cmd.flags & 1)) 201 | { 202 | ret = 0; 203 | break; 204 | } 205 | // If OK, copy data to buffer 206 | if (ret && !wr && data && dlen) 207 | memcpy(data, rsp->cmd.data, dlen); 208 | } 209 | // If no response, wait 210 | else 211 | usdelay(IOCTL_POLL_MSEC * 1000); 212 | } 213 | return(ret); 214 | } 215 | 216 | // Wait until IOCTL command has been processed 217 | int ioctl_wait(int usec) 218 | { 219 | int tout, ready=0; 220 | 221 | ustimeout(&tout, 0); 222 | while (!ready && !ustimeout(&tout, usec)) 223 | ready = ioctl_ready(); 224 | return(ready); 225 | } 226 | 227 | // Check if IOCTL command has been processed (data bit 1 low) 228 | int ioctl_ready(void) 229 | { 230 | return(!gpio_in(SD_D1_PIN)); 231 | } 232 | 233 | // Display fields in structure 234 | // Fields in descriptor are num:id (little-endian) or num;id (big_endian) 235 | void disp_fields(void *data, char *fields, int maxlen) 236 | { 237 | char *strs=fields, delim=0; 238 | uint8_t *dp = (uint8_t *)data; 239 | int n, dlen; 240 | int val; 241 | 242 | while (*strs && dp-(uint8_t *)data='0' && *strs<='9') 246 | dlen = dlen*10 + *strs++ - '0'; 247 | delim = *strs++; 248 | if (*strs > ' ') 249 | { 250 | while (*strs >= '0') 251 | putchar(*strs++); 252 | putchar('='); 253 | if (dlen <= 4) 254 | { 255 | val = 0; 256 | for (n=0; n 19 | #include 20 | #include 21 | #include 22 | 23 | #include "zw_gpio.h" 24 | #include "zw_sdio.h" 25 | #include "zw_regs.h" 26 | 27 | // Log buffer 28 | SDIO_MSG msglog[LOG_SIZE]; 29 | int log_idx, log_start, logging; 30 | 31 | // CRC tables 32 | uint64_t qcrc16r_poly, qcrc16r_table[1 << SD_DATA_PINS]; 33 | uint8_t crc7_table[256], clkval; 34 | 35 | void gdb_break(void); 36 | 37 | // Read & check a value 38 | int sdio_cmd52_reads_check(int func, int addr, uint32_t mask, uint32_t val, int nbytes) 39 | { 40 | U32DATA data; 41 | 42 | return(sdio_cmd52_reads(func, addr, &data.uint32, nbytes) ? (data.uint32 & mask) == val: 0); 43 | } 44 | 45 | // Send SD command 7 to select chip using RCA, get response 46 | int sdio_cmd7(int rca, SDIO_MSG *rsp) 47 | { 48 | SDIO_MSG cmd={.cmd7 = {.start=0, .cmd=1, .num=7, 49 | .rcax=SWAP16(rca), .x1=0, .crc=0, .stop=1}}; 50 | 51 | return(sdio_cmd_rsp(&cmd, rsp)); 52 | } 53 | 54 | // Write multiple 64-byte command 53 blocks (max 32K in total) 55 | int sdio_write_blocks(int func, int addr, uint8_t *dp, int nblocks) 56 | { 57 | int n=0; 58 | SDIO_MSG rspx, cmd={.cmd53 = {.start=0, .cmd=1, .num=53, 59 | .wr=1, .func=func, .blk=1, .inc=1, .addrh=(uint8_t)(addr>>15)&3, 60 | .addrm=(uint8_t)(addr>>7), .addrl=(uint8_t)(addr&0x7f), 61 | .lenh=(uint8_t)(nblocks>>8)&1, .lenl=(uint8_t)nblocks, .crc=0, .stop=1}}; 62 | 63 | clk_0(1); 64 | add_crc7(cmd.data); 65 | log_msg(&cmd); 66 | sdio_cmd_write(cmd.data, MSG_BITS); 67 | if (sdio_rsp_read(rspx.data, MSG_BITS, SD_CMD_PIN)) 68 | { 69 | log_msg(&rspx); 70 | gpio_write(SD_D0_PIN, 4, 0xf); 71 | gpio_mode(SD_D0_PIN, GPIO_OUT); 72 | gpio_mode(SD_D1_PIN, GPIO_OUT); 73 | gpio_mode(SD_D2_PIN, GPIO_OUT); 74 | gpio_mode(SD_D3_PIN, GPIO_OUT); 75 | while (n++ < nblocks) 76 | { 77 | sdio_block_out(dp, SD_BAK_BLK_BYTES); 78 | log_data(dp, SD_BAK_BLK_BYTES, 1); 79 | sdio_rsp_read(rspx.data, BLOCK_ACK_BITS, SD_D0_PIN); 80 | log_data_ack(rspx.data[0]); 81 | dp += SD_BAK_BLK_BYTES; 82 | clk_0(2); 83 | } 84 | gpio_mode(SD_D0_PIN, GPIO_IN); 85 | gpio_mode(SD_D1_PIN, GPIO_IN); 86 | gpio_mode(SD_D2_PIN, GPIO_IN); 87 | gpio_mode(SD_D3_PIN, GPIO_IN); 88 | } 89 | clk_0(1); 90 | return(n); 91 | } 92 | 93 | // Set backplane window, don't set if already OK 94 | void sdio_bak_window(uint32_t addr) 95 | { 96 | static uint32_t lastaddr=0; 97 | 98 | addr &= SB_WIN_MASK; 99 | if (addr != lastaddr) 100 | sdio_cmd52_writes(SD_FUNC_BAK, BAK_WIN_ADDR_REG, addr>>8, 3); 101 | lastaddr = addr; 102 | } 103 | 104 | // Set backplane window, and return offset within window 105 | uint32_t sdio_bak_addr(uint32_t addr) 106 | { 107 | sdio_bak_window(addr); 108 | return(addr & SB_ADDR_MASK); 109 | } 110 | 111 | // Write a 32-bit value via the backplane window 112 | int sdio_bak_write32(uint32_t addr, uint32_t val) 113 | { 114 | U32DATA u32d={.uint32=val}; 115 | 116 | sdio_bak_window(addr); 117 | return(sdio_cmd53_write(SD_FUNC_BAK, addr | SB_32BIT_WIN, u32d.bytes, 4)); 118 | } 119 | 120 | // Read a 32-bit value via the backplane window 121 | int sdio_bak_read32(uint32_t addr, uint32_t *valp) 122 | { 123 | U32DATA u32d; 124 | int n; 125 | 126 | sdio_bak_window(addr); 127 | n = sdio_cmd53_read(SD_FUNC_BAK, addr | SB_32BIT_WIN, u32d.bytes, 4); 128 | *valp = u32d.uint32; 129 | return(n); 130 | } 131 | 132 | // Do a command 53 block write 133 | int sdio_cmd53_write(int func, int addr, uint8_t *dp, int nbytes) 134 | { 135 | SDIO_MSG rspx, cmd={.cmd53 = {.start=0, .cmd=1, .num=53, 136 | .wr=1, .func=func, .blk=0, .inc=1, .addrh=(uint8_t)(addr>>15)&3, 137 | .addrm=(uint8_t)(addr>>7), .addrl=(uint8_t)(addr&0x7f), 138 | .lenh=(uint8_t)(nbytes>>8)&1, .lenl=(uint8_t)nbytes, .crc=0, .stop=1}}; 139 | int n; 140 | 141 | clk_0(2); 142 | add_crc7(cmd.data); 143 | log_msg(&cmd); 144 | sdio_cmd_write(cmd.data, MSG_BITS); 145 | n = sdio_rsp_block_write(rspx.data, dp, nbytes); 146 | clk_0(16); 147 | log_msg(&rspx); 148 | log_data(dp, n, 1); 149 | return(n); 150 | } 151 | 152 | // Do a command 53 block read 153 | int sdio_cmd53_read(int func, int addr, uint8_t *dp, int nbytes) 154 | { 155 | SDIO_MSG rspx, cmd={.cmd53 = {.start=0, .cmd=1, .num=53, 156 | .wr=0, .func=func, .blk=0, .inc=1, .addrh=(uint8_t)(addr>>15)&3, 157 | .addrm=(uint8_t)(addr>>7), .addrl=(uint8_t)(addr&0x7f), 158 | .lenh=(uint8_t)(nbytes>>8)&1, .lenl=(uint8_t)nbytes, .crc=0, .stop=1}}; 159 | int n; 160 | uint64_t crc; 161 | 162 | clk_0(2); 163 | add_crc7(cmd.data); 164 | log_msg(&cmd); 165 | sdio_cmd_write(cmd.data, MSG_BITS); 166 | n = sdio_rsp_block_read(rspx.data, dp, nbytes, &crc); 167 | clk_0(1); 168 | log_msg(&rspx); 169 | log_data(dp, n, crc==0); 170 | return(n); 171 | } 172 | 173 | // Do 1 - 4 CMD52 writes to successive addresses 174 | int sdio_cmd52_writes(int func, int addr, uint32_t data, int nbytes) 175 | { 176 | int n=0; 177 | 178 | while (nbytes--) 179 | { 180 | n += sdio_cmd52(func, addr++, (uint8_t)data, SD_WR, 0, 0); 181 | data >>= 8; 182 | } 183 | return(n); 184 | } 185 | 186 | // Do 1 - 4 CMD52 reads from successive addresses 187 | int sdio_cmd52_reads(int func, int addr, uint32_t *dp, int nbytes) 188 | { 189 | int i, n=0; 190 | uint32_t val=0; 191 | SDIO_MSG rspx; 192 | 193 | for (i=0; i>15 & 3), 207 | .addrm=(uint8_t)(addr>>7 & 0xff), .addrl=(uint8_t)(addr&0x7f), .x2=0, 208 | .data=data, .crc=0, .stop=1}}; 209 | 210 | return(sdio_cmd_rsp(&cmd, rsp)); 211 | } 212 | 213 | // Send SD command, get response, return 0 if none 214 | int sdio_cmd(int num, uint32_t arg, SDIO_MSG *rsp) 215 | { 216 | SDIO_MSG cmd={.msg = {.start=0, .cmd=1, .num=num, 217 | .argx=SWAP32(arg), .crc=0, .stop=1}}; 218 | 219 | return(sdio_cmd_rsp(&cmd, rsp)); 220 | } 221 | 222 | // Send SD command, return response length in bits 223 | int sdio_cmd_rsp(SDIO_MSG *cmdp, SDIO_MSG *rsp) 224 | { 225 | SDIO_MSG rspx; 226 | int n; 227 | 228 | clk_0(2); 229 | add_crc7(cmdp->data); 230 | rsp = rsp ? rsp : &rspx; 231 | log_msg(cmdp); 232 | sdio_cmd_write(cmdp->data, MSG_BITS); 233 | memset(rsp->data, 0, MSG_BYTES); 234 | n = sdio_rsp_read(rsp->data, MSG_BITS, SD_CMD_PIN); 235 | log_msg(rsp); 236 | return(n); 237 | } 238 | 239 | // Write command to SD interface 240 | void sdio_cmd_write(uint8_t *data, int nbits) 241 | { 242 | uint8_t b, n; 243 | 244 | gpio_mode(SD_CMD_PIN, GPIO_OUT); 245 | for (n=0; n> 4; 326 | gpio_write(SD_D0_PIN, 4, d); 327 | gpio_out(SD_CLK_PIN, 1); 328 | //clk_0(1); 329 | qcrc = qcrc >> SD_DATA_PINS ^ qcrc16r_table[(d ^ (uint8_t)qcrc) & 0xf]; 330 | dbits += 4; 331 | gpio_out(SD_CLK_PIN, 0); 332 | } 333 | for (n=0; n<16; n++) 334 | { 335 | gpio_write(SD_D0_PIN, 4, (uint8_t)qcrc & 0xf); 336 | gpio_out(SD_CLK_PIN, 1); 337 | qcrc >>= 4; 338 | //clk_0(1); 339 | gpio_out(SD_CLK_PIN, 0); 340 | } 341 | gpio_write(SD_D0_PIN, 4, 0xf); 342 | clk_0(1); 343 | } 344 | 345 | // Return response & data block from a command 53 read 346 | int sdio_rsp_block_read(uint8_t *rsp, uint8_t *dp, int nbytes, uint64_t *crcp) 347 | { 348 | int wt=RSP_WAIT, rbits=1, dbits=0, din=0; 349 | uint8_t r=1, d=0xf; 350 | uint64_t qcrc=0; 351 | 352 | *rsp = 0; 353 | if (dp) 354 | *dp = 0; 355 | while (wt-- && r) 356 | { 357 | usdelay(SD_CLK_DELAY); 358 | gpio_out(SD_CLK_PIN, 1); 359 | r = gpio_in(SD_CMD_PIN); 360 | usdelay(SD_CLK_DELAY); 361 | gpio_out(SD_CLK_PIN, 0); 362 | } 363 | if (r == 0) 364 | { 365 | while (rbits> SD_DATA_PINS ^ qcrc16r_table[(d ^ (uint8_t)qcrc) & 0xf]; 384 | dbits += SD_DATA_PINS; 385 | if (dbits/8 >= nbytes + SD_DATA_PINS*2) 386 | din = 0; 387 | else if (dp && dbits/8 < nbytes && dbits%8 == 0) 388 | *++dp = 0; 389 | } 390 | usdelay(SD_CLK_DELAY); 391 | gpio_out(SD_CLK_PIN, 0); 392 | } 393 | } 394 | *crcp = qcrc; 395 | dbits -= SD_DATA_PINS*2*8; 396 | return(dbits>0 ? dbits/8 : 0); 397 | } 398 | 399 | // Toggle clock, leave it at 0 400 | void clk_0(int cycles) 401 | { 402 | while (cycles--) 403 | { 404 | usdelay(SD_CLK_DELAY); 405 | gpio_out(SD_CLK_PIN, clkval=!clkval); 406 | usdelay(SD_CLK_DELAY); 407 | gpio_out(SD_CLK_PIN, clkval=!clkval); 408 | } 409 | if (clkval) 410 | { 411 | usdelay(SD_CLK_DELAY); 412 | gpio_out(SD_CLK_PIN, clkval=!clkval); 413 | } 414 | 415 | } 416 | 417 | // Initialise CRC7 calculator 418 | void crc7_init(void) 419 | { 420 | int i; 421 | 422 | for (i=0; i<256; i++) 423 | crc7_table[i] = crc7_byte(i); 424 | } 425 | 426 | // Add CRC and stop bit to message 427 | void add_crc7(uint8_t *data) 428 | { 429 | data[MSG_BYTES-1] = crc7_data(data, MSG_BYTES-1); 430 | } 431 | 432 | // Calculate 7-bit CRC of byte, return as bits 1-7 433 | uint8_t crc7_byte(uint8_t b) 434 | { 435 | uint16_t n, w=b; 436 | 437 | for (n=0; n<8; n++) 438 | { 439 | w <<= 1; 440 | if (w & 0x100) 441 | w ^= CRC7_POLY; 442 | } 443 | return((uint8_t)w); 444 | } 445 | 446 | // Calculate 7-bit CRC of data bytes, with l.s.bit as stop bit 447 | uint8_t crc7_data(uint8_t *data, int n) 448 | { 449 | uint8_t crc=0; 450 | 451 | while (n--) 452 | crc = crc7_table[crc ^ *data++]; 453 | return(crc | 1); 454 | } 455 | 456 | // Dump data as byte values 457 | void disp_bytes(uint8_t *data, int len) 458 | { 459 | while (len--) 460 | printf("%02x ", *data++); 461 | } 462 | 463 | // Dump message 464 | void dump_msg(uint8_t *data) 465 | { 466 | uint8_t i, crc=crc7_data(data, MSG_BYTES-1); 467 | 468 | for (i=0; idata, MSG_BYTES-1); 502 | 503 | disp_bytes(smf->data, MSG_BYTES); 504 | printf("%s ", smf->data[MSG_BYTES-1] == crc ? "*" : "?"); 505 | printf("%s %2u %08lX", smf->msg.cmd ? "Cmd" : "Rsp", 506 | smf->msg.num, SWAP32(smf->msg.argx)); 507 | if (smf->msg.num==52) 508 | { 509 | if (smf->msg.cmd) 510 | disp_cmd52(smf); 511 | else 512 | disp_rsp52(smf); 513 | } 514 | if (smf->msg.num==53) 515 | { 516 | if (smf->msg.cmd) 517 | disp_cmd53(smf); 518 | else 519 | disp_rsp53(smf); 520 | } 521 | printf("\n"); 522 | } 523 | 524 | // Display command 52 525 | void disp_cmd52(SDIO_MSG *smf) 526 | { 527 | printf(" %s", smf->cmd52.wr ? "Wr" : "Rd"); 528 | printf(" %s", smf->cmd52.func==0 ? "BUS " : smf->cmd52.func==1 ?"BAK " : "WLAN"); 529 | printf(" %05X", REG_ADDR(smf->cmd52)); 530 | if (smf->cmd52.wr) 531 | printf(" %02X", smf->cmd52.data); 532 | } 533 | 534 | // Display response to command 52 535 | void disp_rsp52(SDIO_MSG *smf) 536 | { 537 | printf(" Flags %02X data %02X", smf->rsp52.flags, smf->rsp52.data); 538 | } 539 | 540 | // Display command 53 541 | void disp_cmd53(SDIO_MSG *smf) 542 | { 543 | int n = smf->cmd53.lenl + smf->cmd53.lenh*256; 544 | 545 | printf(" %s", smf->cmd53.wr ? "Wr" : "Rd"); 546 | printf(" %s", smf->cmd53.func==0 ? "BUS " : smf->cmd53.func==1 ?"BAK " : "WLAN"); 547 | printf(" %05X %s %u", REG_ADDR(smf->cmd53), smf->cmd53.blk ? "blks" : "len", n?n:512); 548 | } 549 | 550 | // Display response to command 53 551 | void disp_rsp53(SDIO_MSG *smf) 552 | { 553 | printf(" Flags %02X", smf->rsp52.flags); 554 | } 555 | 556 | // Enable / disable logging 557 | void log_enable(int on) 558 | { 559 | logging = on; 560 | } 561 | 562 | // Increment log to next record, keeping the last LOG_SIZE records 563 | void log_incr(void) 564 | { 565 | log_idx = (log_idx + 1) % LOG_SIZE; 566 | if (log_start == log_idx) 567 | log_start = (log_start + 1) % LOG_SIZE; 568 | } 569 | 570 | // Log a command or response 571 | void log_msg(SDIO_MSG *msgp) 572 | { 573 | if (logging) 574 | { 575 | memcpy(&msglog[log_idx], msgp, MSG_BYTES); 576 | log_incr(); 577 | } 578 | } 579 | 580 | // Log data, retain max 6 bytes 581 | void log_data(uint8_t *data, int len, int ok) 582 | { 583 | int nbytes = len, n = MIN(nbytes, LOG_DATA_LEN); 584 | 585 | if (logging > LOG_CMDS) 586 | { 587 | msglog[log_idx].data[0] = (uint8_t)(nbytes / 256) | 0x80 | (ok?0x40:0); 588 | msglog[log_idx].data[1] = (uint8_t)nbytes; 589 | memcpy(&msglog[log_idx].data[2], data, n); 590 | log_incr(); 591 | } 592 | } 593 | 594 | // Log data write acknowledgement 595 | void log_data_ack(uint8_t val) 596 | { 597 | if (logging > LOG_CMDS) 598 | { 599 | msglog[log_idx].data[0] = LOG_DATA_ACK; 600 | msglog[log_idx].data[1] = val; 601 | log_incr(); 602 | } 603 | } 604 | 605 | // Display the message log, and trigger breakpoint 606 | void disp_log_break(void) 607 | { 608 | disp_log(); 609 | gdb_break(); 610 | } 611 | 612 | // Dump the message log 613 | void disp_log(void) 614 | { 615 | int n; 616 | uint8_t b; 617 | 618 | while (log_start != log_idx) 619 | { 620 | if ((b=msglog[log_start].data[0]) == 0) 621 | printf("00\n"); 622 | else if (b == LOG_DATA_ACK) 623 | printf("Ack %02X\n", msglog[log_start].data[1]); 624 | else if (b & 0x80) 625 | { 626 | n = (b & 0x3f) * 256 + msglog[log_start].data[1]; 627 | printf("Data %2u bytes: ", n); 628 | disp_bytes(&msglog[log_start].data[2], MIN(n, LOG_DATA_LEN)); 629 | printf("%s\n", (b & 0x40) ? "*" : "?"); 630 | } 631 | else 632 | disp_msg(&msglog[log_start]); 633 | 634 | log_start = (log_start + 1) % LOG_SIZE; 635 | } 636 | printf("\n"); 637 | fflush(stdout); 638 | } 639 | 640 | // Initialise 32 kHz oscillator 641 | void osc_init(void) 642 | { 643 | *GP2DIV = GP2DIV_VAL; 644 | *GP2CTL = GP2CTL_VAL; 645 | gpio_set(SD_32KHZ_PIN, GPIO_ALT0, GPIO_NOPULL); 646 | } 647 | 648 | // EOF 649 | 650 | -------------------------------------------------------------------------------- /srce/zw_sdio.h: -------------------------------------------------------------------------------- 1 | // ZeroWi bare-metal WiFi driver, see https://iosoft.blog/zerowi 2 | // Raspberry Pi SDIO interface definitions 3 | // 4 | // Copyright (c) 2020 Jeremy P Bentham 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | #define LOG_CMDS 1 19 | #define LOG_ALL 2 20 | 21 | // I/O pin numbers 22 | #define LED_PIN 47 23 | #define SD_CLK_PIN 34 24 | #define SD_CMD_PIN 35 25 | #define WLAN_ON_PIN 41 26 | #define SD_32KHZ_PIN 43 27 | 28 | #define SD_D0_PIN 36 29 | #define SD_D1_PIN 37 30 | #define SD_D2_PIN 38 31 | #define SD_D3_PIN 39 32 | #define SD_DATA_PINS 4 33 | 34 | // 32.768 kHz oscillator 35 | #define GP2CTL ((uint32_t *)0x20101080) 36 | #define GP2DIV (GP2CTL + 0x4/4) 37 | #define GP2CTL_VAL (0x5a000000 + 0x291) 38 | #define GP2DIV_VAL (0x5a000000 + 0x00249F00) 39 | 40 | // CRC polynomials 41 | #define CRC7_POLY (uint8_t)(0b10001001 << 1) 42 | #define CRC16R_POLY (1<<(15-0) | 1<<(15-5) | 1<<(15-12)) 43 | 44 | // Bit counts 45 | #define BLOCK_ACK_BITS 8 46 | #define MSG_BITS 48 47 | #define BYTE_BITS 8 48 | #define MSG_BYTES (MSG_BITS / BYTE_BITS) 49 | 50 | // Read/write block sizes 51 | #define SD_BAK_BLK_BYTES 64 52 | #define SD_RAD_BLK_BYTES 512 53 | 54 | // SD function numbers 55 | #define SD_FUNC_BUS 0 56 | #define SD_FUNC_BAK 1 57 | #define SD_FUNC_RAD 2 58 | 59 | // Read/write flags 60 | #define SD_RD 0 61 | #define SD_WR 1 62 | 63 | // Delays 64 | #define SD_CLK_DELAY 1 // Clock on/off time in usec 65 | #define RSP_WAIT 20 // Number of clock cycles to wait for resp 66 | 67 | // Macros to reorder items in structure 68 | #define BITF1(typ, a) typ a 69 | #define BITF2(typ, a, b) typ b, a 70 | #define BITF3(typ, a, b, c) typ c, b, a 71 | #define BITF4(typ, a, b, c, d) typ d, c, b, a 72 | #define BITF5(typ, a, b, c, d, e) typ e, d, c, b, a 73 | 74 | // Structures for SDIO communication 75 | #pragma pack(1) 76 | typedef struct 77 | { 78 | BITF3(uint8_t, start:1, cmd:1, num:6); 79 | BITF1(uint32_t, argx); 80 | BITF2(uint8_t, crc:7, stop:1); 81 | } SDIO_MSG_STRUCT; 82 | 83 | typedef struct 84 | { 85 | BITF3(uint8_t, start:1, cmd:1, num:6); 86 | BITF1(uint16_t, rcax); 87 | BITF1(uint16_t, statusx); 88 | BITF2(uint8_t, crc:7, stop:1); 89 | } SDIO_RSP3_STRUCT; 90 | 91 | typedef struct 92 | { 93 | BITF3(uint8_t, start:1, cmd:1, x1:6); 94 | BITF5(uint8_t, rdy:1, nio:3, mem:1, x2:2, s18a:1); 95 | BITF1(uint8_t, ocrl); 96 | BITF1(uint8_t, ocrm); 97 | BITF1(uint8_t, ocrh); 98 | BITF2(uint8_t, x3:7, stop:1); 99 | } SDIO_RSP5_STRUCT; 100 | 101 | typedef struct 102 | { 103 | BITF3(uint8_t, start:1, cmd:1, num:6); 104 | BITF1(uint16_t, rcax); 105 | BITF1(uint16_t, x1); 106 | BITF2(uint8_t, crc:7, stop:1); 107 | } SDIO_CMD7_STRUCT; 108 | 109 | typedef struct 110 | { 111 | BITF3(uint8_t, start:1, cmd:1, num:6); 112 | BITF5(uint8_t, wr:1, func:3, raw:1, x1:1, addrh:2); 113 | BITF1(uint8_t, addrm); 114 | BITF2(uint8_t, addrl:7, x2:1); 115 | BITF1(uint8_t, data); 116 | BITF2(uint8_t, crc:7, stop:1); 117 | } SDIO_CMD52_STRUCT; 118 | 119 | typedef struct 120 | { 121 | BITF3(uint8_t, start:1, cmd:1, num:6); 122 | BITF1(uint16_t, x1); 123 | BITF1(uint8_t, flags); 124 | BITF1(uint8_t, data); 125 | BITF2(uint8_t, crc:7, stop:1); 126 | } SDIO_RSP52_STRUCT; 127 | 128 | typedef struct 129 | { 130 | BITF3(uint8_t, start:1, cmd:1, num:6); 131 | BITF5(uint8_t, wr:1, func:3, blk:1, inc:1, addrh:2); 132 | BITF1(uint8_t, addrm); 133 | BITF2(uint8_t, addrl:7, lenh:1); 134 | BITF1(uint8_t, lenl); 135 | BITF2(uint8_t, crc:7, stop:1); 136 | } SDIO_CMD53_STRUCT; 137 | 138 | typedef union 139 | { 140 | SDIO_MSG_STRUCT msg; 141 | SDIO_RSP3_STRUCT rsp3; 142 | SDIO_CMD7_STRUCT cmd7; 143 | SDIO_CMD52_STRUCT cmd52; 144 | SDIO_RSP52_STRUCT rsp52; 145 | SDIO_CMD53_STRUCT cmd53; 146 | uint8_t data[MSG_BYTES+2]; 147 | } SDIO_MSG; 148 | 149 | // Union to handle 8/16/32 bit conversions 150 | typedef union 151 | { 152 | int32_t int32; 153 | uint32_t uint32; 154 | uint32_t uint24:24; 155 | uint16_t uint16; 156 | uint8_t uint8; 157 | uint8_t bytes[4]; 158 | } U32DATA; 159 | 160 | // Tags for logged messages 161 | #define LOG_ERROR 0xff 162 | #define LOG_DATA_ACK 0xfe 163 | #define LOG_SIZE 50 164 | #define LOG_DATA_LEN 6 165 | 166 | // Miscellaneous macros 167 | #define BYTES(d) (uint8_t *)(d) 168 | #define REG_ADDR(m) (m.addrl | m.addrm<<7 | m.addrh<<15) 169 | #define SWAP16(x) ((x&0xff)<<8 | (x&0xff00)>>8) 170 | #define SWAP32(x) ((x&0xff)<<24 | (x&0xff00)<<8 | (x&0xff0000)>>8 | (x&0xff000000)>>24) 171 | #define MIN(a,b) (((a)<(b))?(a):(b)) 172 | #define MAX(a,b) (((a)>(b))?(a):(b)) 173 | 174 | void sdio_bak_window(uint32_t addr); 175 | uint32_t sdio_bak_addr(uint32_t addr); 176 | int sdio_cmd7(int rca, SDIO_MSG *rsp); 177 | int sdio_write_blocks(int func, int addr, uint8_t *dp, int nblocks); 178 | int sdio_bak_write32(uint32_t addr, uint32_t val); 179 | int sdio_bak_read32(uint32_t addr, uint32_t *valp); 180 | int sdio_cmd53_write(int func, int addr, uint8_t *dp, int nbytes); 181 | int sdio_cmd53_read(int func, int addr, uint8_t *dp, int nbytes); 182 | int sdio_cmd52_reads_check(int func, int addr, uint32_t mask, uint32_t val, int nbytes); 183 | int sdio_cmd52_writes(int func, int addr, uint32_t data, int nbytes); 184 | int sdio_cmd52_reads(int func, int addr, uint32_t *dp, int nbytes); 185 | int sdio_cmd52(int func, int addr, uint8_t data, int wr, int raw, SDIO_MSG *rsp); 186 | int sdio_cmd(int num, uint32_t arg, SDIO_MSG *rsp); 187 | int sdio_cmd_rsp(SDIO_MSG *cmdp, SDIO_MSG *rsp); 188 | void sdio_cmd_write(uint8_t *data, int nbits); 189 | int sdio_rsp_block_write(uint8_t *rsp, uint8_t *dp, int nbytes); 190 | void sdio_block_out(uint8_t *dp, int nbytes); 191 | int sdio_rsp_block_read(uint8_t *rspd, uint8_t *data, int nbytes, uint64_t *crcp); 192 | int sdio_rsp_read(uint8_t *rsp, int nbits, int pin); 193 | void clk_0(int cycles); 194 | void crc7_init(void); 195 | void add_crc7(uint8_t *data); 196 | uint8_t crc7_byte(uint8_t b); 197 | uint8_t crc7_data(uint8_t *data, int n); 198 | void usdelay(int usec); 199 | int ustimeout(int *tickp, int usec); 200 | void qcrc16r_init(void); 201 | uint64_t quadval(uint16_t val); 202 | void disp_msg(SDIO_MSG *smf); 203 | void disp_cmd52(SDIO_MSG *smf); 204 | void disp_rsp52(SDIO_MSG *smf); 205 | void disp_cmd53(SDIO_MSG *smf); 206 | void disp_rsp53(SDIO_MSG *smf); 207 | void log_enable(int on); 208 | void log_incr(void); 209 | void log_msg(SDIO_MSG *msgp); 210 | void log_data(uint8_t *data, int len, int ok); 211 | void log_data_ack(uint8_t val); 212 | void log_error(uint8_t *data, int len); 213 | void disp_log_break(void); 214 | void disp_log(void); 215 | void dump_msg(uint8_t *data); 216 | void osc_init(void); 217 | 218 | // EOF 219 | 220 | -------------------------------------------------------------------------------- /whd/cy_result.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * \file cy_result.h 3 | * 4 | * \brief 5 | * Basic function result handling. Defines a simple type for conveying 6 | * information about whether something succeeded or details about any issues 7 | * that were detected. 8 | * 9 | ******************************************************************************** 10 | * \copyright 11 | * Copyright 2018-2019 Cypress Semiconductor Corporation 12 | * SPDX-License-Identifier: Apache-2.0 13 | * 14 | * Licensed under the Apache License, Version 2.0 (the "License"); 15 | * you may not use this file except in compliance with the License. 16 | * You may obtain a copy of the License at 17 | * 18 | * http://www.apache.org/licenses/LICENSE-2.0 19 | * 20 | * Unless required by applicable law or agreed to in writing, software 21 | * distributed under the License is distributed on an "AS IS" BASIS, 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | * See the License for the specific language governing permissions and 24 | * limitations under the License. 25 | *******************************************************************************/ 26 | 27 | /** 28 | * \addtogroup group_result Result Type 29 | * \ingroup group_abstraction 30 | * \{ 31 | * Basic function result handling. Defines a simple type for conveying 32 | * information about whether something succeeded or details about any issues 33 | * that were detected. 34 | * 35 | * \defgroup group_result_macros Macros 36 | */ 37 | 38 | #pragma once 39 | 40 | #include 41 | 42 | #if defined(__cplusplus) 43 | extern "C" { 44 | #endif 45 | 46 | /** 47 | * \addtogroup group_result_macros 48 | * \{ 49 | */ 50 | 51 | /** Mask for the bit at position "x" */ 52 | #define CY_BIT_MASK(x) ( (1U << (x) ) - 1U ) 53 | 54 | /** Bit position of the result code */ 55 | #define CY_RSLT_CODE_POSITION (0U) 56 | /** Bit width of the result code */ 57 | #define CY_RSLT_CODE_WIDTH (16U) 58 | /** Bit position of the result type */ 59 | #define CY_RSLT_TYPE_POSITION (16U) 60 | /** Bit width of the result type */ 61 | #define CY_RSLT_TYPE_WIDTH (2U) 62 | /** Bit position of the module identifier */ 63 | #define CY_RSLT_MODULE_POSITION (18U) 64 | /** Bit width of the module identifier */ 65 | #define CY_RSLT_MODULE_WIDTH (14U) 66 | 67 | /** Mask for the result code */ 68 | #define CY_RSLT_CODE_MASK CY_BIT_MASK(CY_RSLT_CODE_WIDTH) 69 | /** Mask for the module identifier */ 70 | #define CY_RSLT_MODULE_MASK CY_BIT_MASK(CY_RSLT_MODULE_WIDTH) 71 | /** Mask for the result type */ 72 | #define CY_RSLT_TYPE_MASK CY_BIT_MASK(CY_RSLT_TYPE_WIDTH) 73 | 74 | /** Informational-only result status */ 75 | #define CY_RSLT_TYPE_INFO (0U) 76 | /** Warning result */ 77 | #define CY_RSLT_TYPE_WARNING (1U) 78 | /** Error result */ 79 | #define CY_RSLT_TYPE_ERROR (2U) 80 | /** Fatal error result */ 81 | #define CY_RSLT_TYPE_FATAL (3U) 82 | 83 | /** Get the value of the result code field */ 84 | #define CY_RSLT_GET_CODE(x) ( ( (x) >> CY_RSLT_CODE_POSITION ) & CY_RSLT_CODE_MASK ) 85 | /** Get the value of the result type field */ 86 | #define CY_RSLT_GET_TYPE(x) ( ( (x) >> CY_RSLT_TYPE_POSITION ) & CY_RSLT_TYPE_MASK ) 87 | /** Get the value of the module identifier field */ 88 | #define CY_RSLT_GET_MODULE(x) ( ( (x) >> CY_RSLT_MODULE_POSITION ) & CY_RSLT_MODULE_MASK ) 89 | 90 | 91 | /**** DRIVER Module codes: 0x0000 - 0x00FF ****/ 92 | /** Base identifier for peripheral driver library */ 93 | #define CY_RSLT_MODULE_DRIVERS_PDL_BASE (0x0000U) 94 | /** Base identifier for peripheral driver library */ 95 | #define CY_RSLT_MODULE_DRIVERS_WHD_BASE (0x0080U) 96 | 97 | /**** ABSTRACTION Module codes: 0x0100 - 0x01FF ****/ 98 | /** Base identifier for chip support modules */ 99 | #define CY_RSLT_MODULE_ABSTRACTION_HAL_BASE (0x0100U) 100 | /** Base identifier for board support modules */ 101 | #define CY_RSLT_MODULE_ABSTRACTION_BSP (0x0180U) 102 | /** Base identifier for file system modules */ 103 | #define CY_RSLT_MODULE_ABSTRACTION_FS (0x0181U) 104 | /** Base identifier for resource abstraction modules */ 105 | #define CY_RSLT_MODULE_ABSTRACTION_RESOURCE (0x0182U) 106 | /** Base identifier for rtos abstraction modules */ 107 | #define CY_RSLT_MODULE_ABSTRACTION_OS (0x0183U) 108 | /** Base identifier for environment abstraction modules */ 109 | #define CY_RSLT_MODULE_ABSTRACTION_ENV (0x0184U) 110 | 111 | /**** Middleware Module codes: 0x0200 - 0x02FF ****/ 112 | #define CY_RSLT_MODULE_MIDDLEWARE_BASE (0x0200U) 113 | 114 | 115 | 116 | /** Provides the result of an operation as a structured bitfield */ 117 | typedef uint32_t cy_rslt_t; 118 | 119 | /** Result value indicating success */ 120 | #define CY_RSLT_SUCCESS ( (cy_rslt_t)0x00000000U ) 121 | 122 | /** Create a result value from the specified type, module, and result code */ 123 | #define CY_RSLT_CREATE(type, module, code) \ 124 | ( ( ( (module) & CY_RSLT_MODULE_MASK ) << CY_RSLT_MODULE_POSITION ) | \ 125 | ( ( (code) & CY_RSLT_CODE_MASK ) << CY_RSLT_CODE_POSITION ) | \ 126 | ( ( (type) & CY_RSLT_TYPE_MASK ) << CY_RSLT_TYPE_POSITION ) ) 127 | 128 | /** \} group_result_macros */ 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | /** \} group_result */ 135 | 136 | -------------------------------------------------------------------------------- /whd/cyhal_hw_types.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * \file cyhal_hw_types_template.h 3 | * 4 | * \brief 5 | * Provides a template for configuration resources used by the HAL. Items 6 | * here need to be implemented for each HAL port. It is up to the environment 7 | * being ported into what the actual types are. There are some suggestions below 8 | * but these are not required. All that is required is that the type is defined; 9 | * it does not matter to the HAL what type is actually chosen for the 10 | * implementation 11 | * All TODOs and references to 'PORT' need to be replaced by with meaningful 12 | * values for the device being supported. 13 | * 14 | ******************************************************************************** 15 | * \copyright 16 | * Copyright 2018-2019 Cypress Semiconductor Corporation 17 | * SPDX-License-Identifier: Apache-2.0 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | *******************************************************************************/ 31 | 32 | /** 33 | * \addtogroup group_hal_hw_types PORT Hardware Types 34 | * \ingroup group_hal_PORT 35 | * \{ 36 | * Struct definitions for configuration resources in the PORT. 37 | * 38 | * \defgroup group_hal_hw_types_data_structures Data Structures 39 | */ 40 | 41 | #pragma once 42 | 43 | /* 44 | #include "TODO: Port specific header file" 45 | */ 46 | 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | /** 52 | * \addtogroup group_hal_hw_types_data_structures 53 | * \{ 54 | */ 55 | 56 | /** GPIO object */ 57 | typedef uint32_t /* TODO: port specific type */ cyhal_gpio_t; 58 | 59 | /** Clock divider object */ 60 | typedef struct 61 | { 62 | /* TODO: replace with port specific items */ 63 | void *div_type; 64 | } cyhal_clock_divider_t; 65 | 66 | /** SDIO object */ 67 | typedef struct 68 | { 69 | /* TODO: replace with port specific items */ 70 | void *empty; 71 | } cyhal_sdio_t; 72 | 73 | /** SPI object */ 74 | typedef struct 75 | { 76 | /* TODO: replace with port specific items */ 77 | void *empty; 78 | } cyhal_spi_t; 79 | 80 | /** \} group_hal_hw_types_data_structures */ 81 | 82 | #if defined(__cplusplus) 83 | } 84 | #endif /* __cplusplus */ 85 | 86 | /** \} group_hal_hw_types */ 87 | 88 | -------------------------------------------------------------------------------- /whd/whd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Cypress Semiconductor Corporation 3 | * SPDX-License-Identifier: Apache-2.0 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 | /** @file whd.h 19 | * Provides abstract pointer type to act as instance for: driver, interface, buffer funcs, network funcs, resource funcs and bus funcs. 20 | */ 21 | 22 | #include "whd_types.h" 23 | 24 | #ifndef INCLUDED_WHD_H 25 | #define INCLUDED_WHD_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | /** 33 | * Abstract pointer type that acts as a handle to an instance of the driver 34 | */ 35 | typedef struct whd_driver *whd_driver_t; 36 | 37 | /** 38 | * Abstract pointer type to handle instance of whd interface 39 | */ 40 | typedef struct whd_interface *whd_interface_t; 41 | 42 | /** 43 | * Abstract type that acts as a handle to an instance of a buffer function 44 | */ 45 | typedef struct whd_buffer_funcs whd_buffer_funcs_t; 46 | 47 | /** 48 | * Abstract type that acts as a handle to an instance of a network interface function 49 | */ 50 | typedef struct whd_netif_funcs whd_netif_funcs_t; 51 | 52 | /** 53 | * Abstract type that acts as a handle to an instance of a resource function 54 | */ 55 | typedef struct whd_resource_source whd_resource_source_t; 56 | 57 | /** 58 | * Abstract type that acts as a handle to an instance of a bus function used for SDIO specific functionality 59 | */ 60 | typedef struct whd_bus_funcs whd_sdio_funcs_t; 61 | 62 | /** 63 | * Abstract type that acts as a handle to an instance of a bus function used for SPI specific functionality 64 | */ 65 | typedef struct whd_bus_funcs whd_spi_funcs_t; 66 | 67 | /** 68 | * Structure for storing WHD init configurations 69 | */ 70 | typedef struct whd_init_config 71 | { 72 | void *thread_stack_start; /**< Pointer to the WHD thread stack */ 73 | uint32_t thread_stack_size; /**< Size of the WHD thread stack */ 74 | uint32_t thread_priority; /**< Priority to be set to WHD Thread */ 75 | whd_country_code_t country; /**< Variable to strore country code information */ 76 | } whd_init_config_t; 77 | 78 | #ifdef __cplusplus 79 | } /* extern "C" */ 80 | #endif 81 | #endif /* INCLUDED_WHD_H */ 82 | 83 | -------------------------------------------------------------------------------- /whd/whd_events.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Cypress Semiconductor Corporation 3 | * SPDX-License-Identifier: Apache-2.0 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 | /** @file whd_events.h 19 | * Header for Event detection 20 | * 21 | * Provides constants and prototypes for functions that allow 22 | * user applications to receive event callbacks and set event handlers 23 | */ 24 | #ifndef INCLUDED_WHD_EVENTS_API_H 25 | #define INCLUDED_WHD_EVENTS_API_H 26 | 27 | #include "whd.h" 28 | 29 | #ifdef __cplusplus 30 | extern "C" 31 | { 32 | #endif 33 | 34 | /* List of events */ 35 | #define WLC_E_NONE (0x7FFFFFFE) /**< Indicates the end of the event array list */ 36 | 37 | #define WLC_E_SET_SSID 0 /**< Indicates status of set SSID. This event occurs when STA tries to join the AP*/ 38 | #define WLC_E_AUTH 3 /**< 802.11 AUTH request event occurs when STA tries to get authenticated with the AP */ 39 | #define WLC_E_DEAUTH 5 /**< 802.11 DEAUTH request event occurs when the the SOFTAP is stopped to deuthenticate the connected stations*/ 40 | #define WLC_E_DEAUTH_IND 6 /**< 802.11 DEAUTH indication event occurs when the STA gets deauthenticated by the AP */ 41 | #define WLC_E_ASSOC 7 /**< 802.11 ASSOC request event occurs when STA joins the AP */ 42 | #define WLC_E_ASSOC_IND 8 /**< 802.11 ASSOC indication occurs when a station joins the SOFTAP that is started */ 43 | #define WLC_E_REASSOC 9 /**< 802.11 REASSOC request event when the STA again gets associated with the AP */ 44 | #define WLC_E_REASSOC_IND 10 /**< 802.11 REASSOC indication occurs when a station again reassociates with the SOFTAP*/ 45 | #define WLC_E_DISASSOC 11 /**< 802.11 DISASSOC request occurs when the STA the tries to leave the AP*/ 46 | #define WLC_E_DISASSOC_IND 12 /**< 802.11 DISASSOC indication occurs when the connected station gets disassociates from SOFTAP, 47 | also when STA gets diassociated by the AP*/ 48 | #define WLC_E_LINK 16 /**< generic link indication */ 49 | #define WLC_E_PROBREQ_MSG 44 /**< Indicates probe request received for the SOFTAP started*/ 50 | #define WLC_E_PSK_SUP 46 /**< WPA Handshake fail during association*/ 51 | #define WLC_E_ACTION_FRAME 59 /**< Indicates Action frame Rx */ 52 | #define WLC_E_ACTION_FRAME_COMPLETE 60 /**< Indicates Action frame Tx complete */ 53 | #define WLC_E_ESCAN_RESULT 69 /**< escan result event occurs when we scan for the networks */ 54 | 55 | /* List of status codes - Applicable for any event type */ 56 | #define WLC_E_STATUS_SUCCESS 0 /**< operation was successful */ 57 | #define WLC_E_STATUS_FAIL 1 /**< operation failed */ 58 | #define WLC_E_STATUS_TIMEOUT 2 /**< operation timed out */ 59 | #define WLC_E_STATUS_NO_NETWORKS 3 /**< failed due to no matching network found */ 60 | #define WLC_E_STATUS_ABORT 4 /**< operation was aborted */ 61 | #define WLC_E_STATUS_NO_ACK 5 /**< protocol failure: packet not ack'd */ 62 | #define WLC_E_STATUS_UNSOLICITED 6 /**< AUTH or ASSOC packet was unsolicited */ 63 | #define WLC_E_STATUS_ATTEMPT 7 /**< attempt to assoc to an auto auth configuration */ 64 | #define WLC_E_STATUS_PARTIAL 8 /**< scan results are incomplete */ 65 | #define WLC_E_STATUS_NEWSCAN 9 /**< scan aborted by another scan */ 66 | #define WLC_E_STATUS_NEWASSOC 10 /**< scan aborted due to assoc in progress */ 67 | #define WLC_E_STATUS_11HQUIET 11 /**< 802.11h quiet period started */ 68 | #define WLC_E_STATUS_SUPPRESS 12 /**< user disabled scanning (WLC_SET_SCANSUPPRESS) */ 69 | #define WLC_E_STATUS_NOCHANS 13 /**< no allowable channels to scan */ 70 | #define WLC_E_STATUS_CCXFASTRM 14 /**< scan aborted due to CCX fast roam */ 71 | #define WLC_E_STATUS_CS_ABORT 15 /**< abort channel select */ 72 | #define WLC_E_STATUS_ERROR 16 /**< request failed due to error */ 73 | #define WLC_E_STATUS_INVALID 0xff /**< Invalid status code to init variables. */ 74 | 75 | #define WLC_SUP_STATUS_OFFSET (256) /**< Status offset added to the status codes to match the values from firmware. */ 76 | 77 | /** 78 | * @brief Status code for event WLC_E_PSK_SUP 79 | * 80 | * -Basic supplicant authentication states 81 | * 82 | + WLC_SUP_DISCONNECTED 83 | * + WLC_SUP_CONNECTING 84 | * + WLC_SUP_IDREQUIRED 85 | * + WLC_SUP_AUTHENTICATING 86 | * + WLC_SUP_AUTHENTICATED 87 | * + WLC_SUP_KEYXCHANGE 88 | * + WLC_SUP_KEYED 89 | * + WLC_SUP_TIMEOUT 90 | * + WLC_SUP_LAST_BASIC_STATE 91 | * -Extended supplicant authentication states 92 | * + WLC_SUP_KEYXCHANGE_WAIT_M1 93 | * + WLC_SUP_KEYXCHANGE_PREP_M2 94 | * + WLC_SUP_KEYXCHANGE_WAIT_M3 95 | * + WLC_SUP_KEYXCHANGE_PREP_M4 96 | * + WLC_SUP_KEYXCHANGE_WAIT_G1 97 | * + WLC_SUP_KEYXCHANGE_PREP_G2 98 | */ 99 | typedef enum sup_auth_status 100 | { 101 | WLC_SUP_DISCONNECTED = 0 + WLC_SUP_STATUS_OFFSET, /**< Disconnected */ 102 | WLC_SUP_CONNECTING = 1 + WLC_SUP_STATUS_OFFSET, /**< Connecting */ 103 | WLC_SUP_IDREQUIRED = 2 + WLC_SUP_STATUS_OFFSET, /**< ID Required */ 104 | WLC_SUP_AUTHENTICATING = 3 + WLC_SUP_STATUS_OFFSET, /**< Authenticating */ 105 | WLC_SUP_AUTHENTICATED = 4 + WLC_SUP_STATUS_OFFSET, /**< Authenticated */ 106 | WLC_SUP_KEYXCHANGE = 5 + WLC_SUP_STATUS_OFFSET, /**< Key Exchange */ 107 | WLC_SUP_KEYED = 6 + WLC_SUP_STATUS_OFFSET, /**< Key Exchanged */ 108 | WLC_SUP_TIMEOUT = 7 + WLC_SUP_STATUS_OFFSET, /**< Timeout */ 109 | WLC_SUP_LAST_BASIC_STATE = 8 + WLC_SUP_STATUS_OFFSET, /**< Last Basic State */ 110 | WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, /**< Waiting to receive handshake msg M1 */ 111 | WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, /**< Preparing to send handshake msg M2 */ 112 | WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, /**< Waiting to receive handshake msg M3 */ 113 | WLC_SUP_KEYXCHANGE_PREP_M4 = 9 + WLC_SUP_STATUS_OFFSET, /**< Preparing to send handshake msg M4 */ 114 | WLC_SUP_KEYXCHANGE_WAIT_G1 = 10 + WLC_SUP_STATUS_OFFSET, /**< Waiting to receive handshake msg G1 */ 115 | WLC_SUP_KEYXCHANGE_PREP_G2 = 11 + WLC_SUP_STATUS_OFFSET /**< Preparing to send handshake msg G2 */ 116 | } sup_auth_status_t; 117 | 118 | #define WHD_MSG_IFNAME_MAX 16 /**< Max length of Interface name */ 119 | 120 | #pragma pack(1) 121 | 122 | /** 123 | * Structure to store ethernet header fields in event packets 124 | */ 125 | typedef struct whd_event_eth_hdr 126 | { 127 | uint16_t subtype; /**< Vendor specific..32769 */ 128 | uint16_t length; /**< Length of ethernet header*/ 129 | uint8_t version; /**< Version is 0 */ 130 | uint8_t oui[3]; /**< Organizationally Unique Identifier */ 131 | uint16_t usr_subtype; /**< User specific data */ 132 | } whd_event_eth_hdr_t; 133 | 134 | /** 135 | * Structure to store ethernet destination, source and ethertype in event packets 136 | */ 137 | typedef struct whd_event_ether_header 138 | { 139 | whd_mac_t destination_address; /**< Ethernet destination address */ 140 | whd_mac_t source_address; /**< Ethernet source address */ 141 | uint16_t ethertype; /**< Ethertype for identifying event packets */ 142 | } whd_event_ether_header_t; 143 | 144 | /** 145 | * Structure to store fields after ethernet header in event message 146 | */ 147 | struct whd_event_msg 148 | { 149 | uint16_t version; /**< Version */ 150 | uint16_t flags; /**< see flags below */ 151 | uint32_t event_type; /**< Event type indicating a response from firmware for IOCTLs/IOVARs sent */ 152 | uint32_t status; /**< Status code corresponding to any event type */ 153 | uint32_t reason; /**< Reason code associated with the event occurred */ 154 | uint32_t auth_type; /**< WLC_E_AUTH: 802.11 AUTH request */ 155 | uint32_t datalen; /**< Length of data in event message */ 156 | whd_mac_t addr; /**< Station address (if applicable) */ 157 | char ifname[WHD_MSG_IFNAME_MAX]; /**< name of the incoming packet interface */ 158 | uint8_t ifidx; /**< destination OS i/f index */ 159 | uint8_t bsscfgidx; /**< source bsscfg index */ 160 | }; 161 | 162 | /** 163 | * Event structure used by driver msgs 164 | */ 165 | typedef struct whd_event 166 | { 167 | whd_event_ether_header_t eth; /**< Variable to store ethernet destination, source and ethertype in event packets */ 168 | whd_event_eth_hdr_t eth_evt_hdr; /**< Variable to store ethernet header fields in event message */ 169 | whd_event_header_t whd_event; /**< Variable to store rest of the event packet fields after ethernet header */ 170 | /* data portion follows */ 171 | } whd_event_t; 172 | 173 | #pragma pack() 174 | 175 | /** @addtogroup event WHD Event handling API 176 | * Functions that allow user applications to receive event callbacks and set event handlers 177 | * @{ 178 | */ 179 | /** Event handler prototype definition 180 | * 181 | * @param ifp Pointer to handle instance of whd interface 182 | * @param event_header whd event header 183 | * @param event_data event data 184 | * @param handler_user_data semaphore data 185 | */ 186 | typedef void *(*whd_event_handler_t)(whd_interface_t ifp, const whd_event_header_t *event_header, 187 | const uint8_t *event_data, void *handler_user_data); 188 | 189 | /** Registers a handler to receive event callbacks. 190 | * 191 | * This function registers a callback handler to be notified when 192 | * a particular event is received. 193 | * 194 | * 195 | * @note Currently each event may only be registered to one handler and there is a limit to the number of simultaneously 196 | * registered events. Maximum of 5 event handlers can registered simultaneously, this also includes the internal 197 | * event handler registration which happens during scan, join and starting an AP. 198 | * 199 | * @param ifp Pointer to handle instance of whd interface 200 | * @param event_type Pointer to the event list array 201 | * @param handler_func A function pointer to the handler callback 202 | * @param handler_user_data A pointer value which will be passed to the event handler function 203 | * at the time an event is triggered (NULL is allowed) 204 | * @param event_index Entry where the event handler is registered in the list 205 | * 206 | * @return WHD_SUCCESS or Error code 207 | */ 208 | uint32_t whd_wifi_set_event_handler(whd_interface_t ifp, const uint32_t *event_type, whd_event_handler_t handler_func, 209 | void *handler_user_data, uint16_t *event_index); 210 | /* @} */ 211 | 212 | /** Delete/Deregister the event entry where callback is registered 213 | * 214 | * @param ifp Pointer to handle instance of whd interface 215 | * @param event_index Event index obtained during registration by whd_wifi_set_event_handler 216 | * 217 | * @return WHD_SUCCESS or Error code 218 | */ 219 | 220 | uint32_t whd_wifi_deregister_event_handler(whd_interface_t ifp, uint16_t event_index); 221 | 222 | #ifdef __cplusplus 223 | } /* extern "C" */ 224 | #endif 225 | #endif /* ifndef */ 226 | 227 | -------------------------------------------------------------------------------- /zerowi.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbentham/zerowi/57283645e89916bb62416941d815a7bc16586720/zerowi.elf --------------------------------------------------------------------------------