├── 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
--------------------------------------------------------------------------------