├── LICENSE ├── Makefile ├── README.md ├── cdc.c ├── cdc_app.c ├── ffff.c ├── include ├── interface.h └── task.h ├── kernel ├── app_hdr.c ├── app_integrated.c ├── dummy.c ├── fixcrc.c ├── map.pl ├── syms.c └── task.c ├── manufacturing.c ├── merge.sh ├── onerng.inf ├── random_data ├── set_size.c ├── size.sh ├── usb.c ├── usb.h ├── val └── validate.c └── validate.c /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # (c) Copyright Paul Campbell paul@taniwha.com 2013, 2014 2 | # 3 | # This library is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU Lesser General Public 5 | # License as published by the Free Software Foundation; either 6 | # version 2.1 of the License, or (at your option) version 3, or any 7 | # later version accepted by Paul Campbell , who shall 8 | # act as a proxy defined in Section 6 of version 3 of the license. 9 | # 10 | # This library 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 GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library. If not, see . 17 | # 18 | 19 | THIS_ARCH = 255 # set this to match the hardware - invalid in this case 20 | THIS_CODE_BASE = 0 # set this to match the code base currently running in the board 21 | THIS_VERSION = 2 # suota version 22 | # DRV_KEYS = 1 # define for key driver 23 | # DRV_LEDS = 1 # define for leds driver 24 | # DRV_DAYLIGHT = 1 # define for daylight detector driver 25 | 26 | # kernel tree root for building kernels 27 | KERNEL_ROOT=. 28 | SERIAL_ROOT=../sys 29 | 30 | # 31 | # where the app is 32 | # 33 | APP_ROOT=. 34 | APP_NAME=cdc_app 35 | 36 | 37 | SDCC_INSTALL_DIR = /usr/local/share/sdcc 38 | KERNEL_ALL = packet_loader kernel.ihx kernel.lk 39 | #KERNEL_ALL = 40 | 41 | HOST_CC = gcc 42 | HOST_CPP = g++ 43 | CC = sdcc 44 | LD = sdld -n 45 | AS = sdas8051 46 | 47 | BASE0 = 0x2000 48 | BASE1 = 0x5000 49 | 50 | CFLAGS = -mmcs51 --model-medium --opt-code-size --debug -I$(KERNEL_ROOT)/include -DBASE0=$(BASE0) -DBASE1=$(BASE1) 51 | CFLAGS += -DTHIS_ARCH=$(THIS_ARCH) -DTHIS_CODE_BASE=$(THIS_CODE_BASE) -DTHIS_VERSION=$(THIS_VERSION) 52 | ifdef DRV_KEYS 53 | CFLAGS += -DDRV_KEYS 54 | endif 55 | ifdef DRV_LEDS 56 | CFLAGS += -DDRV_LEDS 57 | endif 58 | ifdef DRV_DAYLIGHT 59 | CFLAGS += -DDRV_DAYLIGHT 60 | endif 61 | CFLAGS += -DPOOL_SIZE=7168 62 | LDLIBS_SA = -k $(SDCC_INSTALL_DIR)/lib/medium -l mcs51 -l libsdcc -l libint -l liblong -l libfloat 63 | LDLIBS = -k $(SDCC_INSTALL_DIR)/lib/medium -l libsdcc -l libint -l liblong -l libfloat 64 | LDFLAGS_SA = -muwx -b SSEG=0x80 $(LDLIBS_SA) -M -Y -b BSEG=9 65 | LDFLAGS = -muwx -b SSEG=0x80 $(LDLIBS) -M -Y 66 | LDEVEN = -b GSINIT0=$(BASE0) 67 | LDODD = -b GSINIT0=$(BASE1) 68 | 69 | 70 | # kernel objects 71 | KOBJ = task.rel # suota.rel rf.rel suota_key.rel 72 | ifdef DRV_LEDS 73 | KOBJ += leds.rel 74 | endif 75 | ifdef DRV_KEYS 76 | KOBJ += keys.rel 77 | endif 78 | 79 | CFLAGS += -DAPP 80 | AOBJ = $(APP_NAME).rel cdc.rel usb.rel validate.rel manufacturing.rel 81 | APP_REQUIRED=kernel.lk syms.rel app_hdr.rel fixcrc 82 | #APP_REQUIRED= 83 | 84 | all: $(APP_NAME).256k 85 | images: $(APP_NAME).img.256k 86 | 87 | $(APP_NAME).128k: $(APP_NAME).sig.128k $(APP_NAME).img.128k $(APP_NAME).len.sig.128k FFFF 88 | cat $(APP_NAME).img.128k $(APP_NAME).len.sig.128k $(APP_NAME).sig.128k FFFF >$(APP_NAME).128k 89 | truncate -s 131072 $(APP_NAME).128k 90 | $(APP_NAME).256k: $(APP_NAME).sig.256k $(APP_NAME).img.256k $(APP_NAME).len.sig.256k FFFF 91 | cat $(APP_NAME).img.256k $(APP_NAME).len.sig.256k $(APP_NAME).sig.256k FFFF >$(APP_NAME).256k 92 | truncate -s 262144 $(APP_NAME).256k 93 | 94 | 95 | FFFF: ffff.c 96 | gcc -o ff ffff.c 97 | ./ff >FFFF 98 | 99 | $(APP_NAME).len.sig.256k: $(APP_NAME).sig.256k set_size 100 | ./set_size $(APP_NAME).sig.256k >$(APP_NAME).len.sig.256k 101 | 102 | $(APP_NAME).len.sig.128k: $(APP_NAME).sig.128k set_size 103 | ./set_size $(APP_NAME).sig.128k >$(APP_NAME).len.sig.128k 104 | 105 | set_size: set_size.c 106 | gcc -o set_size set_size.c 107 | 108 | $(APP_NAME).sig.128k: $(APP_NAME).img.128k 109 | rm -f $(APP_NAME).sig.128k 110 | gpg -u 0x35d6020c --output $(APP_NAME).sig.128k --detach-sig $(APP_NAME).img.128k 111 | 112 | $(APP_NAME).sig.256k: $(APP_NAME).img.256k 113 | rm -f $(APP_NAME).sig.256k 114 | gpg -u 0x35d6020c --output $(APP_NAME).sig.256k --detach-sig $(APP_NAME).img.256k 115 | 116 | 117 | 118 | $(APP_NAME).img.128k: $(APP_NAME).ihx random_data merge.sh 119 | ./merge.sh $(APP_NAME).ihx random_data 131072 $(APP_NAME).img.128k 120 | 121 | $(APP_NAME).img.256k: $(APP_NAME).ihx random_data merge.sh 122 | ./merge.sh $(APP_NAME).ihx random_data 262144 $(APP_NAME).img.256k 123 | 124 | 125 | ############## App starts here ############################################ 126 | # 127 | # To build a SUOTA app: 128 | # 129 | # - create a new app build directory 130 | # - copy this Makefile to the app build directory 131 | # - copy sample_app/app.c to app build directory 132 | # - change directory to the new build directory 133 | # - edit the Makefile 134 | # - edit APP_NAME 135 | # - edit APP_ROOT to point to "." 136 | # - edit KERNEL_ROOT and SERIAL_ROOT to point to the place you installed the kernel 137 | # - set "THIS_ARCH" to match your hardware 138 | # - choose a value for "THIS_CODE_BASE" (probably this means choosing a random CODE_BASE between 1-254) 139 | # - edit THIS_VERSION to 1 (increment each time you make a downloadble build) 140 | # - type "make" to build a kernel/etc 141 | # - build and test your kernel and app until you want to freeze it then: 142 | # - make a subdirectory called 'save' and copy everything into it (just in case you lose the kernel) 143 | # - edit the Makefile again 144 | # - in the makefile remove everything below "## Kernel starts here ##" 145 | # - edit APP_REQUIRED to make it empty 146 | # - edit KERNEL_ALL to make it empty 147 | # 148 | # Below is a 'push' target you can use to automatically bump the version number, build 149 | # and push a new image to a device 150 | # 151 | 152 | # 153 | # unified build for example application - you must include app_integrated.rel 154 | # 155 | $(APP_NAME).ihx: $(KOBJ) $(AOBJ) app_integrated.rel 156 | $(LD) $(LDFLAGS_SA) -i $(APP_NAME).ihx $(KOBJ) $(AOBJ) app_integrated.rel 157 | 158 | # 159 | # example application 160 | # 161 | $(APP_NAME).rel: $(APP_ROOT)/$(APP_NAME).c $(KERNEL_ROOT)/include/interface.h 162 | $(CC) $(CFLAGS) -I $(SERIAL_ROOT)/serial -c $(APP_ROOT)/$(APP_NAME).c -o $(APP_NAME).rel 163 | cdc.rel: $(APP_ROOT)/cdc.c $(KERNEL_ROOT)/include/interface.h 164 | $(CC) $(CFLAGS) -c $(APP_ROOT)/cdc.c -o cdc.rel 165 | usb.rel: $(APP_ROOT)/usb.c $(KERNEL_ROOT)/include/interface.h 166 | $(CC) $(CFLAGS) -c $(APP_ROOT)/usb.c -o usb.rel 167 | validate.rel: $(APP_ROOT)/validate.c $(KERNEL_ROOT)/include/interface.h 168 | $(CC) $(CFLAGS) -I.. -c $(APP_ROOT)/validate.c -o validate.rel 169 | manufacturing.rel: $(APP_ROOT)/manufacturing.c $(KERNEL_ROOT)/include/interface.h 170 | $(CC) $(CFLAGS) -I.. -c $(APP_ROOT)/manufacturing.c -o manufacturing.rel 171 | 172 | # 173 | # code to automatically build and push new software versions of code to 174 | # a single remote device. 175 | # 176 | # Put the key you want to SUOTA with and the channel it happens on below, use the 177 | # command 178 | # 179 | # "make push" 180 | # 181 | # to build new code and push it to a device 182 | # 183 | APP_SUOTA_KEY=-k ccb17cb57448634ce595c15acf966145 184 | APP_SUOTA_CHANNEL=11 185 | 186 | push: $(AOBJ) $(APP_REQUIRED) THIS_VERSION packet_loader 187 | version=`cat ./THIS_VERSION` ; \ 188 | version=$$(($$version+1));\ 189 | odd=$$(($$version%2));\ 190 | if test $$odd -eq 1; then \ 191 | $(LD) $(LDODD) $(LDFLAGS) -f kernel.lk -i tmp.ihx $(AOBJ) syms.rel app_hdr.rel;\ 192 | else \ 193 | $(LD) $(LDEVEN) $(LDFLAGS) -f kernel.lk -i tmp.ihx $(AOBJ) syms.rel app_hdr.rel;\ 194 | fi ; \ 195 | ./fixcrc -v $$version $(APP_SUOTA_KEY) $(APP_NAME).suota;\ 196 | echo $$version >THIS_VERSION ; \ 197 | echo Installing version $$version ; \ 198 | ./packet_loader -c $(APP_SUOTA_CHANNEL) -x $(APP_NAME).suota 199 | 200 | THIS_VERSION: 201 | echo $(THIS_VERSION) >THIS_VERSION 202 | 203 | 204 | ############## Kernel starts here ############################################ 205 | # 206 | # To build a kernel for SUOTA: 207 | # 208 | # - edit the "THIS_" variables above to suit set the version to 0 209 | # - edit LDLIBS/LDLIBS_SA to point to where your SDCC libraries were installed 210 | # - change HOST_CC/HOST_CPP to point to your local native compilers 211 | # - type "make kernel" 212 | # - copy the folowing files to your app build directory: 213 | # - kernel.lk 214 | # - app_hdr.rel 215 | # - syms.rel 216 | # - fixcrc 217 | # - burn the kernel.ihx file into your hardware 218 | # 219 | kernel: kernel.lk app_hdr.rel syms.rel fixcrc 220 | 221 | # 222 | # create loader script to export kernel context to loadable apps 223 | # 224 | kernel.lk: kernel.map $(KERNEL_ROOT)/kernel/map.pl 225 | perl $(KERNEL_ROOT)/kernel/map.pl kernel.lk 226 | # 227 | # build kernel - kernel.ihx is what you build into a board (we'll add somethign here to allow 228 | # later patching of MAC addresses) 229 | # 230 | kernel.ihx kernel.map: $(KOBJ) dummy.rel 231 | $(LD) $(LDFLAGS_SA) -l mcs51 -b PSEG=0 -b XSEG=0x100 -i kernel.ihx $(KOBJ) dummy.rel 232 | 233 | 234 | # 235 | # build kernel objects - leds.rel and kerys.rel should be left out of you don't need them 236 | # 237 | task.rel: $(KERNEL_ROOT)/kernel/task.c $(KERNEL_ROOT)/include/task.h $(KERNEL_ROOT)/include/interface.h 238 | $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/task.c 239 | #rf.rel: $(KERNEL_ROOT)/kernel/rf.c $(KERNEL_ROOT)/include/rf.h $(KERNEL_ROOT)/include/task.h $(KERNEL_ROOT)/include/interface.h $(KERNEL_ROOT)/include/suota.h $(KERNEL_ROOT)/include/protocol.h 240 | # $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/rf.c 241 | #keys.rel: $(KERNEL_ROOT)/kernel/keys.c $(KERNEL_ROOT)/include/rf.h $(KERNEL_ROOT)/include/task.h $(KERNEL_ROOT)/include/interface.h $(KERNEL_ROOT)/include/suota.h $(KERNEL_ROOT)/include/protocol.h 242 | # $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/keys.c 243 | #suota.rel: $(KERNEL_ROOT)/kernel/suota.c $(KERNEL_ROOT)/include/rf.h $(KERNEL_ROOT)/include/task.h $(KERNEL_ROOT)/include/interface.h $(KERNEL_ROOT)/include/suota.h $(KERNEL_ROOT)/include/protocol.h 244 | # $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/suota.c 245 | #suota_key.rel: $(KERNEL_ROOT)/kernel/suota_key.c #change this if you want a private efault suota key 246 | # $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/suota_key.c 247 | #leds.rel: $(KERNEL_ROOT)/kernel/leds.s 248 | # $(AS) -z -l -o leds.rel $(KERNEL_ROOT)/kernel/leds.s 249 | 250 | # 251 | # this file provides access to kernel symbols exported using the linker .lk file - this 252 | # is solely to avoid a bug in sdcc's linker which complains if you have a -g 253 | # directive to declare a global variable but never use it 254 | # 255 | syms.rel: $(KERNEL_ROOT)/kernel/syms.c 256 | $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/syms.c 257 | 258 | # 259 | # code header for unified build 260 | # 261 | app_integrated.rel: $(KERNEL_ROOT)/kernel/app_integrated.c $(KERNEL_ROOT)/include/task.h $(KERNEL_ROOT)/include/interface.h 262 | $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/app_integrated.c 263 | 264 | # 265 | # code header for SUOTA apps 266 | # 267 | app_hdr.rel: $(KERNEL_ROOT)/kernel/app_hdr.c $(KERNEL_ROOT)/include/rf.h $(KERNEL_ROOT)/include/task.h $(KERNEL_ROOT)/include/interface.h $(KERNEL_ROOT)/include/suota.h $(KERNEL_ROOT)/include/protocol.h 268 | $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/app_hdr.c 269 | 270 | # 271 | # dummy code header for kernel build 272 | # 273 | dummy.rel: $(KERNEL_ROOT)/kernel/dummy.c $(KERNEL_ROOT)/include/protocol.h 274 | $(CC) $(CFLAGS) -c $(KERNEL_ROOT)/kernel/dummy.c 275 | 276 | # 277 | # app to fill in code headers in SUOTA builds and create loadable binaries 278 | # 279 | fixcrc: $(KERNEL_ROOT)/kernel/fixcrc.c 280 | $(HOST_CC) -o fixcrc $(KERNEL_ROOT)/kernel/fixcrc.c 281 | 282 | 283 | # 284 | # linux side packet interface code for talking to the serial internet gateway 285 | # plus example interactive version - this app will host a SUOTA server for your 286 | # network 287 | # 288 | packet_loader: packet_interface.o packet_loader.o 289 | $(HOST_CPP) -o packet_loader packet_interface.o packet_loader.o -lpthread -g -lz 290 | packet_loader.o: $(SERIAL_ROOT)/serial/packet_interface.h $(SERIAL_ROOT)/serial/test.cpp $(SERIAL_ROOT)/serial/ip_packet_interface.h 291 | $(HOST_CPP) -c $(SERIAL_ROOT)/serial/test.cpp -o packet_loader.o -I $(KERNEL_ROOT)/include -I $(SERIAL_ROOT)/serial -g 292 | packet_interface.o: $(SERIAL_ROOT)/serial/packet_interface.h $(SERIAL_ROOT)/serial/packet_interface.cpp 293 | $(HOST_CPP) -c $(SERIAL_ROOT)/serial/packet_interface.cpp -I $(KERNEL_ROOT)/include -I $(SERIAL_ROOT)/serial -g 294 | ip_packet_interface.o: $(SERIAL_ROOT)/serial/packet_interface.h $(SERIAL_ROOT)/serial/ip_packet_interface.cpp $(SERIAL_ROOT)/serial/ip_packet_interface.h 295 | $(HOST_CPP) -c $(SERIAL_ROOT)/serial/ip_packet_interface.cpp -I $(KERNEL_ROOT)/include -I $(SERIAL_ROOT)/serial -g 296 | 297 | 298 | # 299 | # 300 | # unified serial app for the dev board that turns it into a packet gateway 301 | # 302 | SOBJ = serial_app.rel app_integrated.rel 303 | serial.ihx: $(KOBJ) packet_interface.o $(SOBJ) 304 | $(LD) $(LDFLAGS_SA) -i serial.ihx $(KOBJ) $(SOBJ) 305 | serial_app.rel: $(SERIAL_ROOT)/serial/serial_app.c $(KERNEL_ROOT)/include/rf.h $(KERNEL_ROOT)/include/task.h $(KERNEL_ROOT)/include/interface.h $(KERNEL_ROOT)/include/suota.h $(SERIAL_ROOT)/serial/packet_interface.h $(KERNEL_ROOT)/include/protocol.h 306 | $(CC) $(CFLAGS) -c $(SERIAL_ROOT)/serial/serial_app.c 307 | 308 | 309 | 310 | # 311 | # how to build standalone code without the kernel 312 | # 313 | TOBJ = test.rel leds.rel 314 | test: $(TOBJ) 315 | $(LD) $(LDFLAGS_SA) -i test $(TOBJ) 316 | 317 | test.rel: test.c 318 | $(CC) $(CFLAGS) -c test.c 319 | 320 | clean: 321 | rm -f *.rel *.map *.lst *.ihx *.asm *.mem *.sym *.lk *.rst *.o *.cdb *.adb *.omf packet_loader fixcrc *.suota *.128k *.256k 322 | 323 | 324 | 325 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | firmware 2 | ======== 3 | 4 | This repository contains firmware for the OneRNG entropy generator 5 | 6 | To build this you will need a copy of the same version of the open source SDCC compiler 7 | that we use to build the system - you can find one here 8 | 9 | http://moonbaseotago.com/cheaprf/sdcc-2533.tar.gz 10 | 11 | You can find more documentation about setting up a build sustem and programming devices here: 12 | 13 | http://www.moonbaseotago.com/cheaprf/#programming 14 | 15 | The code contained in this directory is a fork of the MoonbaseOtago CheapRF code - it has 16 | had the RF and SUOTA bits removed for obvious security reasons, you can look at and download 17 | the original code in its repository here: 18 | 19 | https://github.com/MoonbaseOtago/CC-System 20 | 21 | Documentation about the minimal OS and how to use it is here: 22 | 23 | http://www.moonbaseotago.com/cheaprf/programming.html 24 | 25 | The one main difference is that the thread schedular instead of low power idling the CPU 26 | it runs the entropy gathering idle_pool() routine 27 | 28 | Files: 29 | 30 | Makefile - type 'make' to build - change SDCC_INSTALL_DIR to point to where your compiler is installed 31 | usb.c - cc2531 USB stack 32 | cdc.c - USB decsriptors - handler stubs for CDC messages 33 | cdc_app.c - main entropy gathering code (the interesting stuff is here) 34 | kernel/* - task scheuler/kernel support 35 | include/* - kernel incloude files 36 | 37 | The build system works like this: 38 | 39 | 1) build a lodable app cdc_app.ihx (intel hex format - you can just use this if you are rolling your own) 40 | 2) concatenate the memory image of the code with known random_data, truncate the result to 41 | the ROM size less room for a signing 42 | 3) sign the resulting image with our private key (not provided) 43 | 4) pad the remaining code with FFs so that the chip is not code locked (open source and binaries right?) 44 | -------------------------------------------------------------------------------- /cdc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "usb.h" 4 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 5 | // 6 | // This library is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU Lesser General Public 8 | // License as published by the Free Software Foundation; either 9 | // version 2.1 of the License, or (at your option) version 3, or any 10 | // later version accepted by Paul Campbell , who shall 11 | // act as a proxy defined in Section 6 of version 3 of the license. 12 | // 13 | // This library is distributed in the hope that it will be useful, 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | // Lesser General Public License for more details. 17 | // 18 | // You should have received a copy of the GNU Lesser General Public 19 | // License along with this library. If not, see . 20 | // 21 | 22 | extern void wake_5(); 23 | const unsigned char __code descs[] = { 24 | //deviceDesc: ; Device descriptor 25 | 18, 26 | DESC_TYPE_DEVICE, // bDescriptorType 27 | 0, 2, // bcdUSB 28 | 2, // bDeviceClass 29 | 0, // bDeviceSubClass 30 | 0, // bDeviceProtocol 31 | EP0_PACKET_SIZE, 32 | //0x51, 4, // idVendor Texas Instruments 33 | //0xA8, 0x16, // idProduct CC2531 34 | 0x50, 0x1d, // openmoko 35 | 0x86, 0x60, 36 | 9, 0, // bcdDevice 37 | 1, // iManufacturer 38 | 3, // iProduct 39 | 3, // iSerialNumber 40 | 1, // bNumConfigurations 41 | 42 | 43 | //configDesc: ; Configuration descriptor 44 | 9, 45 | DESC_TYPE_CONFIG,// bDescriptorType 46 | 0x43, 0, 47 | 2, // NumInterfaces 48 | 1, // bConfigurationValue 49 | 0, // iConfiguration 50 | 0x80, // bmAttributes 51 | 100, // MaxPower 52 | // 53 | // INTERFACE 0 // 54 | // 55 | 56 | 57 | //interface0Desc: ; Interface descriptor 58 | 9, 59 | DESC_TYPE_INTERFACE, // bDescriptorType 60 | 0, // bInterfaceNumber 61 | 0, // bAlternateSetting 62 | 1, // bNumEndpoints 63 | COMM_INTF, // bInterfaceClass 64 | ABSTRACT_CONTROL_MODEL, // bInterfaceSubClass 65 | V25TER, // bInterfaceProcotol 66 | 0, // iInterface 67 | 68 | // CDC Class-Specific Descriptors 69 | //headerFunctionalDesc: ; Header Functional Descriptor 70 | 5, 71 | CS_INTERFACE, 72 | DSC_FN_HEADER, 73 | 0x10, 0x1, 74 | //absCtrlManFuncDesc: ; Abstract Control Management Functional Descriptor 75 | 4, 76 | CS_INTERFACE, 77 | DSC_FN_ACM, 78 | 0x6, 79 | //unionFunctionalDesc: ; Union Functional Descriptor 80 | 5, 81 | CS_INTERFACE, 82 | DSC_FN_UNION, 83 | 0, 84 | 1, 85 | //callMngFuncDesc: ; Call Management Functional Descriptor 86 | 5, 87 | CS_INTERFACE, 88 | DSC_FN_CALL_MGT, 89 | 0, 90 | 1, 91 | 92 | //endpoint0Desc: ; Endpoint descriptor (EP2 IN) 93 | 7, 94 | DESC_TYPE_ENDPOINT, // bDescriptorType 95 | 0x82, // bEndpointAddress 96 | EP_ATTR_INT, // bmAttributes 97 | 0x20, 0, // wMaxPacketSize 98 | 0x40, // bInterval 99 | 100 | // 101 | // INTERFACE 1 - EP 5 - random 102 | // 103 | 104 | //interface1Desc: ; Interface descriptor 105 | 9, 106 | DESC_TYPE_INTERFACE, // Interface descriptor type 107 | 1, // Interface Number 108 | 0, // Alternate Setting Number 109 | 2, // Number of endpoints in this intf 110 | DATA_INTF, // Class code 111 | 0, // Subclass code 112 | NO_PROTOCOL, // Protocol code 113 | 4, // Interface string index 114 | 115 | 116 | //endpoint1Desc: ; Endpoint descriptor (EP5 OUT) 117 | 7, 118 | DESC_TYPE_ENDPOINT, // bDescriptorType 119 | 0x85, // bEndpointAddress 120 | EP_ATTR_BULK, // bmAttributes 121 | 64, 0, // wMaxPacketSize 122 | 1, // bInterval 123 | 124 | //endpoint2Desc: ; Endpoint descriptor (EP5 IN) 125 | 7, 126 | DESC_TYPE_ENDPOINT, // bDescriptorType 127 | 5, // bEndpointAddress 128 | EP_ATTR_BULK, // bmAttributes 129 | 64, 0, // wMaxPacketSize 130 | 1, // bInterval 131 | 132 | 133 | //-------------- 134 | // String descriptors 135 | //string0Desc: ; Language ID 136 | 4, 137 | DESC_TYPE_STRING, // bDescriptorType 138 | 9, // US-EN 139 | 4, 140 | 141 | //string1Desc: ; Manufacturer 142 | 102, 143 | DESC_TYPE_STRING, // bDescriptorType 144 | 'M', 0, 145 | 'o', 0, 146 | 'o', 0, 147 | 'n', 0, 148 | 'b', 0, 149 | 'a', 0, 150 | 's', 0, 151 | 'e', 0, 152 | ' ', 0, 153 | 'O', 0, 154 | 't', 0, 155 | 'a', 0, 156 | 'g', 0, 157 | 'o', 0, 158 | ' ', 0, 159 | 'h', 0, 160 | 't', 0, 161 | 't', 0, 162 | 'p', 0, 163 | ':', 0, 164 | '/', 0, 165 | '/', 0, 166 | 'w', 0, 167 | 'w', 0, 168 | 'w', 0, 169 | '.', 0, 170 | 'm', 0, 171 | 'o', 0, 172 | 'o', 0, 173 | 'n', 0, 174 | 'b', 0, 175 | 'a', 0, 176 | 's', 0, 177 | 'e', 0, 178 | 'o', 0, 179 | 't', 0, 180 | 'a', 0, 181 | 'g', 0, 182 | 'o', 0, 183 | '.', 0, 184 | 'c', 0, 185 | 'o', 0, 186 | 'm', 0, 187 | '/', 0, 188 | 'r', 0, 189 | 'a', 0, 190 | 'n', 0, 191 | 'd', 0, 192 | 'o', 0, 193 | 'm', 0, 194 | 195 | //string2Desc: ; Product 196 | 70, 197 | DESC_TYPE_STRING, // bDescriptorType 198 | 'C', 0, 199 | 'C', 0, 200 | '2', 0, 201 | '5', 0, 202 | '3', 0, 203 | '1', 0, 204 | ' ', 0, 205 | 'U', 0, 206 | 'S', 0, 207 | 'B', 0, 208 | ' ', 0, 209 | 'R', 0, 210 | 'a', 0, 211 | 'n', 0, 212 | 'd', 0, 213 | 'o', 0, 214 | 'm', 0, 215 | ' ', 0, 216 | 'N', 0, 217 | 'u', 0, 218 | 'm', 0, 219 | 'b', 0, 220 | 'e', 0, 221 | 'r', 0, 222 | ' ', 0, 223 | 'G', 0, 224 | 'e', 0, 225 | 'n', 0, 226 | 'e', 0, 227 | 'r', 0, 228 | 'a', 0, 229 | 't', 0, 230 | 'o', 0, 231 | 'r', 0, 232 | 233 | //string3Desc: ; Serial number 234 | 6, 235 | DESC_TYPE_STRING, // bDescriptorType 236 | '0', 0, 237 | '0', 0, 238 | 239 | //string4Desc: ; interface 1 - "random" 240 | 14, 241 | DESC_TYPE_STRING, // bDescriptorType 242 | 'R', 0, 243 | 'a', 0, 244 | 'n', 0, 245 | 'd', 0, 246 | 'o', 0, 247 | 'm', 0, 248 | 249 | 0 // 0 len is end tag 250 | }; 251 | 252 | struct lc __xdata line_config; 253 | static struct lc __xdata line_config_alt; 254 | __bit cdcRTS; 255 | 256 | void class_out(void) 257 | { 258 | if (setup_header.request == CDC_SET_CONTROL_LINE_STATE) { // 0x22 259 | if(ep0Status == EP_IDLE) { 260 | unsigned char ep = setup_header.index&0x1f; 261 | unsigned char v = setup_header.value&1; 262 | cdcRTS = v; 263 | usb_can_send_5(); 264 | ep0Status = EP_RX; 265 | } 266 | } else 267 | if (setup_header.request == CDC_SET_LINE_CODING) { 268 | if(ep0Status == EP_IDLE) { 269 | unsigned char ep = setup_header.index&0x1f; 270 | if (ep == 0) { 271 | pData = (unsigned char __xdata *) &line_config; 272 | } else { 273 | pData = (unsigned char __xdata *) &line_config_alt; 274 | } 275 | 276 | ep0Status = EP_RX; 277 | } else 278 | if (ep0Status == EP_RX) { 279 | unsigned char ep = setup_header.index&0x1f; 280 | if (ep == 0) 281 | change_uart_mode(); 282 | } 283 | } else { 284 | ep0Status = EP_STALL; 285 | } 286 | } 287 | 288 | void class_in(void) 289 | { 290 | if (setup_header.request == CDC_GET_LINE_CODING) { 291 | if (ep0Status == EP_IDLE) { 292 | unsigned char ep = setup_header.index; 293 | if (ep == 0) { 294 | pData = (unsigned char __xdata *) &line_config; 295 | } else { 296 | pData = (unsigned char __xdata *) &line_config_alt; 297 | } 298 | bytes_left = 7; 299 | ep0Status = EP_TX; 300 | } else 301 | if (ep0Status == EP_TX) { 302 | } 303 | } else { 304 | ep0Status = EP_STALL; 305 | } 306 | } 307 | 308 | void cdc_init(unsigned long baudrate) 309 | { 310 | // Set default line coding. 311 | line_config.baudRate = baudrate; 312 | line_config.charFormat = CDC_CHAR_FORMAT_1_STOP_BIT; 313 | line_config.parityType = CDC_PARITY_TYPE_NONE; 314 | line_config.dataBits = 8; 315 | cdcRTS = 0; 316 | 317 | // Initialise hardware flow control 318 | // Initialize the USB interrupt handler with bit mask containing all processed USBIRQ events 319 | usb_init(); 320 | 321 | P1DIR |= 1<<0; 322 | P1INP |= 1<<0; 323 | P1_0 = 1; 324 | } 325 | 326 | -------------------------------------------------------------------------------- /cdc_app.c: -------------------------------------------------------------------------------- 1 | #define VERSION 3 2 | __code char version[] = "\r\nVersion 3\r\n"; 3 | // (c) Copyright Paul Campbell paul@taniwha.com 2013, 2014, 2015 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) version 3, or any 9 | // later version accepted by Paul Campbell , who shall 10 | // act as a proxy defined in Section 6 of version 3 of the license. 11 | // 12 | // This library is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | // Lesser General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU Lesser General Public 18 | // License along with this library. If not, see . 19 | // 20 | 21 | #define NORM_LED 1 // disable when debugging 22 | 23 | #include 24 | #include 25 | #include "interface.h" 26 | #include "string.h" 27 | #include "packet_interface.h" 28 | #include "usb.h" 29 | 30 | #define RX_SIZE 250 31 | #define TX_SIZE 250 32 | 33 | extern __xdata task manufacturing_task; // manufacturing task; 34 | 35 | // 36 | // UART access USB<->uart 37 | // 38 | 39 | unsigned char __xdata pool[POOL_SIZE]; 40 | __xdata unsigned char *__data pool_in = &pool[0]; 41 | __xdata unsigned char *__data pool_out = &pool[0]; 42 | __xdata unsigned char *__data pool_update = &pool[0]; 43 | unsigned int __data pool_count=0; 44 | __bit pool_busy=0; 45 | __bit no_crc=0; 46 | __bit no_avalanche=0; 47 | __bit rf_source=0; 48 | __bit rf_running=0; 49 | __bit dumping=0; 50 | __bit versioning=0; 51 | __bit secret=0; 52 | __bit IDing=0; 53 | __bit alt_action=0; 54 | __bit in_odd=0; 55 | unsigned char sv; 56 | extern void start_encrypt(); 57 | extern void send_id_block(); 58 | extern void encrypt_random_block(); 59 | extern void encrypt_token(); 60 | extern void encrypt_secret_blocks(); 61 | extern void sync_header(); 62 | extern unsigned char __xdata token[]; 63 | 64 | static unsigned char __pdata time_rf_dwell = 0; 65 | unsigned char __data vind; 66 | #define MAX_00_S 8 67 | #define MAX_FF_S 8 68 | 69 | unsigned char __data num_zeros=0; 70 | unsigned char __data num_ffs=0; 71 | unsigned char __data error_state=0; 72 | unsigned char __data dump_state; 73 | unsigned int __data dump_addr; 74 | unsigned char __data dump_page; 75 | 76 | extern __bit cdcRTS; 77 | __bit pause=1; 78 | extern unsigned char __data eventMaskIn; 79 | extern unsigned char __data eventMaskOut; 80 | 81 | static void pool_rcv_thread(task __xdata*t); 82 | static __xdata task pool_rcv_task = {pool_rcv_thread,0,0,0}; 83 | 84 | static void pool_cmd_thread(task __xdata*t); 85 | static __xdata task pool_cmd_task = {pool_cmd_thread,0,0,0}; 86 | 87 | static void error_thread(task __xdata*t); 88 | static __xdata task error_task = {error_thread,0,0,0}; 89 | 90 | static void rf_thread(task __xdata*t); 91 | static __xdata task rf_task = {rf_thread,0,0,0}; 92 | 93 | __bit flv=0; 94 | __bit flash=0; 95 | static void flash_thread(task __xdata*t); 96 | static __xdata task flash_task = {flash_thread,0,0,0}; 97 | void flash_thread(task __xdata*t) 98 | { 99 | if (!flash) 100 | return; 101 | P1_1 = flv; // we use this to signal that the USB is working 102 | flv = !flv; // during manufacturing tests 103 | queue_task(&flash_task, HZ/4); 104 | } 105 | 106 | static void 107 | cpl() __naked 108 | { 109 | __asm; 110 | cpl p1.1 111 | ret 112 | __endasm; 113 | } 114 | 115 | static void 116 | error_thread(task __xdata*t) 117 | { 118 | if (num_zeros == MAX_00_S) { 119 | if (error_state == 1) { // too many 00s? flash 1 on 3 off - stuck at 0 120 | #ifdef NORM_LED 121 | P1_1 = 0; 122 | #endif 123 | error_state = 0; 124 | queue_task(&error_task, 3*HZ); 125 | } else { 126 | P1_1 = 1; 127 | error_state = 1; 128 | queue_task(&error_task, 1*HZ); 129 | } 130 | } else 131 | if (num_ffs == MAX_FF_S) { // too many FFs? flash 1 on 1 off 1 on 3 off - stuck at 1 132 | if (error_state >= 3) { 133 | #ifdef NORM_LED 134 | P1_1 = 0; 135 | #endif 136 | error_state = 0; 137 | queue_task(&error_task, 3*HZ); 138 | } else 139 | if (error_state == 1) { 140 | #ifdef NORM_LED 141 | P1_1 = 0; 142 | #endif 143 | error_state = 2; 144 | queue_task(&error_task, 1*HZ); 145 | } else { 146 | #ifdef NORM_LED 147 | P1_1 = 1; 148 | #endif 149 | error_state++; 150 | queue_task(&error_task, 1*HZ); 151 | } 152 | } else { 153 | error_state = 0; // normal state - just poll for an error state 154 | // P1_1 = pool_busy; 155 | queue_task(&error_task, 1*HZ); 156 | } 157 | } 158 | 159 | void 160 | queue_pool_data(unsigned char x) __naked 161 | { 162 | __asm; 163 | mov _RNDH, dpl // RNDH = x; // through the crc16 164 | jb _no_crc, 0200$ // if (!no_crc) { // whiten the data 165 | mov dpl, _RNDH // x = RNDH; // hardware 166 | // } 167 | 0200$: clr EA 168 | mov a, _pool_count // if (pool_count == POOL_SIZE) { 169 | cjne a, #POOL_SIZE, 0001$ 170 | mov a, _pool_count+1 171 | cjne a, #POOL_SIZE>>8, 0001$ // // the pool is full, keep stiring it 172 | mov r0, dpl 173 | mov dpl, _pool_update // *pool_update++ ^= x; 174 | mov dph, _pool_update+1 175 | movx a, @dptr 176 | xrl a, r0 177 | movx @dptr, a 178 | inc dptr 179 | mov a, dpl 180 | cjne a, #_pool+POOL_SIZE, 0002$// if (pool_update == &pool[POOL_SIZE]) 181 | mov a, dph // pool_update = &pool[0]; 182 | cjne a, #(_pool+POOL_SIZE)>>8, 0002$ 183 | mov dptr, #_pool 184 | 0002$: mov _pool_update, dpl 185 | mov _pool_update+1, dph 186 | setb EA 187 | ret 188 | 189 | 0001$: // } else { 190 | mov a, dpl 191 | mov dpl, _pool_in // *pool_in++ = x; 192 | mov dph, _pool_in+1 193 | movx @dptr, a 194 | inc dptr 195 | mov a, dpl // if (pool_in == &pool[POOL_SIZE]) 196 | cjne a, #_pool+POOL_SIZE, 0003$// pool_in = &pool[0]; 197 | mov a, dph 198 | cjne a, #(_pool+POOL_SIZE)>>8, 0003$ 199 | mov dptr, #_pool 200 | 0003$: mov _pool_in, dpl 201 | mov _pool_in+1, dph 202 | inc _pool_count // pool_count++; 203 | mov a, _pool_count 204 | jnz 0004$ 205 | inc _pool_count+1 206 | 0004$: 207 | jb _pool_busy, 0005$ // if (!pool_busy && pool_count > 64) { 208 | mov a, _pool_count+1 209 | jnz 0007$ 210 | mov a, _pool_count 211 | jb a.7, 0007$ 212 | jnb a.6, 0005$ 213 | 0007$: 214 | setb _pool_busy // pool_busy = 1; 215 | #ifdef NORM_LED 216 | setb p1.1 // p1.1 = 1; 217 | #endif 218 | mov dptr, #_pool_rcv_task// queue_task(&pool_rcv_task, 0_' 219 | lcall _queue_task_0 220 | 0005$: // } 221 | setb EA // } 222 | ret 223 | __endasm; 224 | } 225 | 226 | void 227 | idle_pool() __naked 228 | { 229 | __asm; // for (;; ) { 230 | 0001$: jb _no_avalanche, 0200$ // if (!no_avalanche) { 231 | mov r0, #8 // for (i = 0; i < 8 i++) 232 | 0003$: mov c, p1.7 // v = (v<<1)|p1.7; 233 | rlc a 234 | djnz r0, 0003$ 235 | mov r1, a // r1 = v; 236 | mov r0, #8 // for (i = 0; i < 8 i++) 237 | 0033$: mov c, p1.7 // v = (v<<1)|p1.7; 238 | rlc a 239 | djnz r0, 0033$ 240 | xrl a, r1 // v = v^r1; 241 | mov dpl, a 242 | jnz 0300$ // if (v == 0) { 243 | mov _num_ffs, #0 // num_ffs = 0; 244 | mov a, _num_zeros // if (num_zeros == MAX_00_S) 245 | cjne a, #MAX_00_S, 0310$ // goto retry 246 | sjmp 0200$ 247 | 0310$: inc _num_zeros // num_zeros++; 248 | sjmp 0302$ // } else 249 | 0300$: cjne a, #0xff, 0301$ // if (v == 0xff) { 250 | mov _num_zeros, #0 // num_zeros = 0; 251 | mov a, _num_ffs // if (num_ffs == MAX_FF_S) 252 | cjne a, #MAX_FF_S, 0311$ // goto retry; 253 | sjmp 0200$ 254 | 255 | 0311$: inc _num_ffs // num_ffs++; 256 | sjmp 0302$ // } else { 257 | 258 | 0301$: mov _num_zeros, #0 // num_zeros = 0; 259 | mov _num_ffs, #0 // num_ffs = 0; 260 | 0302$: // } 261 | mov a, _enter_sleep_mod_flag // if (enter_sleep_mod_flag) break; 262 | jz 0002$ 263 | lcall _queue_pool_data // queue_pool_data(v); 264 | 0200$: mov a, _enter_sleep_mod_flag //retry: if (enter_sleep_mod_flag) break; 265 | jz 0002$ 266 | // } 267 | jnb _rf_running, 0001$ // if (rf_running) { 268 | 269 | 270 | mov a, _enter_sleep_mod_flag //retry: if (enter_sleep_mod_flag) break; 271 | jz 0002$ 272 | mov r0, #8 // for (i = 0; i < 8;i++) 273 | mov dptr, #_RFRND 274 | mov r2, #0 275 | 0500$: movx a, @dptr // v = (v<<1)|RFRND&1; 276 | 277 | mov c, a.0 // - note must wait 8 clocks between samples 278 | mov a, r2 279 | rlc a 280 | mov r2, a 281 | nop 282 | djnz r0, 0500$ 283 | mov dpl, r2 284 | mov a, _enter_sleep_mod_flag// if (enter_sleep_mod_flag) break; 285 | jz 0002$ 286 | lcall _queue_pool_data // queue_pool_data(v); 287 | // } 288 | 0201$: mov a, _enter_sleep_mod_flag // if (enter_sleep_mod_flag) break; 289 | jz 0002$ 290 | ljmp 0001$ 291 | 0002$: // } 292 | ret 293 | __endasm; 294 | } 295 | 296 | static unsigned char 297 | get_5(void) __naked 298 | { 299 | __asm; 300 | mov dptr, #_USBF5 301 | movx a, @dptr 302 | mov dpl, a 303 | ret 304 | __endasm; 305 | } 306 | 307 | static unsigned char __data in_state=0; 308 | 309 | static void 310 | pool_cmd_thread(task __xdata*t) // woken when uart buffers have room new data or USB has data to send 311 | { 312 | for (;;) { 313 | unsigned char c, a; 314 | unsigned char x; 315 | unsigned char x2; 316 | 317 | EA=0; 318 | c = USBINDEX; 319 | USBINDEX = 5; 320 | if (!(USBCSOL&USBCSOL_OUTPKT_RDY)) { 321 | USBINDEX = c; 322 | EA=1; 323 | return; 324 | } 325 | x = USBCNTL; 326 | x2 = USBCNTH; 327 | a = get_5(); // get a character in from USBA 328 | if (in_state == 0) { 329 | if (a == 'c') 330 | in_state=1; 331 | } else 332 | if (in_state == 1) { 333 | if (a == 'm') { 334 | in_state=2; 335 | } else { 336 | in_state=0; 337 | } 338 | } else 339 | if (in_state == 2) { 340 | if (a == 'd') { 341 | in_state=3; 342 | } else { 343 | in_state=0; 344 | } 345 | } else 346 | if (in_state == 3) { 347 | in_state=0; 348 | if (a >= '0' && a <= '9') { 349 | a -= '0'; 350 | set: // a is 4 bit mask 351 | // - bit 0 - disables CRC whitening 352 | // - bit 1 - enables RF source 353 | // - bit 2 - disables avalanche source 354 | if (a&1) { 355 | no_crc = 1; 356 | } else { 357 | no_crc = 0; 358 | } 359 | if (a&2) { 360 | if (!rf_source) { 361 | rf_source = 1; 362 | time_rf_dwell = 0; 363 | cancel_task(&rf_task); 364 | queue_task(&rf_task, 0); 365 | } 366 | } else { 367 | rf_source = 0; 368 | rf_running = 0; 369 | RFST = 0xef; 370 | RFST = 0xec; 371 | } 372 | if (a&4) { 373 | no_avalanche = 1; 374 | } else { 375 | no_avalanche = 0; 376 | } 377 | } else 378 | if (a >= 'a' && a <= 'f') { 379 | a = a-'a'+10; 380 | goto set; 381 | } else 382 | if (a >= 'A' && a <= 'F') { 383 | a = a-'A'+10; 384 | goto set; 385 | } else 386 | if (a == 'X') { 387 | alt_action = 1; 388 | dumping = 1; 389 | dump_state = 0; 390 | dump_addr = 0x8000; 391 | dump_page = 0; 392 | } else 393 | if (a == 'O') { 394 | pause = 0; // run 395 | queue_task_0(&pool_rcv_task); 396 | 397 | } else 398 | if (a == 'v') { 399 | vind = 0; // version 400 | versioning = 1; 401 | alt_action = 1; 402 | } else 403 | if (a == 'I') { 404 | vind = 0; // extract ID 405 | IDing = 1; 406 | alt_action = 1; 407 | } else 408 | if (a == 'S') { 409 | in_state = 10; 410 | in_odd = 0; 411 | } else 412 | if (a == 'o') { 413 | pause = 1; // pause 414 | } else 415 | if (a == 'T') { // flash for testing - flashes the LED during manufacturing when we're testing the USN 416 | flash = !flash; 417 | if (flash) { 418 | flv = 0; 419 | queue_task(&flash_task, 0); 420 | } else { 421 | cancel_task(&flash_task); 422 | } 423 | } else 424 | if (a == 'w') { // flush 425 | pool_in = &pool[0]; 426 | pool_out = &pool[0]; 427 | pool_update = &pool[0]; 428 | pool_count=0; 429 | pool_busy=0; 430 | } 431 | } else 432 | if (in_state >= 10 && in_state < 26) { // suck in token 433 | if (a >= '0' && a <= '9') { 434 | a = a-'0'; 435 | } else 436 | if (a >= 'A' && a <= 'F') { 437 | a = a-'A'; 438 | a = a+10; 439 | } else 440 | if (a >= 'a' && a <= 'f') { 441 | a = a-'a'; 442 | a = a+10; 443 | } else { 444 | goto bad; 445 | } 446 | if (!in_odd) { 447 | sv = a<<4; 448 | in_odd = 1; 449 | } else { 450 | token[in_state-10] = sv|a; 451 | in_odd = 0; 452 | in_state++; 453 | } 454 | if (in_state == 26) { 455 | vind = 0; // encrypt secret 456 | secret = 1; 457 | alt_action = 1; 458 | in_state =0; 459 | } 460 | } else { 461 | bad: in_state = 0; 462 | } 463 | if (x==1 && !x2) { 464 | USBINDEX = 5; 465 | USBCSOL = 0; 466 | } 467 | USBINDEX = c; 468 | EA=1; 469 | } 470 | } 471 | 472 | 473 | 474 | static void 475 | pool_rcv_thread(task __xdata*t) __naked // woken when pool has new data or USB can send data 476 | { 477 | __asm; 478 | mov _DPS, #0 479 | 0001$: // for (;;) { 480 | // unsigned int len; 481 | // unsigned char ep, xlen; 482 | mov a, _eventMaskIn // if (eventMaskIn&USBIIE_EP0IE) 483 | jb a.0, 0020$ // break; 484 | mov a, _eventMaskOut 485 | jb a.5, 0020$ // if (eventMaskOut&USBOIE_OUTEP5IE) 486 | // break 487 | jb _pause, 0020$ // if (pause) 488 | // return; 489 | jnb _cdcRTS, 0020$ // if (!cdcRTS) 490 | // return; 491 | clr EA // EA = 0; 492 | jb _alt_action, 0002$ // if (alt_action) goto do_xtra; 493 | mov a, _pool_count+1 // if (pool_count < 64) { 494 | jnz 0002$ 495 | mov a, _pool_count 496 | jb a.7, 0002$ 497 | jb a.6, 0002$ 498 | #ifdef NORM_LED 499 | clr p1.1 500 | #endif 501 | clr _pool_busy // pool_busy = 0; 502 | setb EA // EA = 1; 503 | 0020$: ret // return; 504 | 0555$: 505 | ljmp 0510$ // } 506 | 507 | 0002$: 508 | mov dptr, #_USBINDEX // ep = USBINDEX; 509 | movx a, @dptr 510 | mov r7, a 511 | mov a, #5 // USBINDEX = 5; 512 | movx @dptr, a 513 | mov dptr, #_USBCSIL // if (USBCSIL&USBCSIL_INPKT_RDY) { 514 | movx a, @dptr 515 | jnb a.0, 0003$ 516 | mov dptr, #_USBINDEX// USBINDEX = ep; 517 | mov a, r7 518 | movx @dptr, a 519 | mov a, _eventMaskIn // eventMaskIn &= ~USBIIE_INEP5IE; 520 | clr a.5 521 | mov _eventMaskIn, a 522 | setb EA // EA = 1; 523 | ret // return; 524 | // } 525 | 1201$: ljmp 1200$ 526 | 6002$: jnb _secret, 4202$ // if (secret) goto do_secret; 527 | ljmp 5202$ 528 | 4202$: jnb _IDing, 4201$ // if (IDing) goto do_id; 529 | ljmp 5201$ 530 | 4201$: jb _versioning, 1201$ // if (versioning) goto do_version; 531 | jnb _dumping, 1555$ // if (dumping) goto do_dump; 532 | ljmp 0555$ 533 | 1555$: clr _alt_action // alt_action = 0; 534 | 535 | 0003$: jb _alt_action, 6002$ // 536 | mov r2, #64 // len = 64; 537 | clr c 538 | mov a, _pool_count // pool_count -= 64; 539 | subb a, r2 540 | mov _pool_count, a 541 | mov a, _pool_count+1 542 | subb a, #0 543 | mov _pool_count+1, a 544 | mov _DPL1, #_USBF5 // // usb_write_fifo_5(pool_out, len); 545 | mov _DPH1, #_USBF5>>8 546 | mov dpl, _pool_out // for (i = 0;i < 64; i++) { 547 | mov dph, _pool_out+1 548 | 0010$: movx a, @dptr // *USBF5 = *pool_out; 549 | inc _DPS 550 | movx @dptr, a 551 | dec _DPS 552 | clr a // *pool_out++ = 0; // delete data once it's sent 553 | movx @dptr, a 554 | inc dptr 555 | mov a, dpl // if (pool_out == &pool[POOL_SIZE]) 556 | cjne a, #_pool+POOL_SIZE, 0011$ 557 | mov a, dph // pool_out = &pool[0]; 558 | cjne a, #(_pool+POOL_SIZE)>>8, 0011$ 559 | mov dptr, #_pool 560 | 0011$: djnz r2, 0010$ // } 561 | mov _pool_out, dpl 562 | mov _pool_out+1, dph 563 | 564 | 0501$: //send_usb: 565 | mov dptr, #_USBINDEX // USBINDEX = 5; 566 | mov a, #5 567 | movx @dptr, a 568 | mov a, #USBCSIL_INPKT_RDY // USBCSIL = USBCSIL_INPKT_RDY; 569 | mov dptr, #_USBCSIL 570 | movx @dptr, a 571 | mov dptr, #_USBINDEX // USBINDEX = ep; 572 | mov a, r7 573 | movx @dptr, a 574 | setb EA // EA = 1; 575 | ljmp 0001$ // } 576 | 577 | // 578 | // code to push rom image 579 | // 580 | // looks like: 581 | // fe ed be ef 20 14 - magic number 582 | // 00 00 04 - len (little endian) 583 | // 00 00 - version (little endian) 584 | // image - len bytes of image 585 | // 586 | 0510$: 587 | clr _DPS 588 | mov _DPL1, #_USBF5 589 | mov _DPH1, #_USBF5>>8 590 | mov r2, #64 // for (i = 0; i < 64; i++) { 591 | 592 | 0500$: 593 | mov a, _dump_state // switch (dump_state) { 594 | cjne a, #13, 0575$ // case 13: 595 | mov a, _dump_page // v = *{dump_page,dump_addr}; 596 | mov _FMAP, a 597 | mov dpl, _dump_addr 598 | mov dph, _dump_addr+1 599 | clr a 600 | movc a, @a+dptr 601 | mov r0, a 602 | inc dptr // dump_addr++; 603 | mov _dump_addr, dpl 604 | mov a, dph 605 | mov _dump_addr+1, a // if (dump_addr == 0) { 606 | 607 | 608 | jnz 0570$ 609 | mov _dump_addr+1, #0x80 // dump_addr = 0x800; 610 | inc _dump_page // dump_page++; 611 | sjmp 0572$ // } 612 | 0570$: cjne a, #0xff, 0572$ // if (address == last 128 bytes) // hide the 'secret' 613 | mov r3, dpl 614 | cjne r3, #0x80, 0572$ 615 | mov r3, _dump_page 616 | cjne r3, #0x7, 0572$ 617 | inc _dump_state // last bytes dump_state++ 618 | // 619 | 0572$: mov a, r0 // break; 620 | 621 | 0700$: inc _DPS // // at end of case statement 622 | movx @dptr, a // *USBF5 = v; 623 | dec _DPS 624 | djnz r2, 0500$ 625 | ljmp 0501$ // goto send_usb; 626 | 627 | 0575$: cjne a, #14, 0600$ // case 14: 628 | mov dpl, _dump_addr // v = 0xff // for secret area 629 | mov dph, _dump_addr+1 630 | mov r0, #0xff 631 | inc dptr // dump_addr++; 632 | mov _dump_addr, dpl 633 | mov a, dph 634 | mov _dump_addr+1, a // if (dump_addr == 0) 635 | jnz 0572$ 636 | inc _dump_state // last byte dump_state++ 637 | sjmp 0572$ 638 | 639 | 0600$: inc _dump_state // case 0: dump_state++; 640 | cjne a, #0, 0601$ 641 | mov a, #0xfe // v = 0xfe; 642 | sjmp 0700$ // break; 643 | 0601$: cjne a, #1, 0602$ // case 1: dump_state++; 644 | mov a, #0xed // v = 0xed; 645 | sjmp 0700$ // break; 646 | 0602$: cjne a, #2, 0603$ // case 2: dump_state++; 647 | mov a, #0xbe // v = 0xbe; 648 | sjmp 0700$ // break; 649 | 0603$: cjne a, #3, 0604$ // case 3: dump_state++; 650 | mov a, #0xef // v = 0xef; 651 | sjmp 0700$ // break; 652 | 0604$: cjne a, #4, 0605$ // case 4: dump_state++; 653 | mov a, #0x20 // v = 0x20; 654 | sjmp 0700$ // break; 655 | 0605$: cjne a, #5, 0606$ // case 5: dump_state++; 656 | mov a, #0x14 // v = 0x14; 657 | sjmp 0700$ // break; 658 | 0606$: cjne a, #6, 0607$ // case 6: dump_state++; 659 | mov a, #0x00 // v = 0x00; 660 | sjmp 0700$ // break; 661 | 0607$: cjne a, #7, 0608$ // case 7: dump_state++; 662 | mov a, #0x00 // v = 0x00; 663 | sjmp 0700$ // break; 664 | 0608$: cjne a, #8, 0609$ // case 8: dump_state++; 665 | mov a, #0x04 // v = 0x04; 666 | sjmp 0700$ // break; 667 | 0609$: cjne a, #9, 0610$ // case 9: dump_state++; 668 | mov a, #VERSION // v = VERSION; 669 | sjmp 0700$ // break; 670 | 0610$: cjne a, #10, 0611$ // case 10: dump_state++; 671 | mov a, #VERSION>>8 // v = VERSION>>8; 672 | ljmp 0700$ // break; 673 | 0611$: cjne a, #11, 0612$ // case 11: dump_state++; 674 | .globl s_CODE 675 | .globl l_CODE 676 | mov a, #s_CODE 677 | add a, #l_CODE // v = text size; 678 | ljmp 0700$ // break; 679 | 0612$: cjne a, #12, 0613$ // case 12: dump_state++; 680 | mov a, #s_CODE 681 | add a, #l_CODE 682 | mov a, #s_CODE>>8 683 | addc a, #l_CODE>>8 // v = (text size)>>8; 684 | ljmp 0700$ // break; 685 | 686 | 0613$: clr _dumping // default:dumping = 0; 687 | ljmp 0501$ // goto send_usb; 688 | // } 689 | // do_version 690 | 1200$: 691 | clr _DPS 692 | mov _DPL1, #_USBF5 693 | mov _DPH1, #_USBF5>>8 694 | mov dptr, #_version 695 | 1203$: // for (;;) { 696 | mov a, _vind // v = version[vind++]; 697 | inc _vind // 698 | movc a, @a+dptr // 699 | jz 1202$ // if (!v) 700 | // break; 701 | inc _DPS // 702 | movx @dptr, a // *USBF5 = v; 703 | dec _DPS 704 | sjmp 1203$ // } 705 | 1202$: 706 | clr _versioning 707 | ljmp 0501$ // goto send_usb; 708 | 5201$: mov a, _vind // do_id: switch (vind) { 709 | jnz 5705$ // case 0: 710 | inc _vind // vind = 1; 711 | lcall _crlf // crlf() 712 | lcall _sync_header// sync_header() 713 | ajmp 0501$ // break; 714 | 5705$: cjne a, #1, 5215$ 715 | inc _vind // case 1: vind = 2; 716 | lcall _send_id_block // send_id_block(); // load block 717 | ajmp 0501$ // break; 718 | 5215$: lcall _sync_header// default:sync_header() 719 | lcall _crlf // crlf() 720 | clr _IDing // IDing = 0; 721 | // } 722 | ajmp 0501$ // goto do_usb; // send blocks 723 | 724 | 5202$: mov a, _vind // do_secret: switch (vind) { 725 | jnz 5207$ // case 0: 726 | inc _vind // vind = 1; 727 | lcall _crlf // crlf() 728 | lcall _sync_header// sync_header() 729 | ajmp 0501$ // break; 730 | 5207$: cjne a, #1, 5206$ // case 1: 731 | inc _vind // vind = 2; 732 | lcall _start_encrypt// start_encrypt(); 733 | lcall _encrypt_random_block// encrypt_random_block(); 734 | ajmp 0501$ // break; 735 | 5206$: cjne a, #2, 5203$ // case 2: 736 | inc _vind // vind = 3; 737 | lcall _encrypt_token// encrypt_token(); 738 | ajmp 0501$ // break; 739 | 5203$: cjne a, #3, 5204$ // case 3: 740 | inc _vind // vind = 4; 741 | lcall _sync_header// sync_header() 742 | ajmp 0501$ // break; 743 | 5204$: cjne a, #4, 5205$ // case 4: 744 | inc _vind // vind = 5; 745 | mov dptr, #0xff80+32 746 | lcall _encrypt_secret_blocks// encrypt_secret_blocks(&secret[32]); 747 | ajmp 0501$ // break; 748 | 5205$: cjne a, #5, 5214$ // case 5: 749 | inc _vind // vind = 6; 750 | mov dptr, #0xff80+64 // 751 | lcall _encrypt_secret_blocks// encrypt_secret_blocks(&secret[32]); 752 | ajmp 0501$ // break; 753 | 5214$: clr _secret // default:secret = 0; 754 | lcall _sync_header// sync_header() 755 | lcall _crlf // crlf() 756 | ajmp 0501$ // } 757 | // goto do_usb; // send blocks 758 | __endasm; 759 | } 760 | 761 | 762 | void 763 | usb_can_send_5() 764 | { 765 | queue_task(&pool_rcv_task, 0); 766 | } 767 | 768 | void 769 | flush_in_5() 770 | { 771 | } 772 | 773 | void 774 | usb_has_data_5() 775 | { 776 | queue_task(&pool_cmd_task, 0); 777 | } 778 | 779 | static void 780 | uart_setup() 781 | { 782 | EA = 0; 783 | cdc_init(9600); 784 | EA = 1; 785 | } 786 | 787 | void 788 | change_uart_mode() 789 | { 790 | } 791 | 792 | 793 | static void rf_thread(task __xdata*t) 794 | { 795 | if (!rf_source) { // idle .... poll 796 | queue_task(&rf_task, HZ/5); 797 | rf_running = 0; 798 | time_rf_dwell = 0; 799 | return; 800 | } 801 | if (time_rf_dwell == 0) { 802 | FREQCTRL = RNDH&0x3f; 803 | time_rf_dwell = (RNDL&0x1f)+80; 804 | FRMCTRL0 = (FRMCTRL0&(3<<2))|(1<<2); // infinite receive mode 805 | RFST = 0xED; // flush 806 | RFST = 0xED; 807 | RFST = 0xec; 808 | RFST = 0xe3; 809 | rf_running = 0; 810 | queue_task(&rf_task, 2); 811 | return; 812 | } 813 | if (!(RSSISTAT&1)) { 814 | queue_task(&rf_task, 2); 815 | rf_running = 0; 816 | time_rf_dwell--; 817 | return; 818 | } 819 | rf_running = 1; 820 | time_rf_dwell--; 821 | queue_task(&rf_task, HZ/30); 822 | } 823 | 824 | 825 | 826 | 827 | unsigned char my_app(unsigned char op) 828 | { 829 | switch (op) { 830 | case APP_INIT: 831 | RNDL = 1; 832 | RNDL = 1; 833 | sys_active = 1; 834 | uart_setup(); 835 | P1DIR |= 1<<1; 836 | P1INP |= 1<<1; 837 | #ifdef NORM_LED 838 | P1_1 = 1; 839 | #else 840 | P1_1 = 0; 841 | #endif 842 | P1DIR &= ~(1<<7); 843 | P1INP |= (1<<7); 844 | RFIRQM0 = 0; // disable RF subsection interrupts 845 | RFIRQM1 = 0; 846 | FRMCTRL0 = (FRMCTRL0&(3<<2))|(1<<2); // infinite receive mode 847 | queue_task(&error_task, 1*HZ); 848 | queue_task(&rf_task, HZ/2); 849 | queue_task(&manufacturing_task, 0); 850 | break; 851 | case APP_GET_MAC: 852 | return 0; 853 | case APP_GET_KEY: 854 | break; 855 | case APP_GET_SUOTA_KEY: 856 | break; 857 | case APP_RCV_PACKET: 858 | break; 859 | } 860 | return 0; 861 | } 862 | -------------------------------------------------------------------------------- /ffff.c: -------------------------------------------------------------------------------- 1 | #include 2 | main() 3 | { 4 | int i; 5 | for (i = 0; i < 66536; i++) 6 | putchar(0xff); 7 | exit(0); 8 | } 9 | -------------------------------------------------------------------------------- /include/interface.h: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | #ifndef __interface_h 20 | #define __interface_h 21 | 22 | #include 23 | #include 24 | #include "task.h" 25 | 26 | #ifndef THIS_ARCH 27 | #define THIS_ARCH 1 // initial CC2533 // 0 unavailable as an extension 28 | #endif 29 | #ifndef THIS_CODE_BASE 30 | #define THIS_CODE_BASE 0 // initial CC2533 31 | #endif 32 | typedef struct code_hdr { // caution: these offsets are hard coded in suota assembly, fixcrc and packet_interface.cpp 33 | unsigned char crc[4]; 34 | unsigned char len[2]; 35 | unsigned char arch; 36 | unsigned char code_base; 37 | unsigned char version[2]; 38 | unsigned char data[1]; 39 | } code_hdr; 40 | 41 | 42 | extern unsigned char (* __data x_app) (u8 v); 43 | #define APP_INIT 0 44 | #define APP_GET_MAC 1 45 | #define APP_GET_KEY 2 46 | #define APP_GET_SUOTA_KEY 3 47 | #define APP_RCV_PACKET 4 48 | #define APP_LOW_LEVEL_INIT 0xff 49 | #define APP_WAKE 5 50 | #define APP_KEY 6 51 | #define APP_SUOTA_START 7 52 | #define APP_SUOTA_DONE 8 53 | __bit __at (0x06) sys_active; 54 | #define KEY_X 0 55 | #define KEY_O 1 56 | #define KEY_LEFT 2 57 | #define KEY_RIGHT 3 58 | 59 | // call backs 60 | #ifdef DRV_LEDS 61 | extern void leds_rgb(unsigned char * __xdata); 62 | extern void leds_off(); 63 | #endif 64 | extern void uart_init(); 65 | extern void putchar(char c); 66 | extern void putstr(char __code *cp); 67 | extern void puthex(unsigned char v); 68 | 69 | 70 | extern void (* __pdata uart_rx_0_vect) (); 71 | extern void (* __pdata uart_rx_1_vect) (); 72 | extern void (* __pdata uart_tx_0_vect) (); 73 | extern void (* __pdata uart_tx_1_vect) (); 74 | extern void (* __pdata p0_vect) (); 75 | extern void (* __pdata p1_vect) (); 76 | extern void (* __pdata p2_vect) (); 77 | extern void (* __pdata t2_vect) (); 78 | extern void (* __pdata t3_vect) (); 79 | extern void (* __pdata t4_vect) (); 80 | extern void (* __pdata adc_vect) (); 81 | extern void (* __pdata aec_vect) (); 82 | extern void (* __pdata dma_vect) (); 83 | 84 | // 85 | // Simple Arduino compatability macros 86 | // 87 | // instead of pin numbers we use P(port,bit) 88 | // P(1,2) refers to pin p1.2 89 | // 90 | // "digitalWrite(P(1,2), HIGH);" 91 | // 92 | #ifndef LOW 93 | #define HIGH 1 94 | #define LOW 0 95 | #define P(p, b) p , b 96 | #define __XP(p,b) P##p##_##b 97 | #define __Xp(p,b) p 98 | #define __Xb(p,b) b 99 | #define digitalWrite(p , v) __XP(p)=(v) 100 | #define digitalRead(p) __XP(p) 101 | #define INPUT 0 102 | #define OUTPUT 1 103 | #define INPUT_PULLUP 2 104 | #define __XPINP(p) P##p##INP 105 | #define __XPDIR(p) P##p##DIR 106 | #define __PINP(p) __XPINP(p) 107 | #define __PDIR(p) __XPDIR(p) 108 | #define pinMode(p, m) if ((m)==OUTPUT) {__PDIR(__Xp(p)) |= (1<<__Xb(p)); __PINP(__Xp(p)) |= (1<<__Xb(p));} else { __PDIR(__Xp(p)) &= ~(1<<__Xb(p)); if ((m)==INPUT_PULLUP) {__PINP(__Xp(p)) &= ~(1<<__Xb(p)); } else {__PINP(__Xp(p)) |= (1<<__Xb(p));} } 109 | #endif 110 | #endif 111 | -------------------------------------------------------------------------------- /include/task.h: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | #ifndef _TASK_H 20 | #define _TASK_H 21 | 22 | __sfr __at (0x93) _XPAGE; 23 | 24 | typedef unsigned char u8; 25 | 26 | typedef struct task { 27 | void (*callout)(struct task __xdata*); // offset 0 28 | unsigned int time; // offset 2 29 | struct task __xdata*next; // offset 4 30 | u8 state; // offset 6 31 | } task; 32 | 33 | void queue_task(task __xdata *, unsigned int); 34 | void queue_task_0(task __xdata *); 35 | void cancel_task(task __xdata * ); 36 | 37 | #define HZ (32000/256) 38 | 39 | 40 | #define TASK_IDLE 0 41 | #define TASK_CALLOUT 1 42 | #define TASK_QUEUED 2 43 | 44 | extern void wait_us(u8); 45 | extern unsigned char app(u8); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /kernel/app_hdr.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | #include "interface.h" 20 | static xxxx() __naked { 21 | __asm; 22 | .area GSINIT0 (CODE) 23 | .globl _CODE_HEADER 24 | _CODE_HEADER: 25 | .db 0, 0, 0, 0 // CRC will go here 26 | .db 0, 0 // len from here to end of code 27 | .db THIS_ARCH 28 | .db THIS_CODE_BASE 29 | .db 0, 0 // version (little endian) 30 | .globl _my_app 31 | mov a, dpl 32 | cjne a, #APP_LOW_LEVEL_INIT, 0001$ 33 | sjmp 0002$ 34 | 0001$: ljmp _my_app 35 | 0002$: mov r0, #s_DSEG // clear data seg 36 | mov a, #l_DSEG 37 | jz 0004$ 38 | mov r1, a 39 | clr a 40 | 0003$: mov @r0, a 41 | inc r0 42 | 0004$: mov r0, #s_PSEG // clear pseg 43 | mov a, #l_PSEG 44 | jz 0006$ 45 | mov r1, a 46 | clr a 47 | 0005$: movx @r0, a 48 | inc r0 49 | djnz r1, 0005$ 50 | 0006$: mov dptr, #s_XSEG // clear xseg 51 | mov r1, #l_XSEG 52 | mov r2, #l_XSEG>>8 53 | cjne r1, #0, 0007$ 54 | cjne r2, #0, 0007$ 55 | sjmp 0011$ 56 | 0007$: 57 | inc r2 58 | 0010$: movx @dptr, a 59 | inc dptr 60 | djnz r1, 0010$ 61 | djnz r2, 0010$ 62 | 0011$: 63 | mov r1, #l_XINIT 64 | mov a, r1 65 | orl a, #(l_XINIT >> 8) 66 | jz 0023$ 67 | mov r2, #((l_XINIT+255) >> 8) 68 | mov _DPS, #0x01 69 | mov dptr, #s_XINIT 70 | dec _DPS 71 | mov dptr, #s_XISEG 72 | 0021$: clr a 73 | inc _DPS 74 | movc a, @a+dptr 75 | inc dptr 76 | dec _DPS 77 | movx @dptr, a 78 | inc dptr 79 | djnz r1, 0021$ 80 | djnz r2, 0021$ 81 | 0023$: ret 82 | .area XSEG (XDATA) 83 | .globl _xseg_end 84 | _xseg_end: 85 | .ds 1 86 | __endasm; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /kernel/app_integrated.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | #include "interface.h" 20 | static xxxx() __naked { 21 | __asm; 22 | .area CODE (CODE) 23 | .globl _CODE_HEADER 24 | _CODE_HEADER: 25 | .db 0, 0, 0, 0 // CRC will go here 26 | .db 1, 0 // len from arch to end of code - '1' signals a standalone app 27 | .db THIS_ARCH 28 | .db THIS_CODE_BASE 29 | .db 0, 0 // version (little endian) 30 | .globl _my_app 31 | ljmp _my_app 32 | .area XSEG (XDATA) 33 | .globl _xseg_end 34 | _xseg_end: 35 | .ds 1 36 | __endasm; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /kernel/dummy.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | #include "protocol.h" 20 | 21 | static void xxxx() __naked { 22 | __asm; 23 | .area CSEG (CODE) 24 | .globl _CODE_HEADER 25 | _CODE_HEADER: 26 | .db 0, 0, 0, 0 // CRC will go here 27 | .db 0, 0 // len from arch to end of code - must be 0 28 | .db THIS_ARCH 29 | .db THIS_CODE_BASE 30 | .db 0, 0 // version (little endian) 31 | clr a 32 | mov dpl, a 33 | ret 34 | .area DSEG (DATA) 35 | .globl _data_end 36 | _data_end: 37 | .ds 1 38 | .area XSEG (XDATA) 39 | .globl _xseg_end 40 | _xseg_end: 41 | .ds 1 42 | 43 | __endasm; 44 | } 45 | -------------------------------------------------------------------------------- /kernel/fixcrc.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2013 Paul Campbell paul@taniwha.com 3 | // 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) version 3, or any 9 | // later version accepted by Paul Campbell , who shall 10 | // act as a proxy defined in Section 6 of version 3 of the license. 11 | // 12 | // This library is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | // Lesser General Public License for more details. 16 | // 17 | // You should have received a copy of the GNU Lesser General Public 18 | // License along with this library. If not, see . 19 | // 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | int mn=0x10000, mx=0; 26 | unsigned char m[65536]; 27 | 28 | 29 | int 30 | hex(FILE *f) 31 | { 32 | char c1, c2; 33 | int r; 34 | c1 = fgetc(f); 35 | if (c1 < 0) 36 | return -1; 37 | c2 = fgetc(f); 38 | if (c2 < 0) 39 | return -1; 40 | if (c1 >= '0' && c1 <= '9') { 41 | r = c1-'0'; 42 | } else 43 | if (c1 >= 'A' && c1 <= 'F') { 44 | r = c1-'A'+10; 45 | } else 46 | if (c1 >= 'a' && c1 <= 'f') { 47 | r = c1-'a'+10; 48 | } else return -1; 49 | r=r<<4; 50 | if (c2 >= '0' && c2 <= '9') { 51 | r += c2-'0'; 52 | } else 53 | if (c2 >= 'A' && c2 <= 'F') { 54 | r += c2-'A'+10; 55 | } else 56 | if (c2 >= 'a' && c2 <= 'f') { 57 | r += c2-'a'+10; 58 | } else return -1; 59 | return r; 60 | } 61 | 62 | int 63 | upload(FILE *f) 64 | { 65 | memset(m, 0xff, sizeof(m)); 66 | for(;;) { 67 | int c; 68 | int i; 69 | int sum=0, len, addr; 70 | c = fgetc(f); 71 | if (c < 0) 72 | break; 73 | if (c == '\n') 74 | continue; 75 | if (c != ':') { 76 | fprintf(stderr, "bad file format\n"); 77 | fail2: 78 | return 0; 79 | } 80 | len = hex(f); 81 | if (len < 0) { 82 | fprintf(stderr, "bad file format\n"); 83 | goto fail2; 84 | } 85 | sum += len; 86 | addr = hex(f); 87 | if (addr < 0) { 88 | fprintf(stderr, "bad file format\n"); 89 | goto fail2; 90 | } 91 | sum += addr; 92 | i = hex(f); 93 | if (i < 0) { 94 | fprintf(stderr, "bad file format\n"); 95 | goto fail2; 96 | } 97 | sum += i; 98 | addr = (addr<<8)+i; 99 | int type = hex(f); 100 | if (type < 0) { 101 | fprintf(stderr, "bad file format\n"); 102 | goto fail2; 103 | } 104 | sum += type; 105 | if (type == 0x01) 106 | break; 107 | if (mn > addr) 108 | mn = addr; 109 | for (i = 0; i < len; i++) { 110 | int v = hex(f); 111 | if (v < 0) 112 | break; 113 | m[(addr+i)&0xffff] = v; 114 | sum += v; 115 | } 116 | i = hex(f); 117 | if (i < 0) { 118 | goto fail2; 119 | } 120 | if (i < 0 || i != ((0x100-(sum&0xff))&0xff)) { 121 | fprintf(stderr, "bad checksum\n"); 122 | goto fail2; 123 | } 124 | addr += len; 125 | if (addr > mx) 126 | mx = addr; 127 | } 128 | return 1; 129 | } 130 | 131 | unsigned long 132 | crc(unsigned long c, unsigned char *p, int len) 133 | { 134 | while (len--) { 135 | unsigned char v = *p++; 136 | int i; 137 | 138 | c ^= (v<<24); 139 | for (i = 0; i < 8; i++) { 140 | if (c&0x80000000) { 141 | c = (c<<1)^0x04c11db7; 142 | } else { 143 | c = (c<<1); 144 | } 145 | } 146 | } 147 | return c; 148 | } 149 | 150 | 151 | int 152 | main(int argc, char **argv) 153 | { 154 | unsigned char h[4]; 155 | unsigned char k[16]; 156 | int len; 157 | unsigned long c; 158 | int version = -1; 159 | int i; 160 | 161 | for (i = 1; i < argc; i++) { 162 | if (strcmp(argv[i], "-v") == 0 && i < argc) { 163 | i++; 164 | version = strtol(argv[i], 0, 0); 165 | } else 166 | if (strcmp(argv[i], "-k") == 0 && i < argc) { 167 | char *cp; 168 | i++; 169 | cp = argv[i]; 170 | for (i = 0; i < 16; i++) { 171 | int v; 172 | 173 | if (*cp >= '0' && *cp <= '9') { 174 | v = (*cp-'0'); 175 | } else 176 | if (*cp >= 'a' && *cp <= 'f') { 177 | v = (*cp-'a')+10; 178 | } else 179 | if (*cp >= 'A' && *cp <= 'F') { 180 | v = (*cp-'A')+10; 181 | } else { 182 | fprintf(stderr, "%s: bad key '%s'\n", argv[0], argv[i]); 183 | exit(9); 184 | } 185 | cp++; 186 | v = v<<4; 187 | if (*cp >= '0' && *cp <= '9') { 188 | v |= (*cp-'0'); 189 | } else 190 | if (*cp >= 'a' && *cp <= 'f') { 191 | v |= (*cp-'a')+10; 192 | } else 193 | if (*cp >= 'A' && *cp <= 'F') { 194 | v |= (*cp-'A')+10; 195 | } else { 196 | fprintf(stderr, "%s: bad key '%s'\n", argv[0], argv[i]); 197 | exit(9); 198 | } 199 | cp++; 200 | k[i] = v; 201 | } 202 | if (*cp) { 203 | fprintf(stderr, "%s: bad key '%s' - too long\n", argv[0], argv[i]); 204 | exit(9); 205 | } 206 | } else { 207 | fprintf(stderr, "%s: unknown flag '%s'\n", argv[0], argv[i]); 208 | exit(9); 209 | } 210 | } 211 | if (!upload(stdin) || mx <= mn) { 212 | fprintf(stderr, "unpack failed mx=%d mn=%d\n", mx, mn); 213 | exit(9); 214 | } 215 | len = mx-mn; 216 | m[mn+4] = (len-4); 217 | m[mn+5] = (len-4)>>8; 218 | if (version >= 0) { 219 | m[mn+8] = version; 220 | m[mn+9] = version>>8; 221 | } 222 | c = crc(0xffffffff, &m[mn+4], len-4); 223 | m[mn+0] = c; 224 | m[mn+1] = c>>8; 225 | m[mn+2] = c>>16; 226 | m[mn+3] = c>>24; 227 | h[0] = mn; // base addr 228 | h[1] = mn>>8; 229 | h[2] = len; // len 230 | h[3] = len>>8; 231 | fwrite(&h[0], 4, 1, stdout); 232 | fwrite(&k[0], 16, 1, stdout); 233 | fwrite(&m[mn], len, 1, stdout); 234 | exit(0); 235 | } 236 | -------------------------------------------------------------------------------- /kernel/map.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # (c) Copyright Paul Campbell paul@taniwha.com 2013 3 | # 4 | # This library is free software; you can redistribute it and/or 5 | # modify it under the terms of the GNU Lesser General Public 6 | # License as published by the Free Software Foundation; either 7 | # version 2.1 of the License, or (at your option) version 3, or any 8 | # later version accepted by Paul Campbell , who shall 9 | # act as a proxy defined in Section 6 of version 3 of the license. 10 | # 11 | # This library is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # Lesser General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public 17 | # License along with this library. If not, see . 18 | # 19 | 20 | 21 | while (<>) { 22 | 23 | # BITS 24 | # rx_crypto 25 | # rx_broadcast 26 | # key_down 27 | # _limit 28 | if (/^C:.*([0-9A-F][0-9A-F]*).*s_BSEG .*$/ ) { 29 | $bs = hex($1); 30 | } 31 | if (/^C:.*([0-9A-F][0-9A-F]*).*l_BSEG .*$/ ) { 32 | $bl = hex($1); 33 | } 34 | 35 | # DATA 36 | # rtx_key 37 | if (/^ *([0-9A-F][0-9A-F]*) *_rtx_key .*$/ ) { 38 | printf STDOUT "-g _rtx_key=0x%x\n", hex($1); 39 | } 40 | # rx_mac 41 | if (/^ *([0-9A-F][0-9A-F]*) *_rx_mac .*$/ ) { 42 | printf STDOUT "-g _rx_mac=0x%x\n", hex($1); 43 | } 44 | # rx_len 45 | if (/^ *([0-9A-F][0-9A-F]*) *_rx_len .*$/ ) { 46 | printf STDOUT "-g _rx_len=0x%x\n", hex($1); 47 | } 48 | # rx_packet 49 | if (/^ *([0-9A-F][0-9A-F]*) *_rx_packet .*$/ ) { 50 | printf STDOUT "-g _rx_packet=0x%x\n", hex($1); 51 | } 52 | # _limit 53 | if (/^ *([0-9A-F][0-9A-F]*) *_data_end .*$/ ) { 54 | printf STDOUT "-b DSEG=0x%x\n", hex($1); 55 | } 56 | 57 | 58 | # CODE 59 | # leds_rgb 60 | if (/^C: *([0-9A-F][0-9A-F]*) *_leds_rgb .*$/ ) { 61 | printf STDOUT "-g _leds_rgb=0x%x\n", hex($1); 62 | } 63 | # leds_off 64 | if (/^C: *([0-9A-F][0-9A-F]*) *_leds_off .*$/ ) { 65 | printf STDOUT "-g _leds_off=0x%x\n", hex($1); 66 | } 67 | # rf_receive_on 68 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_receive_on .*$/ ) { 69 | printf STDOUT "-g _rf_receive_on=0x%x\n", hex($1); 70 | } 71 | # rf_receive_off 72 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_receive_off .*$/ ) { 73 | printf STDOUT "-g _rf_receive_off=0x%x\n", hex($1); 74 | } 75 | # rf_set_channel 76 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_set_channel .*$/ ) { 77 | printf STDOUT "-g _rf_set_channel=0x%x\n", hex($1); 78 | } 79 | # rf_set_key_c 80 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_set_key_c .*$/ ) { 81 | printf STDOUT "-g _rf_set_key_c=0x%x\n", hex($1); 82 | } 83 | # rf_set_key 84 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_set_key .*$/ ) { 85 | printf STDOUT "-g _rf_set_key=0x%x\n", hex($1); 86 | } 87 | # rf_set_mac 88 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_set_mac .*$/ ) { 89 | printf STDOUT "-g _rf_set_mac=0x%x\n", hex($1); 90 | } 91 | # rf_send 92 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_send .*$/ ) { 93 | printf STDOUT "-g _rf_send=0x%x\n", hex($1); 94 | } 95 | if (/^D: *([0-9A-F][0-9A-F]*) *_rf_send_PARM_2 .*$/ ) { 96 | printf STDOUT "-g _rf_send_PARM_2=0x%x\n", hex($1); 97 | } 98 | if (/^D: *([0-9A-F][0-9A-F]*) *_rf_send_PARM_3 .*$/ ) { 99 | printf STDOUT "-g _rf_send_PARM_3=0x%x\n", hex($1); 100 | } 101 | if (/^D: *([0-9A-F][0-9A-F]*) *_rf_send_PARM_4 .*$/ ) { 102 | printf STDOUT "-g _rf_send_PARM_4=0x%x\n", hex($1); 103 | } 104 | # rf_set_transmit_power 105 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_set_transmit_power .*$/ ) { 106 | printf STDOUT "-g _rf_set_transmit_power=0x%x\n", hex($1); 107 | } 108 | # rf_set_promiscuous 109 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_set_promiscuous .*$/ ) { 110 | printf STDOUT "-g _rf_set_promiscuous=0x%x\n", hex($1); 111 | } 112 | # rf_set_raw 113 | if (/^C: *([0-9A-F][0-9A-F]*) *_rf_set_raw .*$/ ) { 114 | printf STDOUT "-g _rf_set_raw=0x%x\n", hex($1); 115 | } 116 | # daylight 117 | if (/^C: *([0-9A-F][0-9A-F]*) *_daylight .*$/ ) { 118 | printf STDOUT "-g _daylight=0x%x\n", hex($1); 119 | } 120 | # keys_on 121 | if (/^C: *([0-9A-F][0-9A-F]*) *_keys_on .*$/ ) { 122 | printf STDOUT "-g _keys_on=0x%x\n", hex($1); 123 | } 124 | # keys_off 125 | if (/^C: *([0-9A-F][0-9A-F]*) *_keys_off .*$/ ) { 126 | printf STDOUT "-g _keys_off=0x%x\n", hex($1); 127 | } 128 | # uart_init 129 | if (/^C: *([0-9A-F][0-9A-F]*) *_uart_init .*$/ ) { 130 | printf STDOUT "-g _uart_init=0x%x\n", hex($1); 131 | } 132 | # putchar 133 | if (/^C: *([0-9A-F][0-9A-F]*) *_putchar .*$/ ) { 134 | printf STDOUT "-g _putchar=0x%x\n", hex($1); 135 | } 136 | # system_attributes 137 | if (/^C: *([0-9A-F][0-9A-F]*) *_system_attributes .*$/ ) { 138 | printf STDOUT "-g _system_attributes=0x%x\n", hex($1); 139 | } 140 | # putstr 141 | if (/^C: *([0-9A-F][0-9A-F]*) *_putstr .*$/ ) { 142 | printf STDOUT "-g _putstr=0x%x\n", hex($1); 143 | } 144 | # puthex 145 | if (/^C: *([0-9A-F][0-9A-F]*) *_puthex .*$/ ) { 146 | printf STDOUT "-g _puthex=0x%x\n", hex($1); 147 | } 148 | # queue_task 149 | if (/^C: *([0-9A-F][0-9A-F]*) *_queue_task .*$/ ) { 150 | printf STDOUT "-g _queue_task=0x%x\n", hex($1); 151 | } 152 | if (/^D: *([0-9A-F][0-9A-F]*) *_queue_task_PARM_2 .*$/ ) { 153 | printf STDOUT "-g _queue_task_PARM_2=0x%x\n", hex($1); 154 | } 155 | # cancel_task 156 | if (/^C: *([0-9A-F][0-9A-F]*) *_cancel_task .*$/ ) { 157 | printf STDOUT "-g _cancel_task=0x%x\n", hex($1); 158 | } 159 | # wait_us 160 | if (/^C: *([0-9A-F][0-9A-F]*) *_wait_us .*$/ ) { 161 | printf STDOUT "-g _wait_us=0x%x\n", hex($1); 162 | } 163 | # _limit 164 | 165 | # PDATA 166 | # key 167 | if (/^D: *([0-9A-F][0-9A-F]*) *_key .*$/ ) { 168 | printf STDOUT "-g _key=0x%x\n", hex($1); 169 | } 170 | # uart_rx_0_vect 171 | if (/^D: *([0-9A-F][0-9A-F]*) *_uart_rx_0_vect .*$/ ) { 172 | printf STDOUT "-g _uart_rx_0_vect=0x%x\n", hex($1); 173 | } 174 | # uart_rx_1_vect 175 | if (/^D: *([0-9A-F][0-9A-F]*) *_uart_rx_1_vect .*$/ ) { 176 | printf STDOUT "-g _uart_rx_1_vect=0x%x\n", hex($1); 177 | } 178 | # uart_tx_0_vect 179 | if (/^D: *([0-9A-F][0-9A-F]*) *_uart_tx_0_vect .*$/ ) { 180 | printf STDOUT "-g _uart_tx_0_vect=0x%x\n", hex($1); 181 | } 182 | # uart_tx_1_vect 183 | if (/^D: *([0-9A-F][0-9A-F]*) *_uart_tx_1_vect .*$/ ) { 184 | printf STDOUT "-g _uart_tx_1_vect=0x%x\n", hex($1); 185 | } 186 | # p0_vect 187 | if (/^D: *([0-9A-F][0-9A-F]*) *_p0_vect .*$/ ) { 188 | printf STDOUT "-g _p0_vect=0x%x\n", hex($1); 189 | } 190 | # p1_vect 191 | if (/^D: *([0-9A-F][0-9A-F]*) *_p1_vect .*$/ ) { 192 | printf STDOUT "-g _p1_vect=0x%x\n", hex($1); 193 | } 194 | # p2_vect 195 | if (/^D: *([0-9A-F][0-9A-F]*) *_p2_vect .*$/ ) { 196 | printf STDOUT "-g _p2_vect=0x%x\n", hex($1); 197 | } 198 | # t2_vect 199 | if (/^D: *([0-9A-F][0-9A-F]*) *_t2_vect .*$/ ) { 200 | printf STDOUT "-g _t2_vect=0x%x\n", hex($1); 201 | } 202 | # t3_vect 203 | if (/^D: *([0-9A-F][0-9A-F]*) *_t3_vect .*$/ ) { 204 | printf STDOUT "-g _t3_vect=0x%x\n", hex($1); 205 | } 206 | # t4_vect 207 | if (/^D: *([0-9A-F][0-9A-F]*) *_t4_vect .*$/ ) { 208 | printf STDOUT "-g _t4_vect=0x%x\n", hex($1); 209 | } 210 | # adc_vect 211 | if (/^D: *([0-9A-F][0-9A-F]*) *_adc_vect .*$/ ) { 212 | printf STDOUT "-g _adc_vect=0x%x\n", hex($1); 213 | } 214 | # aec_vect 215 | if (/^D: *([0-9A-F][0-9A-F]*) *_aec_vect .*$/ ) { 216 | printf STDOUT "-g _aec_vect=0x%x\n", hex($1); 217 | } 218 | # dma_vect 219 | if (/^D: *([0-9A-F][0-9A-F]*) *_dma_vect .*$/ ) { 220 | printf STDOUT "-g _dma_vect=0x%x\n", hex($1); 221 | } 222 | # _limit 223 | if (/^C: *([0-9A-F][0-9A-F]*) *l_PSEG.*$/ ) { 224 | printf STDOUT "-b PSEG=0x%x\n", hex($1); 225 | } 226 | 227 | # XDATA 228 | # _limit 229 | # if (/^D: *([0-9A-F][0-9A-F]*) *_xseg_end.*$/ ) { 230 | # printf STDOUT "-b XSEG=0x%x\n", hex($1); 231 | # } 232 | if (/^C: *([0-9A-F][0-9A-F]*) *s_XISEG.*$/ ) { 233 | $a=hex($1); 234 | } 235 | if (/^C: *([0-9A-F][0-9A-F]*) *l_XISEG.*$/ ) { 236 | $b=hex($1); 237 | } 238 | 239 | } 240 | printf STDOUT "-b xSEG=0x%x\n", $a+$b; 241 | printf STDOUT "-b BSEG=0x%x\n", $bs+$bl; 242 | printf STDOUT "-e\n"; 243 | 244 | -------------------------------------------------------------------------------- /kernel/syms.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | void ____x___() __naked 20 | { 21 | __asm; 22 | .globl _rx_len 23 | .globl _rx_packet 24 | .globl _rx_mac 25 | .globl _rtx_key 26 | .globl _uart_rx_0_vect 27 | .globl _uart_rx_1_vect 28 | .globl _uart_tx_0_vect 29 | .globl _uart_tx_1_vect 30 | .globl _p0_vect 31 | .globl _p1_vect 32 | .globl _p2_vect 33 | .globl _t2_vect 34 | .globl _t3_vect 35 | .globl _t4_vect 36 | .globl _adc_vect 37 | .globl _aec_vect 38 | .globl _dma_vect 39 | .globl _queue_task_PARM_2 40 | .globl _rf_send_PARM_2 41 | .globl _rf_send_PARM_3 42 | .globl _rf_send_PARM_4 43 | #ifdef DRV_KEYS 44 | .globl _key 45 | #endif 46 | #ifdef DRV_DAYLIGHT 47 | .globl _daylight 48 | #endif 49 | .globl _putchar 50 | .globl _putstr 51 | .globl _puthex 52 | .globl _wait_us 53 | .globl _queue_task 54 | .globl _cancel_task 55 | .globl _uart_init 56 | .globl _rf_set_key 57 | .globl _rf_set_key_c 58 | .globl _rf_set_promiscuous 59 | .globl _rf_set_raw 60 | .globl _rf_set_mac 61 | .globl _rf_set_channel 62 | .globl _rf_set_transmit_power 63 | .globl _rf_receive_on 64 | .globl _rf_receive_off 65 | .globl _rf_send 66 | #ifdef DRV_LEDS 67 | .globl _leds_off 68 | .globl _leds_rgb 69 | #endif 70 | #ifdef DRV_KEYS 71 | .globl _keys_off 72 | #endif 73 | .globl _system_attributes 74 | #ifdef DRV_KEYS 75 | .globl _keys_on 76 | #endif 77 | .area CSEG (CODE) 78 | .globl __2 79 | __2=_rx_len 80 | .globl __3 81 | __3=_rx_packet 82 | .globl __4 83 | __4=_rx_mac 84 | .globl __5 85 | __5=_rtx_key 86 | .globl __6 87 | __6=_uart_rx_0_vect 88 | .globl __7 89 | __7=_uart_rx_1_vect 90 | .globl __8 91 | __8=_uart_tx_0_vect 92 | .globl __9 93 | __9=_uart_tx_1_vect 94 | .globl __10 95 | __10=_p0_vect 96 | .globl __11 97 | __11=_p1_vect 98 | .globl __12 99 | __12=_p2_vect 100 | .globl __13 101 | __13=_t2_vect 102 | .globl __14 103 | __14=_t3_vect 104 | .globl __15 105 | __15=_t4_vect 106 | .globl __16 107 | __16=_adc_vect 108 | .globl __17 109 | __17=_aec_vect 110 | .globl __18 111 | __18=_dma_vect 112 | .globl __19 113 | __19=_queue_task_PARM_2 114 | .globl __20 115 | __20=_rf_send_PARM_2 116 | .globl __21 117 | __21=_rf_send_PARM_3 118 | .globl __22 119 | __22=_rf_send_PARM_4 120 | #ifdef DRV_KEYS 121 | .globl __23 122 | __23=_key 123 | #endif 124 | #ifdef DRV_DAYLIGHT 125 | .globl __24 126 | __24=_daylight 127 | #endif 128 | .globl __25 129 | __25=_putchar 130 | .globl __26 131 | __26=_putstr 132 | .globl __27 133 | __27=_puthex 134 | .globl __28 135 | __28=_wait_us 136 | .globl __29 137 | __29=_queue_task 138 | .globl __30 139 | __30=_cancel_task 140 | .globl __31 141 | __31=_uart_init 142 | .globl __32 143 | __32=_rf_set_key 144 | .globl __33 145 | __33=_rf_set_promiscuous 146 | .globl __34 147 | __34=_rf_set_raw 148 | .globl __35 149 | __35=_rf_set_mac 150 | .globl __36 151 | __36=_rf_set_channel 152 | .globl __37 153 | __37=_rf_set_transmit_power 154 | .globl __38 155 | __38=_rf_receive_on 156 | .globl __39 157 | __39=_rf_receive_off 158 | .globl __40 159 | __40=_rf_send 160 | #ifdef DRV_LEDS 161 | .globl __41 162 | __41=_leds_off 163 | .globl __42 164 | __42=_leds_rgb 165 | #endif 166 | #ifdef DRV_KEYS 167 | .globl __43 168 | __43=_keys_off 169 | .globl __44 170 | __44=_keys_on 171 | .globl __45 172 | #endif 173 | __45=_system_attributes 174 | .globl __46 175 | __46=_rf_set_key_c 176 | .globl __33 177 | __endasm; 178 | } 179 | -------------------------------------------------------------------------------- /kernel/task.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | //#define TDEBUG 20 | //#define XMT 21 | #include 22 | #include 23 | #include "task.h" 24 | #include "interface.h" 25 | 26 | extern __bit inSuspend; 27 | static task __xdata * __data waitq; 28 | volatile u8 __data enter_sleep_mod_flag; 29 | void putstr(char __code *cp); 30 | #define radio_busy 1 31 | extern void idle_pool(); 32 | 33 | static unsigned char dummy_app(u8 v) { return 0; } 34 | unsigned char (* __data x_app) (u8 v) = dummy_app; 35 | 36 | static unsigned int __data last; 37 | static unsigned char __data tmp0; 38 | static unsigned char __data tmp1; 39 | 40 | //extern __bit rx_active; 41 | 42 | #ifndef SYSTEM_ATTRIBUTES 43 | #define SYSTEM_ATTRIBUTES 0 44 | #endif 45 | unsigned char __code system_attributes=SYSTEM_ATTRIBUTES; 46 | 47 | static void 48 | iretx() __naked 49 | { 50 | __asm; 51 | reti 52 | __endasm; 53 | } 54 | 55 | u8 app(u8 v) __naked 56 | { 57 | __asm; 58 | push _x_app 59 | push _x_app+1 60 | ret 61 | __endasm; 62 | } 63 | 64 | static u8 __data isr_save0; 65 | static u8 __data isr_save1; 66 | extern void sleep(); 67 | //extern void rf_err_isr() __interrupt(0); 68 | #ifdef DRV_KEYS 69 | extern void t1_isr() __interrupt(9); 70 | extern void keys_on(); 71 | #else 72 | void (* __pdata t1_vect) () = iretx; 73 | void t1_isr() __interrupt(9) __naked 74 | { 75 | __asm; 76 | mov _isr_save0, r0 77 | mov r0, #_t1_vect 78 | sjmp do_isr 79 | __endasm; 80 | } 81 | #endif 82 | 83 | void (* __pdata uart_rx_0_vect) () = iretx; 84 | void (* __pdata uart_rx_1_vect) () = iretx; 85 | void (* __pdata uart_tx_0_vect) () = iretx; 86 | void (* __pdata uart_tx_1_vect) () = iretx; 87 | void (* __pdata p0_vect) () = iretx; 88 | void (* __pdata p1_vect) () = iretx; 89 | void (* __pdata p2_vect) () = iretx; 90 | void (* __pdata t2_vect) () = iretx; 91 | void (* __pdata t3_vect) () = iretx; 92 | void (* __pdata t4_vect) () = iretx; 93 | void (* __pdata adc_vect) () = iretx; 94 | void (* __pdata aec_vect) () = iretx; 95 | void (* __pdata dma_vect) () = iretx; 96 | void uart_rx_0_isr() __interrupt(2) __naked 97 | { 98 | __asm; 99 | mov _isr_save0, r0 100 | mov r0, #_uart_rx_0_vect 101 | do_isr: mov _isr_save1, a 102 | movx a, @r0 103 | push acc 104 | inc r0 105 | movx a, @r0 106 | push acc 107 | mov r0, _isr_save0 108 | mov a, _isr_save1 109 | 110 | ret 111 | __endasm; 112 | } 113 | void uart_rx_1_isr() __interrupt(3) __naked 114 | { 115 | __asm; 116 | mov _isr_save0, r0 117 | mov r0, #_uart_rx_1_vect 118 | sjmp do_isr 119 | __endasm; 120 | } 121 | void uart_tx_0_isr() __interrupt(7) __naked 122 | { 123 | __asm; 124 | mov _isr_save0, r0 125 | mov r0, #_uart_tx_0_vect 126 | sjmp do_isr 127 | __endasm; 128 | } 129 | void uart_tx_1_isr() __interrupt(14) __naked 130 | { 131 | __asm; 132 | mov _isr_save0, r0 133 | mov r0, #_uart_tx_1_vect 134 | sjmp do_isr 135 | __endasm; 136 | } 137 | void p0_isr() __interrupt(13) __naked 138 | { 139 | __asm; 140 | mov _isr_save0, r0 141 | mov r0, #_p0_vect 142 | sjmp do_isr 143 | __endasm; 144 | } 145 | void p1_isr() __interrupt(15) __naked 146 | { 147 | __asm; 148 | mov _isr_save0, r0 149 | mov r0, #_p1_vect 150 | sjmp do_isr 151 | __endasm; 152 | } 153 | void p2_isr() __interrupt(6) __naked 154 | { 155 | __asm; 156 | mov _isr_save0, r0 157 | mov r0, #_p2_vect 158 | sjmp do_isr 159 | __endasm; 160 | } 161 | void t2_isr() __interrupt(10) __naked 162 | { 163 | __asm; 164 | mov _isr_save0, r0 165 | mov r0, #_t2_vect 166 | sjmp do_isr 167 | __endasm; 168 | } 169 | void t3_isr() __interrupt(11) __naked 170 | { 171 | __asm; 172 | mov _isr_save0, r0 173 | mov r0, #_t3_vect 174 | sjmp do_isr 175 | __endasm; 176 | } 177 | void t4_isr() __interrupt(12) __naked 178 | { 179 | __asm; 180 | mov _isr_save0, r0 181 | mov r0, #_t4_vect 182 | sjmp do_isr 183 | __endasm; 184 | } 185 | void adc_isr() __interrupt(1) __naked 186 | { 187 | __asm; 188 | mov _isr_save0, r0 189 | mov r0, #_adc_vect 190 | sjmp do_isr 191 | __endasm; 192 | } 193 | void aec_isr() __interrupt(4) __naked 194 | { 195 | __asm; 196 | mov _isr_save0, r0 197 | mov r0, #_aec_vect 198 | sjmp do_isr 199 | __endasm; 200 | } 201 | void dma_isr() __interrupt(8) __naked 202 | { 203 | __asm; 204 | mov _isr_save0, r0 205 | mov r0, #_dma_vect 206 | sjmp do_isr 207 | __endasm; 208 | } 209 | 210 | #ifdef DRV_DAYLIGHT 211 | unsigned char 212 | daylight() __naked 213 | { 214 | __asm; 215 | clr a 216 | jb P0.7, 0001$ 217 | inc a 218 | 0001$: 219 | mov dpl, a 220 | ret 221 | __endasm; 222 | } 223 | #endif 224 | 225 | static void 226 | xxxx_sleep() __naked 227 | { 228 | __asm; 229 | .odd 230 | _sleep: 231 | mov PCON, _enter_sleep_mod_flag 232 | nop 233 | ret 234 | __endasm; 235 | } 236 | void 237 | start_timer(unsigned int v) __naked 238 | { 239 | __asm; 240 | mov a, _ST0 241 | mov b, a 242 | mov a, _ST1 243 | mov _last, a 244 | add a, dpl 245 | mov dpl, a 246 | mov a, _ST2 247 | mov _last+1, a 248 | addc a, dph 249 | mov dph, a 250 | xxx: mov a, _STLOAD 251 | jnb a.0, xxx 252 | mov _ST2, dph 253 | mov _ST1, dpl 254 | mov a, b 255 | mov _ST0, a 256 | setb _STIE 257 | ret 258 | __endasm; 259 | } 260 | 261 | unsigned int 262 | get_timer() __naked 263 | { 264 | __asm; 265 | mov a, _ST0 266 | mov dpl, _ST1 267 | mov dph, _ST2 268 | ret 269 | __endasm; 270 | } 271 | 272 | unsigned int 273 | stop_timer() __naked 274 | { 275 | __asm; 276 | clr _STIE 277 | mov a, _ST0 278 | clr c 279 | mov a, _ST1 280 | subb a, _last 281 | mov dpl, a 282 | mov a, _ST2 283 | subb a, _last+1 284 | mov dph, a 285 | ret 286 | __endasm; 287 | } 288 | 289 | unsigned int 290 | save_timer() __naked 291 | { 292 | __asm; 293 | mov a, _ST0 294 | clr c 295 | mov a, _ST1 296 | mov r0, a 297 | subb a, _last 298 | mov dpl, a 299 | mov _last, r0 300 | mov a, _ST2 301 | mov r0, a 302 | subb a, _last+1 303 | mov dph, a 304 | mov _last+1, r0 305 | ret 306 | __endasm; 307 | } 308 | 309 | void sleep_isr() __interrupt(5) __naked 310 | { 311 | __asm; 312 | clr _STIE 313 | clr _STIF 314 | mov _enter_sleep_mod_flag, #0 315 | reti 316 | __endasm; 317 | } 318 | 319 | void putchar(char c) __naked 320 | { 321 | __asm; 322 | push ACC 323 | mov _U0DBUF, dpl // U0DBUF = c; 324 | 0004$: mov a, _U0CSR 325 | jb _ACC_0, 0004$ 326 | pop ACC 327 | ret 328 | __endasm; 329 | } 330 | void 331 | putstr(char __code *cp) __naked 332 | { 333 | __asm; 334 | 0001$: // for (;;) { 335 | clr a 336 | movc a, @a+dptr// // c = *cp++; 337 | inc dptr 338 | jnz 0002$ // if (!c) break; 339 | ret 340 | 0002$: cjne a, #'\n', 0003$ // if (*cp == '\n') { 341 | mov _U0DBUF, #13 // U0DBUF = 13; 342 | 0004$: mov a, _U0CSR 343 | jb _ACC_0, 0004$ 344 | mov _U0DBUF, #10 // U0DBUF = 10; 345 | 0014$: mov a, _U0CSR 346 | jb _ACC_0, 0014$ 347 | sjmp 0001$ 348 | 0003$: // } else { 349 | mov _U0DBUF, a // U0DBUF = c; 350 | 0034$: mov a, _U0CSR 351 | jb _ACC_0, 0034$ 352 | sjmp 0001$ // } 353 | __endasm; // } 354 | } 355 | void 356 | puthex(unsigned char v) __naked 357 | { 358 | __asm; 359 | mov a, dpl 360 | swap a 361 | anl a, #0xf // i = (v>>4)&0xf; 362 | cjne a, #9, 0001$ // if (i <= 9) { 363 | 0002$: 364 | add a, #'0' // i += '0' 365 | 366 | sjmp 0003$ // } else { 367 | 0001$: jc 0002$ 368 | add a, #'a'-10// i += 'a'-10 369 | // } 370 | 0003$: mov _U0DBUF, a // putchar(i); 371 | 0094$: mov a, _U0CSR 372 | jb _ACC_0, 0094$ 373 | 374 | 0024$: 375 | mov a, dpl 376 | anl a, #0xf // i = v&0xf; 377 | cjne a, #9, 0011$ // if (i <= 9) { 378 | 0012$: 379 | add a, #'0' // i += '0' 380 | 381 | sjmp 0013$ // } else { 382 | 0011$: jc 0012$ 383 | add a, #'a'-10// i += 'a'-10 384 | // } 385 | 0013$: mov _U0DBUF, a // putchar(i); 386 | 0084$: mov a, _U0CSR 387 | jb _ACC_0, 0084$ 388 | ret 389 | __endasm; 390 | } 391 | 392 | void dump_wait_list(char __code *cp) __naked 393 | { 394 | #ifdef TDEBUG 395 | __asm; 396 | lcall _putstr 397 | mov dpl, _waitq 398 | mov dph, _waitq+1 399 | 0001$: 400 | mov a, dpl 401 | orl a, dph 402 | jnz 0002$ 403 | mov _U0DBUF, #13 404 | 0032$: mov a, _U0CSR 405 | jb _ACC_0, 0032$ 406 | mov _U0DBUF, #10 407 | 0033$: mov a, _U0CSR 408 | jb _ACC_0, 0033$ 409 | ret 410 | 0002$: push dpl 411 | push dph 412 | push dpl 413 | mov _U0DBUF, #'(' 414 | 0034$: mov a, _U0CSR 415 | jb _ACC_0, 0034$ 416 | mov dpl, dph 417 | lcall _puthex 418 | pop dpl 419 | lcall _puthex 420 | mov _U0DBUF, #',' 421 | 0035$: mov a, _U0CSR 422 | jb _ACC_0, 0035$ 423 | 424 | // pop dph 425 | // pop dpl 426 | // push dpl 427 | // push dph 428 | // movx a, @dptr 429 | // push acc 430 | // inc dptr 431 | // movx a, @dptr 432 | // mov dpl, a 433 | // lcall _puthex 434 | // pop dpl 435 | // lcall _puthex 436 | // 437 | // mov _U0DBUF, #',' 438 | //0135$: mov a, _U0CSR 439 | // jb _ACC_0, 0135$ 440 | 441 | pop dph 442 | pop dpl 443 | inc dptr 444 | inc dptr 445 | movx a, @dptr 446 | inc dptr 447 | push acc 448 | movx a, @dptr 449 | inc dptr 450 | push dpl 451 | push dph 452 | mov dpl, a 453 | lcall _puthex 454 | pop dph 455 | pop dpl 456 | pop acc 457 | push dpl 458 | push dph 459 | mov dpl, a 460 | lcall _puthex 461 | pop dph 462 | pop dpl 463 | mov _U0DBUF, #')' 464 | 0036$: mov a, _U0CSR 465 | jb _ACC_0, 0036$ 466 | movx a, @dptr 467 | push acc 468 | inc dptr 469 | movx a, @dptr 470 | mov dph, a 471 | pop dpl 472 | ljmp 0001$ 473 | __endasm; 474 | #endif 475 | } 476 | 477 | void 478 | wait_us(unsigned char t) 479 | { 480 | while (t--) { 481 | __asm 482 | nop 483 | nop 484 | nop 485 | nop 486 | nop 487 | nop 488 | nop 489 | nop 490 | __endasm; 491 | } 492 | } 493 | 494 | void queue_task_0(task __xdata * t) __naked // for ISRs - save param so we don't trash global 495 | { 496 | __asm; 497 | mov r0, #_queue_task_PARM_2 498 | movx a, @r0 499 | push ACC 500 | clr a 501 | movx @r0, a 502 | inc r0 503 | movx a, @r0 504 | push ACC 505 | clr a 506 | movx @r0, a 507 | acall _queue_task 508 | mov r0, #_queue_task_PARM_2+1 509 | pop ACC 510 | movx @r0, a 511 | dec r0 512 | pop ACC 513 | movx @r0, a 514 | ret 515 | __endasm; 516 | } 517 | 518 | void 519 | queue_task(task __xdata * t, unsigned int time) __naked 520 | { 521 | __asm; 522 | #ifdef TDEBUG 523 | push dpl 524 | push dph 525 | push dpl 526 | push dph 527 | movx a, @dptr 528 | push acc 529 | inc dptr 530 | movx a, @dptr 531 | push acc 532 | sjmp 0101$ 533 | 0102$: .ascii "queue " 534 | .db 0 535 | 0103$: .ascii " " 536 | .db 0 537 | 0101$: mov dptr, #0102$ 538 | lcall _putstr 539 | pop dpl 540 | lcall _puthex 541 | pop dpl 542 | lcall _puthex 543 | mov dpl, #' ' 544 | lcall _putchar 545 | pop dpl 546 | lcall _puthex 547 | pop dpl 548 | lcall _puthex 549 | 550 | mov dpl, #' ' 551 | lcall _putchar 552 | mov r0, #_queue_task_PARM_2+1 553 | movx a, @r0 554 | mov dpl, a 555 | lcall _puthex 556 | mov r0, #_queue_task_PARM_2 557 | movx a, @r0 558 | mov dpl, a 559 | lcall _puthex 560 | mov dptr, #0103$ 561 | lcall _dump_wait_list 562 | pop dph 563 | pop dpl 564 | #endif 565 | mov r4, dpl 566 | mov r5, dph // t 567 | push _IEN0 568 | clr EA 569 | acall _save_timer// delta = stop_timer() 570 | mov a, dpl // delta 571 | mov r6, a 572 | mov r7, dph 573 | #ifdef TDEBUG 574 | push acc 575 | lcall xlog6 576 | pop acc 577 | #endif 578 | mov _enter_sleep_mod_flag, #0 // enter_sleep_mod_flag = 0; 579 | // for (pt = waitq; delta && pt; pt = pt->next) { 580 | // if (pt->time > delta) { 581 | // pt->time -= delta; 582 | // break; 583 | // } 584 | // delta -= pt->time; 585 | // pt->time = 0; 586 | // enter_sleep_mod_flag = 0; 587 | // } 588 | orl a, r7 // for (;;) { 589 | jz qt_2 // if (!delta) break 590 | mov a, _waitq 591 | mov dpl, a 592 | mov dph, _waitq+1 593 | orl a, dph 594 | jz qt_2 595 | qt_1: // a contains dpl 596 | inc dptr 597 | inc dptr // points at time 598 | movx a, @dptr 599 | mov _DPL1, dpl 600 | mov _DPH1, dph 601 | clr c 602 | subb a, r6 603 | mov r2, a 604 | inc dptr 605 | movx a, @dptr 606 | subb a, r7 607 | inc _DPS 608 | jc qt_3 // if (pt->time > delta) 609 | mov r0, a // pt->time -= delta; 610 | mov a, r2 611 | movx @dptr, a 612 | inc dptr 613 | mov a, r0 614 | movx @dptr, a 615 | dec _DPS 616 | sjmp qt_2 617 | qt_3: mov r3, a 618 | clr a // pt->time = 0; 619 | movx @dptr, a 620 | inc dptr 621 | movx @dptr, a 622 | inc dptr 623 | 624 | //mov _enter_sleep_mod_flag, #0 // enter_sleep_mod_flag = 0; 625 | subb a, r2 // delta -= pt->time; 626 | mov r6, a 627 | clr a 628 | subb a, r3 629 | mov r7, a 630 | movx a, @dptr// pt = pt->next 631 | mov r0, a 632 | inc dptr 633 | mov _DPL0, a 634 | movx a, @dptr 635 | mov _DPH0, a 636 | dec _DPS 637 | orl a, r0 // if pt == null break 638 | jz qt_2 639 | mov a, r6 640 | orl a, r7 641 | jnz qt_1 642 | qt_2: 643 | // if (t->state == TASK_QUEUED) { 644 | // t->state = TASK_IDLE; 645 | // pt = waitq; 646 | // ptp = &waitq; 647 | // for (;;) { 648 | // if (pt == t) { 649 | // if ((*ptp = pt = t->next) != 0) 650 | // pt->time += t->time; 651 | // break; 652 | // } 653 | // ptp = &pt->next; 654 | // pt = *ptp; 655 | // } 656 | // } 657 | 658 | mov a, r4 // if (t->state == TASK_QUEUED) 659 | add a, #6 660 | mov dpl, a 661 | mov a, r5 662 | addc a, #0 663 | mov dph, a 664 | movx a, @dptr 665 | cjne a, #TASK_QUEUED, qt_4 666 | mov a, #TASK_IDLE // t->state = TASK_IDLE; 667 | movx @dptr, a 668 | mov r2, #0 669 | mov r0, _waitq // for (pt = waitq;;) { 670 | mov r1, _waitq+1 671 | qt_5: 672 | mov a, r0 // if (pt == t) { 673 | cjne a, ar4, qt_6 674 | mov a, r1 675 | cjne a, ar5, qt_6 676 | mov dpl, r4 677 | mov dph, r5 678 | inc dptr 679 | inc dptr 680 | movx a, @dptr // r1:r0 = t->time 681 | inc dptr 682 | mov r0, a 683 | movx a, @dptr 684 | inc dptr 685 | mov r1, a 686 | 687 | movx a, @dptr // pt = dptr0 = t->next 688 | inc dptr 689 | mov r3, a 690 | movx a, @dptr 691 | mov dph, a 692 | mov dpl, r3 693 | 694 | cjne r2, #0, qt_8 // if (prev) 695 | //mov _enter_sleep_mod_flag, #0 // enter_sleep_mod_flag = 0; 696 | mov _waitq, dpl // waitq = dptr0 697 | mov _waitq+1, dph 698 | sjmp qt_9 // else 699 | qt_8: 700 | inc _DPS 701 | mov a, _DPL0 // prev->next = dptr0 702 | movx @dptr, a 703 | inc dptr 704 | mov a, _DPH0 705 | movx @dptr, a 706 | dec _DPS 707 | qt_9: 708 | mov a, dpl 709 | orl a, dph 710 | jz qt_4 711 | inc dptr 712 | inc dptr 713 | movx a, @dptr // pt->time += t->time; 714 | add a, r0 715 | movx @dptr, a 716 | inc dptr 717 | movx a, @dptr 718 | addc a, r1 719 | movx @dptr, a 720 | sjmp qt_4 721 | 722 | qt_6: 723 | mov r2, #1 724 | mov dpl, r0 725 | mov dph, r1 726 | inc dptr 727 | inc dptr 728 | inc dptr 729 | inc dptr 730 | mov _DPL1, dpl // prev = pt 731 | mov _DPH1, dph 732 | movx a, @dptr // pt = pt->next 733 | mov r0, a 734 | inc dptr 735 | movx a, @dptr //} 736 | mov r1, a 737 | sjmp qt_5 738 | qt_4: 739 | // ptp = &waitq; 740 | // pt = waitq; 741 | // for (;;) { 742 | // while (pt && pt->time == 0) { 743 | // ptp = &pt->next; 744 | // pt = *ptp; 745 | // } 746 | // if (!pt) { 747 | // t->time = time; 748 | // t->next = 0; 749 | // t->state = TASK_QUEUED; 750 | // *ptp = t; 751 | // break; 752 | // } 753 | // if (pt->time <= time) { 754 | // time -= pt->time; 755 | // ptp = &pt->next; 756 | // pt = *ptp; 757 | // continue; 758 | // } 759 | // pt->time -= time; 760 | // t->time = time; 761 | // t->next = pt; 762 | // *ptp = t; 763 | // t->state = TASK_QUEUED; 764 | // break; 765 | // } 766 | mov dpl, _waitq // pt = waitq 767 | mov dph, _waitq+1 768 | mov r2, #0 // prev marked invalid 769 | qt_11: // for (;;) { 770 | mov r6, dpl // save pt in r7:r6 771 | mov r7, dph 772 | mov a, r6 // 773 | orl a, r7 // if (!pt) break; 774 | jz qt_12 775 | 776 | 777 | inc dptr // if (pt->time != 0) break; 778 | inc dptr 779 | movx a, @dptr 780 | mov r3, a 781 | inc dptr 782 | movx a, @dptr 783 | orl a, r3 784 | jnz qt_13 785 | 786 | mov r2, #1 // mark prev valid 787 | inc dptr 788 | mov _DPL1, dpl // prev = &pt->next 789 | mov _DPH1, dph 790 | movx a, @dptr // pt = pt->next 791 | mov r3, a 792 | inc dptr 793 | movx a, @dptr 794 | mov dph, a 795 | mov dpl, r3 796 | sjmp qt_11 // } 797 | qt_12: // if (pt == 0) { // end of Q 798 | 799 | qt_99: 800 | #ifdef TDEBUG 801 | //lcall xlog3 802 | //lcall xlog4 803 | push dpl 804 | push dph 805 | mov dptr, #i0033 806 | lcall _dump_wait_list 807 | pop dph 808 | pop dpl 809 | #endif 810 | cjne r2, #0, qt_14 // if (prev) { 811 | //mov _enter_sleep_mod_flag, #0 // enter_sleep_mod_flag = 0; 812 | mov _waitq, r4 // waitq = t 813 | mov _waitq+1, r5 // 814 | sjmp qt_15 815 | qt_14: // } else { 816 | inc _DPS 817 | mov a, r4 818 | movx @dptr, a // *prev = t 819 | inc dptr 820 | mov a, r5 821 | movx @dptr, a 822 | dec _DPS // } 823 | qt_15: mov dpl, r4 // dptr = t 824 | mov dph, r5 825 | inc dptr 826 | inc dptr 827 | mov r0, #_queue_task_PARM_2 // t->time = time; 828 | movx a, @r0 829 | movx @dptr, a 830 | inc dptr 831 | inc r0 832 | movx a, @r0 833 | movx @dptr, a 834 | inc dptr 835 | mov a, r6 836 | movx @dptr, a // t->next = next; 837 | inc dptr 838 | mov a, r7 839 | movx @dptr, a 840 | inc dptr 841 | mov a, #TASK_QUEUED // t->state = TASK_QUEUED; 842 | movx @dptr, a 843 | #ifdef TDEBUG 844 | sjmp $0064 845 | $0063: .ascii " post-queue " 846 | .db 0 847 | $0064: 848 | mov dptr, #$0063 849 | lcall _dump_wait_list 850 | #endif 851 | pop _IEN0 852 | ret // return 853 | // } 854 | qt_13: 855 | mov dpl, r6 // 856 | mov dph, r7 857 | inc dptr 858 | inc dptr 859 | clr c 860 | mov r0, #_queue_task_PARM_2 861 | movx a, @r0 862 | mov r1, a 863 | movx a, @dptr 864 | subb a, r1 // tmp1:0 = pt->time - time 865 | inc dptr 866 | mov _tmp0, a 867 | inc r0 868 | movx a, @r0 869 | mov r1, a 870 | movx a, @dptr 871 | subb a, r1 872 | mov _tmp1, a 873 | jc qt_98 // if pt->time was >= time (must insert t prior to pt) 874 | mov dpl, r6 875 | mov dph, r7 876 | inc dptr 877 | inc dptr 878 | mov a, _tmp0 // pt->time = p->time - time 879 | movx @dptr, a 880 | inc dptr 881 | mov a, _tmp1 882 | movx @dptr, a // t->time = time 883 | ajmp qt_99 884 | 885 | // if (pt->time <= time) { 886 | // time -= pt->time; 887 | // ptp = &pt->next; 888 | // pt = *ptp; 889 | // continue; 890 | // } 891 | qt_98: 892 | dec r0 893 | clr a 894 | clr c 895 | subb a, _tmp0 // time = -tmp // 896 | movx @r0, a // 897 | inc r0 898 | clr a 899 | subb a, _tmp1 900 | movx @r0, a 901 | inc dptr 902 | mov _DPL1, dpl // prev = &pt->next 903 | mov _DPH1, dph 904 | movx a, @dptr // pt = pt->next 905 | mov r0, a 906 | inc dptr 907 | movx a, @dptr 908 | mov dpl, r0 909 | mov dph, a 910 | mov r2, #1 911 | ajmp qt_11 //} 912 | 913 | #ifdef TDEBUG 914 | xlog6: 915 | push dpl 916 | push dph 917 | mov dptr, #0157$ 918 | lcall _putstr 919 | mov dpl, r7 920 | lcall _puthex 921 | mov dpl, r6 922 | lcall _puthex 923 | pop dph 924 | pop dpl 925 | ret 926 | 0157$: .ascii "timer " 927 | .db 0 928 | xlog3: 929 | push dpl 930 | push dph 931 | mov dptr, #0152$ 932 | lcall _putstr 933 | mov dpl, r5 934 | lcall _puthex 935 | mov dpl, r4 936 | lcall _puthex 937 | pop dph 938 | pop dpl 939 | ret 940 | 0152$: .ascii "r5/4 " 941 | .db 0 942 | xlog4: 943 | push dpl 944 | push dph 945 | mov dptr, #0153$ 946 | lcall _putstr 947 | mov dpl, r7 948 | lcall _puthex 949 | mov dpl, r6 950 | lcall _puthex 951 | pop dph 952 | pop dpl 953 | ret 954 | 0153$: .ascii "r7/6 " 955 | .db 0 956 | i0033: //.db 0x0a 957 | .ascii "pre-queue " 958 | .db 0 959 | #endif 960 | 961 | 962 | __endasm; 963 | } 964 | 965 | void 966 | cancel_task(task __xdata* t) __naked 967 | { 968 | __asm; 969 | #ifdef TDEBUG 970 | push dpl 971 | push dph 972 | push dpl 973 | push dph 974 | sjmp 0201$ 975 | 0202$: .ascii "cancel " 976 | .db 0 977 | 0203$: .ascii " " 978 | .db 0 979 | 0201$: mov dptr, #0202$ 980 | lcall _putstr 981 | pop dpl 982 | lcall _puthex 983 | pop dpl 984 | lcall _puthex 985 | mov dptr, #0203$ 986 | lcall _dump_wait_list 987 | pop dph 988 | pop dpl 989 | #endif 990 | mov r6, dpl // 991 | mov r7, dph 992 | 993 | push _IEN0 // s=EA; 994 | clr EA // EA = 0; 995 | mov r2, #0 996 | mov dpl, _waitq // pt = waitq; 997 | mov dph, _waitq+1 998 | // ptp = &waitq; 999 | ct_1: // for (;;) { 1000 | // 1001 | mov a, r6 1002 | cjne a, dpl, ct_2 // if (pt == t) { 1003 | mov a, r7 1004 | cjne a, dph, ct_2 1005 | inc dptr 1006 | inc dptr 1007 | movx a, @dptr // r1:r0 = t->time 1008 | mov r0, a 1009 | inc dptr 1010 | movx a, @dptr 1011 | mov r1, a 1012 | inc dptr 1013 | movx a, @dptr // pt = t->next 1014 | mov r4, a 1015 | inc dptr 1016 | movx a, @dptr 1017 | mov r5, a 1018 | inc dptr 1019 | mov a, #TASK_IDLE // t->state = T_IDLE 1020 | movx @dptr, a 1021 | 1022 | cjne r4, #0, ct_6 // if (pt) { 1023 | cjne r5, #0, ct_6 1024 | sjmp ct_3 1025 | ct_6: mov dpl, r4 1026 | mov dph, r5 1027 | inc dptr 1028 | inc dptr // pt->time += t->time; 1029 | movx a, @dptr 1030 | add a, r0 1031 | movx @dptr, a 1032 | inc dptr 1033 | movx a, @dptr 1034 | addc a, r1 1035 | movx @dptr, a 1036 | ct_3: // } 1037 | cjne r2, #0, ct_8 // *prev = pt 1038 | mov _waitq, r4 // waitq = dptr0 1039 | mov _waitq+1, r5 1040 | pop _IEN0 // EA = s; 1041 | ret 1042 | ct_8: inc _DPS 1043 | mov a, r4 // prev->next = dptr0 1044 | movx @dptr, a 1045 | inc dptr 1046 | mov a, r5 1047 | movx @dptr, a 1048 | dec _DPS 1049 | ct_9: pop _IEN0 // EA = s; 1050 | ret 1051 | 1052 | // } 1053 | 1054 | ct_2: 1055 | 1056 | #ifdef TDEBUG 1057 | push dpl 1058 | push dph 1059 | push dpl 1060 | mov dpl, dph 1061 | lcall _puthex 1062 | pop dpl 1063 | lcall _puthex 1064 | mov dpl, #13 // U0DBUF = c; 1065 | lcall _putchar 1066 | mov dpl, #10 // U0DBUF = c; 1067 | lcall _putchar 1068 | pop dph 1069 | pop dpl 1070 | #endif 1071 | 1072 | mov a, dpl 1073 | orl a, dph 1074 | jz ct_9 1075 | 1076 | inc dptr 1077 | inc dptr 1078 | inc dptr 1079 | inc dptr 1080 | mov _DPL1, dpl // prev = &pt->next 1081 | mov _DPH1, dph 1082 | movx a, @dptr // pt = pt->next 1083 | inc dptr 1084 | mov r2, a 1085 | movx a, @dptr 1086 | mov dph, a 1087 | mov dpl, r2 1088 | mov r2, #1 1089 | ajmp ct_1 // } 1090 | __endasm; 1091 | } 1092 | 1093 | #ifdef TASK_TEST 1094 | static unsigned char __xdata rgb[6]={0,0,0,0,0,0}; 1095 | static void test(task __xdata*t); 1096 | static __xdata task test_task = {test,0,0,0}; 1097 | static void test(task __xdata*t) 1098 | { 1099 | rgb[0]+=16; 1100 | rgb[1]+=16; 1101 | send_RGB(&rgb[0]); 1102 | putstr("1"); 1103 | queue_task(&test_task, HZ); 1104 | 1105 | } 1106 | static void test2(task __xdata*t); 1107 | static __xdata task test_task2 = {test2,0,0,0}; 1108 | static void test2(task __xdata*t) 1109 | { 1110 | putstr("2"); 1111 | rgb[2]+=64; 1112 | rgb[3]+=64; 1113 | send_RGB(&rgb[0]); 1114 | queue_task(&test_task2, 2*HZ); 1115 | } 1116 | static void test3(task __xdata*t); 1117 | static __xdata task test_task3 = {test3,0,0,0}; 1118 | static void test3(task __xdata*t) 1119 | { 1120 | putstr("3"); 1121 | rgb[4]-=32; 1122 | rgb[5]-=32; 1123 | send_RGB(&rgb[0]); 1124 | queue_task(&test_task3, 5*HZ/2); 1125 | } 1126 | #endif 1127 | 1128 | void 1129 | uart_init() __naked 1130 | { 1131 | __asm; 1132 | orl _P0DIR, #0x08 1133 | orl _P0SEL, #0x08 // p0.3 out - TXD 1134 | mov _U0CSR, #0x80 1135 | mov _U0GCR, #0x08 1136 | mov _U0BAUD, #59 1137 | mov _U0CSR, #0x80 1138 | //U0UCR = 0x82; 1139 | mov _U0UCR, #0x86 1140 | mov _UTX0IF, #0 1141 | ret 1142 | __endasm; 1143 | } 1144 | 1145 | void 1146 | main() 1147 | { 1148 | EA = 0; 1149 | sys_active = 0; 1150 | // 1151 | CLKCONCMD=0x80; // 32MHz ext, int 32khz 1152 | while (CLKCONSTA != 0x80) 1153 | ; 1154 | P1 = 0; 1155 | P1DIR = 0xc1; 1156 | P0DIR = 0x00; 1157 | P0SEL = 0; 1158 | P1SEL = 0; 1159 | P2SEL = 0; 1160 | P2DIR = 0; 1161 | PERCFG = 0; 1162 | // 1163 | // sleep timer 1164 | // 1165 | ST2 = 0; 1166 | { 1167 | extern code_hdr __code CODE_HEADER; 1168 | x_app = (unsigned char (* __data ) (u8))(&CODE_HEADER.data[0]); 1169 | } 1170 | #ifdef TDEBUG 1171 | uart_init(); 1172 | putstr("calling suota_setup ...\n"); 1173 | #endif 1174 | //suota_setup(); 1175 | // rf_init(); 1176 | #ifdef TDEBUG 1177 | putstr("calling APP_INIT ...\n"); 1178 | #endif 1179 | app(APP_INIT); 1180 | #ifdef TDEBUG 1181 | putstr("return APP_INIT ...\n"); 1182 | #endif 1183 | #ifdef XMT 1184 | queue_task(&test_task4, 1*HZ); 1185 | #endif 1186 | #ifdef TASK_TEST 1187 | queue_task(&test_task, 1*HZ); 1188 | queue_task(&test_task2, 2*HZ); 1189 | queue_task(&test_task3, 3*HZ); 1190 | #endif 1191 | __asm; 1192 | .globl _restart_point 1193 | _restart_point: 1194 | mov r6, #0 // delta = 0; 1195 | mov r7, #0 1196 | m_1: // for (;;) { 1197 | distribute: 1198 | #ifdef TDEBUG 1199 | sjmp 0707$ 1200 | 0706$: .ascii "." 1201 | .db 0 1202 | 0707$: mov dptr, #0706$ 1203 | lcall _dump_wait_list 1204 | #endif 1205 | mov dpl, _waitq // for (xpt = waitq;;) { 1206 | mov dph, _waitq+1 1207 | m_2: mov a, dph 1208 | m_2a: orl a, dpl 1209 | jz m_4 1210 | cjne r6, #0, m_5// if (!delta) break 1211 | cjne r7, #0, m_5 1212 | sjmp m_4 1213 | m_5: inc dptr 1214 | inc dptr 1215 | clr c 1216 | movx a, @dptr// delta = xpt->time = xpt->time-delta 1217 | subb a, r6 1218 | movx @dptr, a 1219 | mov r6, a 1220 | inc dptr 1221 | movx a, @dptr 1222 | subb a, r7 1223 | jc m_6 // if (xpt->time >= delta) { 1224 | movx @dptr, a// xpt->time -= delta; 1225 | sjmp m_4// break; 1226 | // } 1227 | m_6: mov r7, a 1228 | clr a 1229 | movx @dptr, a// xpt->time = 0; 1230 | dec dpl 1231 | mov r0, dpl 1232 | cjne r0, #0xff, m_6a 1233 | dec dph 1234 | m_6a: movx @dptr, a 1235 | clr c 1236 | subb a, r6 // delta = -delta 1237 | mov r6, a 1238 | clr a 1239 | subb a, r7 1240 | mov r7, a 1241 | inc dptr 1242 | inc dptr 1243 | movx a, @dptr// xpt = xpt->next 1244 | mov r0, a 1245 | inc dptr 1246 | movx a, @dptr 1247 | mov dpl, r0 1248 | mov dph, a 1249 | sjmp m_2a // } 1250 | m_4: // for (;;) { 1251 | #ifdef TDEBUG 1252 | sjmp 0717$ 1253 | 0716$: .ascii "-" 1254 | .db 0 1255 | 0717$: mov dptr, #0716$ 1256 | lcall _dump_wait_list 1257 | #endif 1258 | mov dpl, _waitq // xpt = waitq; 1259 | mov dph, _waitq+1 1260 | mov a, dpl // if (!xpt) break 1261 | orl a, dph 1262 | jz m_8 1263 | mov r6, dpl 1264 | mov r7, dph 1265 | inc dptr // if (xpt->time != 0) break 1266 | inc dptr 1267 | movx a, @dptr 1268 | cjne a, #0, m_8 1269 | inc dptr 1270 | movx a, @dptr 1271 | cjne a, #0, m_8 1272 | #ifdef TDEBUG 1273 | lcall xlog1 1274 | #endif 1275 | push dpl 1276 | push dph 1277 | mov dpl, #0xff // start_timer(60000); 1278 | mov dph, #0xfe 1279 | acall _start_timer 1280 | pop dph 1281 | pop dpl 1282 | inc dptr // waitq = xpt->next; 1283 | movx a, @dptr 1284 | mov _waitq, a 1285 | inc dptr 1286 | movx a, @dptr 1287 | mov _waitq+1, a 1288 | inc dptr 1289 | mov a, #TASK_CALLOUT// xpt->state = TASK_CALLOUT; 1290 | movx @dptr, a 1291 | setb EA // EA = 1; 1292 | push dpl 1293 | push dph 1294 | 1295 | mov a, #m_ret 1296 | push acc 1297 | mov a, #m_ret>>8 1298 | push acc 1299 | mov dpl, r6 // xpt->callout(xpt); 1300 | mov dph, r7 1301 | movx a, @dptr 1302 | push acc 1303 | inc dptr 1304 | movx a, @dptr 1305 | push acc 1306 | mov dpl, r6 1307 | mov dph, r7 1308 | ret 1309 | m_ret: 1310 | #ifdef TDEBUG 1311 | lcall xlog2 1312 | #endif 1313 | pop dph 1314 | pop dpl 1315 | clr EA // EA = 0; 1316 | movx a, @dptr 1317 | cjne a, #TASK_CALLOUT, m_9// if (xpt->state == TASK_CALLOUT) 1318 | mov a, #TASK_IDLE// xpt->state = TASK_IDLE; 1319 | movx @dptr, a 1320 | m_9: 1321 | acall _stop_timer// delta = stop_timer(); 1322 | mov r6, dpl 1323 | mov r7, dph 1324 | cjne r6, #0, m_9a// if (delta) 1325 | cjne r7, #0, m_9a// goto distribute; 1326 | sjmp m_4 // } 1327 | m_9a: 1328 | ajmp distribute 1329 | m_8: 1330 | #ifdef TDEBUG 1331 | // lcall xlog5 1332 | #endif 1333 | mov a, _waitq // if (!waitq) { 1334 | orl a, _waitq+1 1335 | jnz m_10 1336 | mov _enter_sleep_mod_flag, #1//enter_sleep_mod_flag = 1; 1337 | // jb _rx_active, m_85 1338 | jb _sys_active, m_85 1339 | 1340 | mov a, _CLKCONSTA 1341 | anl a, #0x38 // tsaved = CLKCONSTA & TICKSPD_MASK 1342 | push acc 1343 | anl _CLKCONSTA, #~0x38 // CLKCONCMD &= ~TICKSPD_MASK; 1344 | 1345 | mov _SLEEPCMD, #5 // SLEEPCMD = PM1 1346 | setb EA // EA = 1; 1347 | m_81d: mov a, _enter_sleep_mod_flag 1348 | cjne a, #1, m_11c // while(enter_sleep_mod_flag) 1349 | lcall _idle_pool 1350 | //lcall _sleep // sleep(); 1351 | sjmp m_81d 1352 | 1353 | m_81c: mov a, _CLKCONSTA // while ((CLKCONSTA & OSC) != CLKCONCMD_32MHZ); 1354 | jnb a.6, m_81c 1355 | pop acc 1356 | orl _CLKCONCMD, a // CLKCONCMD |= tsaved; 1357 | clr EA 1358 | //mov _rtx_key, #NO_CRYPTO // crypto key is invalidated in PM2 1359 | sjmp m_8x// EA = 0; 1360 | 1361 | m_85: mov _SLEEPCMD, #4 // SLEEPCMD = 4;//(radio_busy?0:2); IDLE 1362 | setb EA // EA = 1; 1363 | m_8b: mov a, _enter_sleep_mod_flag 1364 | cjne a, #1, m_8a // while(enter_sleep_mod_flag) 1365 | lcall _idle_pool 1366 | //acall _sleep // sleep(); 1367 | sjmp m_8b 1368 | m_8a: clr EA // EA = 0; 1369 | m_8x: mov r6, #0 // delta = 0; 1370 | mov r7, #0 1371 | ajmp m_1 1372 | 1373 | 1374 | m_10: // } else { 1375 | #ifdef TDEBUG 1376 | mov a, _ST0 1377 | push _ST1 1378 | push _ST2 1379 | // lcall _puthex 1380 | // pop dpl 1381 | // lcall _puthex 1382 | 1383 | // lcall xlog5 1384 | #endif 1385 | mov dpl, _waitq 1386 | mov dph, _waitq+1 1387 | inc dptr 1388 | inc dptr 1389 | movx a, @dptr // if (!xpt->time) { 1390 | mov r0, a 1391 | inc dptr 1392 | movx a, @dptr 1393 | cjne a, #0, m_11 1394 | cjne r0, #0, m_11 1395 | #ifdef TDEBUG 1396 | pop ACC 1397 | pop ACC 1398 | #endif 1399 | 1400 | mov r6, #0 // delta = 0; 1401 | mov r7, #0 1402 | ljmp m_1 1403 | 1404 | m_11: // } else { 1405 | mov _enter_sleep_mod_flag, #1 // enter_sleep_mod_flag = 1; 1406 | mov dpl, r0 1407 | mov dph, a 1408 | // jb _rx_active, m_55 1409 | jb _sys_active, m_55 1410 | 1411 | mov a, _CLKCONSTA 1412 | anl a, #0x38 // tsaved = CLKCONSTA & TICKSPD_MASK 1413 | push acc 1414 | anl _CLKCONSTA, #~0x38 // CLKCONCMD &= ~TICKSPD_MASK; 1415 | 1416 | lcall _start_timer // start_timer(xpt->time); 1417 | mov _SLEEPCMD, #5 // SLEEPCMD = PM1 1418 | setb EA // EA = 1; 1419 | m_11d: mov a, _enter_sleep_mod_flag 1420 | cjne a, #1, m_11c // while(enter_sleep_mod_flag) 1421 | #ifdef NOTDEF 1422 | jnb _inSuspend, x_idle1 1423 | lcall _sleep // sleep(); 1424 | sjmp m_11d 1425 | #endif 1426 | x_idle1: lcall _idle_pool 1427 | sjmp m_11d 1428 | 1429 | m_11c: mov a, _CLKCONSTA // while ((CLKCONSTA & OSC) != CLKCONCMD_32MHZ); 1430 | jnb a.6, m_11c 1431 | pop acc 1432 | orl _CLKCONCMD, a // CLKCONCMD |= tsaved; 1433 | clr EA // EA = 0; 1434 | //mov _rtx_key, #NO_CRYPTO // crypto key is invalidated in PM2 1435 | lcall _stop_timer // delta = stop_timer(); 1436 | mov r6, dpl 1437 | mov r7, dph 1438 | sjmp m_56 1439 | 1440 | 1441 | 1442 | m_55: 1443 | lcall _start_timer // start_timer(xpt->time); 1444 | mov _SLEEPCMD, #4 // SLEEPCMD = IDLE 1445 | setb EA // EA = 1; 1446 | m_11b: mov a, _enter_sleep_mod_flag 1447 | cjne a, #1, m_11a // while(enter_sleep_mod_flag) 1448 | #ifdef NOTDEF 1449 | jnb _inSuspend, x_idle2 1450 | lcall _sleep // sleep(); 1451 | sjmp m_11b 1452 | #endif 1453 | x_idle2: lcall _idle_pool 1454 | sjmp m_11b 1455 | m_11a: clr EA // EA = 0; 1456 | lcall _stop_timer // delta = stop_timer(); 1457 | mov r6, dpl 1458 | mov r7, dph 1459 | m_56: 1460 | #ifdef TDEBUG 1461 | mov a, _ST0 1462 | push _ST1 1463 | mov dpl, _ST2 1464 | lcall _puthex // current time 1465 | pop dpl 1466 | lcall _puthex 1467 | 1468 | mov dpl, r7 // measured delta 1469 | lcall _puthex 1470 | mov dpl, r6 1471 | lcall _puthex 1472 | mov dpl, _last+1 // last time when we started 1473 | lcall _puthex 1474 | mov dpl, _last 1475 | lcall _puthex 1476 | pop dpl // measured same thing 1477 | lcall _puthex 1478 | pop dpl 1479 | lcall _puthex 1480 | mov dptr,#317$ 1481 | lcall _putstr 1482 | #endif 1483 | ljmp m_1 // } 1484 | // } 1485 | //} 1486 | #ifdef TDEBUG 1487 | 0317$: .db 0x0a, 0 1488 | xlog1: 1489 | push dpl 1490 | push dph 1491 | mov dptr, #0102$ 1492 | lcall _putstr 1493 | mov dpl, r7 1494 | lcall _puthex 1495 | mov dpl, r6 1496 | lcall _puthex 1497 | mov dptr, #0103$ 1498 | lcall _dump_wait_list 1499 | pop dph 1500 | pop dpl 1501 | ret 1502 | 0102$: .ascii "call " 1503 | .db 0 1504 | 0103$: .ascii " " 1505 | .db 0 1506 | xlog2: 1507 | push dpl 1508 | push dph 1509 | mov dptr, #0202$ 1510 | lcall _putstr 1511 | pop dph 1512 | pop dpl 1513 | ret 1514 | 0202$: .ascii "done" 1515 | 0203$: .db 0x0a, 0 1516 | xlog5: 1517 | push dpl 1518 | push dph 1519 | mov dptr, #0312$ 1520 | lcall _dump_wait_list 1521 | pop dph 1522 | pop dpl 1523 | ret 1524 | 0312$: .ascii "sleeping " 1525 | 0313$: .db 0x0a, 0 1526 | #endif 1527 | __endasm; 1528 | } 1529 | -------------------------------------------------------------------------------- /manufacturing.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2015 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | // 20 | // Manufacturing test 21 | // 22 | // this file generates a stream of bits on P2.1 (the debug data pin) describing 23 | // the results of self test - (valid CRC, active RNG) 24 | // this provide no more useful information to an outside snooper 25 | // other than "the device is operating" (basically what the LED displays) 26 | // 27 | 28 | #include 29 | #include 30 | #include "interface.h" 31 | 32 | static void manufacturing_thread(task __xdata*t); 33 | __xdata task manufacturing_task = {manufacturing_thread,0,0,0}; 34 | static __data unsigned char manufacturing_state=0; 35 | static __bit crc_ok; // should be 1 36 | extern __bit pool_busy; // should be 1 37 | extern unsigned char __data error_state; // should be 0 38 | 39 | static void check_manufacturing_crc_16() __naked 40 | { 41 | __asm; 42 | mov r6, _RNDL 43 | mov r7, _RNDH 44 | mov _RNDL, #0xff // crc = 0xff 45 | mov _RNDL, #0xff 46 | 47 | mov _FMAP, #0x00 // for (ptr = 0; ptr < (top-of-mem-32); ptr++) 48 | 0001$: 49 | mov dptr, #0x8000 50 | 0002$: 51 | clr a 52 | movc a, @a+dptr // crc = crc16(crc, *ptr); 53 | mov _RNDH, a 54 | inc dptr 55 | mov a, dph 56 | jnz 0002$ 57 | mov a, _FMAP 58 | inc a 59 | mov _FMAP, a 60 | cjne a, #7, 0001$ 61 | 62 | mov dptr, #0x8000 63 | 0003$: 64 | clr a 65 | movc a, @a+dptr 66 | mov _RNDH, a 67 | inc dptr 68 | mov a, dph 69 | cjne a, #0xff, 0003$ 70 | 0004$: 71 | clr a 72 | movc a, @a+dptr 73 | mov _RNDH, a 74 | inc dptr 75 | mov a, dpl 76 | cjne a, #0xe0, 0004$ 77 | clr a 78 | movc a, @a+dptr // lsb CRC // crc_ok = crc == *(u16*)ptr; 79 | mov r0, a 80 | inc dptr 81 | clr a 82 | movc a, @a+dptr // msb CRC 83 | mov r1, a 84 | mov a, _RNDL 85 | cjne a, ar0, 0005$ 86 | mov a, _RNDH 87 | cjne a, ar1, 0005$ 88 | setb _crc_ok 89 | sjmp 0006$ 90 | 0005$: clr _crc_ok 91 | 0006$: 92 | mov _RNDL, r7 93 | mov _RNDL, r6 94 | mov _ADCCON1, #0x00 // go 95 | ret 96 | __endasm; 97 | } 98 | 99 | static void 100 | manufacturing_thread(task __xdata*t) 101 | { 102 | switch (manufacturing_state) { 103 | case 0: check_manufacturing_crc_16(); // fall thru 104 | P2DIR |= 1<<1; 105 | P2INP |= 1<<1; 106 | P2_1 = 0; 107 | case 1: manufacturing_state = 2; // frame 00110101 108 | P2_1 = 0; 109 | break; 110 | case 2: manufacturing_state = 3; // frame 00110101 111 | P2_1 = 0; 112 | break; 113 | case 3: manufacturing_state = 4; // frame 00110101 114 | P2_1 = 1; 115 | break; 116 | case 4: manufacturing_state = 5; // frame 00110101 117 | P2_1 = 1; 118 | break; 119 | case 5: manufacturing_state = 6; // frame 00110101 120 | P2_1 = 0; 121 | break; 122 | case 6: manufacturing_state = 7; // frame 00110101 123 | P2_1 = 1; 124 | break; 125 | case 7: manufacturing_state = 8; // frame 00110101 126 | P2_1 = 0; 127 | break; 128 | case 8: manufacturing_state = 9; // frame 00110101 129 | P2_1 = 1; 130 | break; 131 | case 9: manufacturing_state = 10; // CRC - should be 1 132 | P2_1 = crc_ok; 133 | break; 134 | case 10:manufacturing_state = 11; // no error - should be 1 135 | if (error_state == 0) { 136 | P2_1 = 1; 137 | } else { 138 | P2_1 = 0; 139 | } 140 | break; 141 | case 11:manufacturing_state = 1; // no error - should be 1 142 | P2_1 = pool_busy; 143 | break; 144 | default: 145 | manufacturing_state = 1; 146 | break; 147 | } 148 | queue_task(&manufacturing_task, HZ/10); 149 | } 150 | -------------------------------------------------------------------------------- /merge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # $1 incoming .ihx file 3 | # $2 random_data 4 | # $3 size 5 | # $4 output file 6 | # 7 | # makebin comes from the sdcc build system 8 | # 9 | makebin -p $1 $1.tmp 10 | cat $1.tmp $2 >$4 11 | n=$(($3-600-80)) 12 | truncate -s $n $4 13 | rm $1.tmp 14 | exit 0 15 | -------------------------------------------------------------------------------- /onerng.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; Moonbase Otago CC2531 entropy generator 3 | ; 4 | ; based on Windows USB CDC ACM Setup file 5 | ; Copyright (c) 2000 Microsoft Corporation 6 | ; Copyright (C) 2009 Texas Instruments Inc 7 | 8 | [Version] 9 | Signature="$Windows NT$" 10 | Class=Ports 11 | ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} 12 | Provider=%PROVIDER% 13 | LayoutFile=layout.inf 14 | DriverVer=05/01/2009,1.1.0.0 15 | 16 | [Manufacturer] 17 | %MFGNAME%=DeviceList, NTx86, NTia64, NTamd64 18 | 19 | [DestinationDirs] 20 | DefaultDestDir=12 21 | 22 | [SourceDisksFiles] 23 | 24 | [SourceDisksNames] 25 | 26 | [DeviceList.NTx86] 27 | %DESCRIPTION%=DriverInstall, USB\VID_1d50&PID_6086 28 | 29 | [DeviceList.NTia64] 30 | %DESCRIPTION%=DriverInstall, USB\VID_1d50&PID_6086 31 | 32 | [DeviceList.NTamd64] 33 | %DESCRIPTION%=DriverInstall, USB\VID_1d50&PID_6086 34 | 35 | 36 | ;------------------------------------------------------------------------------ 37 | ; 32-bit section for Windows 2000/2003/XP/Vista 38 | ;------------------------------------------------------------------------------ 39 | 40 | [DriverInstall.NTx86] 41 | include=mdmcpq.inf 42 | CopyFiles=DriverCopyFiles 43 | AddReg=DriverInstall.NTx86.AddReg 44 | 45 | [DriverInstall.NTx86] 46 | include=mdmcpq.inf 47 | CopyFiles=DriverCopyFiles 48 | AddReg=DriverInstall.NTx86.AddReg 49 | 50 | [DriverCopyFiles] 51 | usbser.sys,,,0x20 52 | 53 | [DriverInstall.NTx86.AddReg] 54 | HKR,,DevLoader,,*ntkern 55 | HKR,,NTMPDriver,,usbser.sys 56 | HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" 57 | 58 | [DriverInstall.NTx86.Services] 59 | AddService=usbser, 0x00000002, DriverService 60 | 61 | ;------------------------------------------------------------------------------ 62 | ; 64-bit section for Intel Itanium based systems 63 | ;------------------------------------------------------------------------------ 64 | 65 | [DriverInstall.NTia64] 66 | include=mdmcpq.inf 67 | CopyFiles=DriverCopyFiles 68 | AddReg=DriverInstall.NTia64.AddReg 69 | 70 | [DriverInstall.NTia64] 71 | include=mdmcpq.inf 72 | CopyFiles=DriverCopyFiles 73 | AddReg=DriverInstall.NTia64.AddReg 74 | 75 | [DriverCopyFiles] 76 | usbser.sys,,,0x20 77 | 78 | [DriverInstall.NTia64.AddReg] 79 | HKR,,DevLoader,,*ntkern 80 | HKR,,NTMPDriver,,usbser.sys 81 | HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" 82 | 83 | [DriverInstall.NTia64.Services] 84 | AddService=usbser, 0x00000002, DriverService 85 | 86 | ;------------------------------------------------------------------------------ 87 | ; 64-bit section for AMD64 and Intel EM64T based systems 88 | ;------------------------------------------------------------------------------ 89 | 90 | [DriverInstall.NTamd64] 91 | include=mdmcpq.inf 92 | CopyFiles=DriverCopyFiles 93 | AddReg=DriverInstall.NTamd64.AddReg 94 | 95 | [DriverInstall.NTamd64] 96 | include=mdmcpq.inf 97 | CopyFiles=DriverCopyFiles 98 | AddReg=DriverInstall.NTamd64.AddReg 99 | 100 | [DriverCopyFiles] 101 | usbser.sys,,,0x20 102 | 103 | [DriverInstall.NTamd64.AddReg] 104 | HKR,,DevLoader,,*ntkern 105 | HKR,,NTMPDriver,,usbser.sys 106 | HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" 107 | 108 | [DriverInstall.NTamd64.Services] 109 | AddService=usbser, 0x00000002, DriverService 110 | 111 | ;------------------------------------------------------------------------------ 112 | ; 113 | ;------------------------------------------------------------------------------ 114 | 115 | [DriverService] 116 | DisplayName=%SERVICE% 117 | ServiceType=1 118 | StartType=3 119 | ErrorControl=1 120 | ServiceBinary=%12%\usbser.sys ;;%12% == "%WINDIR%\system32\" 121 | 122 | ;------------------------------------------------------------------------------ 123 | ; String Definitions 124 | ;------------------------------------------------------------------------------ 125 | 126 | [Strings] 127 | PROVIDER="Moonbase Otago" 128 | MFGNAME="Moonbase Otago" 129 | DESCRIPTION="OneRNG entropy generator" 130 | SERVICE="OneRNG entropy generator" 131 | -------------------------------------------------------------------------------- /random_data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OneRNG/firmware/81d70bf5e24d8b672b1f50fde7366c8e21640c38/random_data -------------------------------------------------------------------------------- /set_size.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | void 7 | main(int argc, char**argv) 8 | { 9 | struct stat s; 10 | 11 | stat(argv[1], &s); 12 | printf("%c%c", (int)s.st_size&0xff, (int)(s.st_size>>8)&0xff); 13 | exit(0); 14 | } 15 | -------------------------------------------------------------------------------- /size.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | s=`stat --format="%s" $1` 4 | echo $s 5 | -------------------------------------------------------------------------------- /usb.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "usb.h" 4 | #include "interface.h" 5 | 6 | // (c) Copyright Paul Campbell paul@taniwha.com 2013 7 | // 8 | // This library is free software; you can redistribute it and/or 9 | // modify it under the terms of the GNU Lesser General Public 10 | // License as published by the Free Software Foundation; either 11 | // version 2.1 of the License, or (at your option) version 3, or any 12 | // later version accepted by Paul Campbell , who shall 13 | // act as a proxy defined in Section 6 of version 3 of the license. 14 | // 15 | // This library is distributed in the hope that it will be useful, 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | // Lesser General Public License for more details. 19 | // 20 | // You should have received a copy of the GNU Lesser General Public 21 | // License along with this library. If not, see . 22 | // 23 | 24 | unsigned char __data eventMaskIn; 25 | unsigned char __data eventMaskOut; 26 | static unsigned char __data eventMaskCtrl; 27 | static unsigned char __pdata irqMaskCtrl; 28 | static unsigned char __pdata irqMaskIn; 29 | static unsigned char __pdata irqMaskOut; 30 | 31 | __bit inSuspend; 32 | extern __bit pool_busy; 33 | static void usb_handler(struct task __xdata *p); 34 | static struct task __xdata usb_task = {usb_handler, 0, 0, 0}; 35 | 36 | struct sh __pdata setup_header; 37 | 38 | unsigned char __xdata * __data pData; 39 | unsigned int __data bytes_left; 40 | unsigned char __pdata usbState; ///< USB device state 41 | unsigned char __xdata configurationValue; ///< Current configuration value 42 | unsigned char __xdata pAlternateSetting[5]; ///< Current alternate settings 43 | unsigned char __pdata ep0Status; ///< Endpoint 0 status 44 | unsigned char __pdata pEpInStatus[5]; ///< Endpoint 1-5 IN status 45 | unsigned char __pdata pEpOutStatus[5]; 46 | unsigned char __pdata remoteWakeup; 47 | 48 | #ifndef NULL 49 | #define NULL 0 50 | #endif 51 | 52 | static void (* __pdata ProcessFunc)(); 53 | 54 | 55 | void usb_intr(void); 56 | void 57 | usb_init() 58 | { 59 | eventMaskIn = 0x00; 60 | eventMaskOut = 0x00; 61 | eventMaskCtrl = 0x00; 62 | inSuspend = 0; 63 | irqMaskCtrl = 0xff; 64 | irqMaskIn = 0xff; 65 | irqMaskOut = 0x3e; 66 | 67 | USBCIE = 0xff; 68 | USBIIE = 0xff; 69 | USBOIE = 0x3E; 70 | 71 | P2IFG = 0; 72 | P2IF = 0; 73 | P2IEN |= 0x20; 74 | IEN2 |= 0x02; 75 | 76 | p2_vect = usb_intr; 77 | 78 | USBCTRL= USBCTRL_PLL_EN|USBCTRL_USB_EN; 79 | while (!(USBCTRL&USBCTRL_PLL_LOCKED)) 80 | ; 81 | USBCIE |= USBCIE_RESUMEIE; 82 | } 83 | 84 | void 85 | usb_intr(void) __naked 86 | { 87 | __asm; 88 | push PSW 89 | push ACC 90 | push _DPS 91 | push dpl 92 | push dph 93 | push _DPL1 94 | push _DPH1 95 | push ar0 96 | push ar1 97 | push ar2 98 | push ar3 99 | push ar4 100 | push ar5 101 | push ar6 102 | push ar7 103 | mov _DPS, #0 104 | 0001$: mov a, _SLEEPSTA // while (!(SLEEPSTA & SLEEP_XOSC_STB_BM)); 105 | jnb a.6, 0001$ 106 | 107 | mov dptr, #_USBCIF 108 | movx a, @dptr // u = USBCIF; 109 | 110 | 111 | jnb a.0, 0003$ // if (u&USBCIF_SUSPENDIF) 112 | setb _inSuspend // inSuspend = 1; 113 | clr p1.1 114 | 0003$: 115 | jb a.2, 0004$ // if (u&(USBCIF_RSTIF|USBCIF_RESUMEIF)) 116 | jnb a.1, 0005$ 117 | 0004$: 118 | clr _inSuspend // inSuspend = 0; 119 | mov c, _pool_busy 120 | mov p1.1, c 121 | 0005$: 122 | 123 | jnb a.2, 0002$ // if (u&USBCIF_RSTIF) { 124 | mov r1, #_irqMaskCtrl // 125 | movx a, @r1 // USBCIE = irqMask; 126 | mov dptr, #_USBCIE 127 | movx @dptr, a 128 | 129 | mov r1, #_irqMaskIn // 130 | movx a, @r1 // USBIIE = irqMask; 131 | mov dptr, #_USBIIE 132 | movx @dptr, a 133 | 134 | mov r1, #_irqMaskOut // 135 | movx a, @r1 // USBOIE = irqMask; 136 | mov dptr, #_USBOIE 137 | movx @dptr, a 138 | 139 | mov dptr, #_USBPOW // USBPOW |= USBPOW_SUSPEND_EN; 140 | movx a, @dptr 141 | orl a, #USBPOW_SUSPEND_EN 142 | movx @dptr, a 143 | // } 144 | 0002$: 145 | anl a, #0x0f 146 | orl a, _eventMaskCtrl // eventMask |= USN; 147 | mov _eventMaskCtrl, a 148 | 149 | mov dptr, #_USBIIF // eventMask |= USBIIF; 150 | movx a, @dptr 151 | orl a, _eventMaskIn 152 | mov _eventMaskIn, a 153 | 154 | mov dptr, #_USBOIF // eventMask |= USBOIF << 9; 155 | movx a, @dptr 156 | orl a, _eventMaskOut 157 | mov _eventMaskOut, a 158 | 159 | 160 | // if (P2IFG&P2IFG_DPIF) { 161 | mov a, _P2IFG 162 | jnb a.5, 0010$ 163 | anl _P2IFG, #~(1<<5)// P2IFG = ~P2IFG_DPIF; 164 | clr _inSuspend // inSuspend = 0; 165 | mov c, _pool_busy 166 | mov p1.1, c 167 | // } 168 | 0010$: 169 | mov _P2IFG, #0 // P2IFG = 0; 170 | clr _P2IF // P2IF = 0; 171 | 172 | mov dptr, #_usb_task 173 | lcall _queue_task_0 174 | 175 | pop ar7 176 | pop ar6 177 | pop ar5 178 | pop ar4 179 | pop ar3 180 | pop ar2 181 | pop ar1 182 | pop ar0 183 | pop _DPH1 184 | pop _DPL1 185 | pop dph 186 | pop dpl 187 | pop _DPS 188 | pop ACC 189 | pop PSW 190 | reti 191 | __endasm; 192 | } 193 | 194 | static unsigned char __code * __data pDesc; 195 | unsigned char __code* 196 | find_next(unsigned char type, unsigned char halt) __naked 197 | { 198 | __asm; 199 | // unsigned char __code *p; 200 | 201 | mov r2, dpl // p = NULL; 202 | mov r0, #_find_next_PARM_2 203 | movx a, @r0 204 | mov r3, a 205 | mov dpl, _pDesc 206 | mov dph, _pDesc+1 207 | 0001$: 208 | clr a // while (pDesc[0] != 0) { 209 | movc a, @a+dptr 210 | jz 0002$ 211 | mov r4, a 212 | 213 | mov a, #1 // if (pDesc[1] == type) { 214 | movc a, @a+dptr 215 | cjne a, ar2, 0003$ 216 | 217 | // p = pDesc; 218 | mov a, r4 // pDesc += pDesc[0]; 219 | add a, dpl 220 | mov _pDesc, a 221 | clr a 222 | addc a, dph 223 | mov _pDesc+1, a 224 | ret // break; 225 | // } else 226 | 0003$: 227 | cjne a, ar3, 0004$ // if (halt && pDesc[1] == halt) 228 | mov a, r3 // break; 229 | jnz 0002$ 230 | 0004$: 231 | mov a, r4 // pDesc += pDesc[0]; 232 | add a, dpl 233 | mov dpl, a 234 | clr a 235 | addc a, dph 236 | mov dph, a 237 | sjmp 0001$ // } 238 | 0002$: 239 | mov _pDesc, dpl 240 | mov _pDesc+1, dph 241 | 242 | mov dptr, #0 // return p; 243 | ret 244 | __endasm; 245 | } 246 | 247 | static unsigned char __xdata temp_desc[256]; 248 | static unsigned char __xdata * 249 | copy_to_xdata(unsigned char __code *p, unsigned char l) __naked 250 | { 251 | __asm; 252 | clr _DPS 253 | mov r0, #_copy_to_xdata_PARM_2 254 | movx a, @r0 255 | mov r0, a 256 | mov _DPL1, #_temp_desc 257 | mov _DPH1, #_temp_desc>>8 258 | 0001$: clr a 259 | movc a, @a+dptr 260 | inc dptr 261 | inc _DPS 262 | movx @dptr, a 263 | inc dptr 264 | dec _DPS 265 | djnz r0, 0001$ 266 | mov dptr, #_temp_desc 267 | ret 268 | __endasm; 269 | } 270 | 271 | 272 | unsigned char __xdata * 273 | get_device_desc() 274 | { 275 | unsigned char __code *p; 276 | pDesc = &descs[0]; 277 | p = find_next(DESC_TYPE_DEVICE, 0); 278 | return copy_to_xdata(p, p[0]); 279 | } 280 | 281 | unsigned char __xdata * 282 | get_config_desc(unsigned char val, unsigned char ind) 283 | { 284 | unsigned char __code *p; 285 | pDesc = &descs[0]; 286 | while (p = find_next(DESC_TYPE_CONFIG, 0)) { 287 | if (val) { 288 | if (val == ((struct configuration_desc __code *)p)->bConfigurationValue) 289 | return copy_to_xdata(p, p[2]); 290 | } else { 291 | if (!ind) 292 | return copy_to_xdata(p, p[2]); 293 | ind--; 294 | } 295 | } 296 | return 0; 297 | } 298 | 299 | unsigned char __code * 300 | get_interface_desc(unsigned char val, unsigned char num, unsigned char alt) 301 | { 302 | unsigned char __code *p; 303 | pDesc = &descs[0]; 304 | get_config_desc(val, 0); 305 | while (p = find_next(DESC_TYPE_INTERFACE, DESC_TYPE_CONFIG)) { 306 | if (num == ((struct interface_desc __code *)p)->bInterfaceNumber && 307 | alt == ((struct interface_desc __code *)p)->bAlternateSetting) 308 | return p; 309 | } 310 | return 0; 311 | } 312 | 313 | unsigned char __xdata * 314 | get_string_desc(unsigned char ind) 315 | { 316 | unsigned char __code *p; 317 | pDesc = &descs[0]; 318 | for (;;) { 319 | p = find_next(DESC_TYPE_STRING, 0); 320 | if (!p) 321 | return 0; 322 | if (ind == 0) 323 | return copy_to_xdata(p, p[0]); 324 | ind--; 325 | } 326 | } 327 | 328 | void 329 | usb_read_fifo_0_p(unsigned char __pdata *pd, unsigned char count) 330 | { 331 | __asm; 332 | mov r0, #_usb_read_fifo_0_p_PARM_2 333 | movx a, @r0 334 | mov r0, a 335 | mov r1, dpl 336 | mov dptr, #_USBF0 337 | 0001$: movx a, @dptr 338 | movx @r1, a 339 | inc r1 340 | djnz r0, 0001$ 341 | ret 342 | __endasm; 343 | } 344 | void 345 | usb_read_fifo_0(unsigned char __xdata *pd, unsigned char count) 346 | { 347 | __asm; 348 | clr _DPS 349 | mov r0, #_usb_read_fifo_0_PARM_2 350 | movx a, @r0 351 | mov r0, a 352 | mov _DPL1, #_USBF0 353 | mov _DPH1, #_USBF0>>8 354 | 0001$: inc _DPS 355 | movx a, @dptr 356 | dec _DPS 357 | movx @dptr, a 358 | inc dptr 359 | djnz r0, 0001$ 360 | ret 361 | __endasm; 362 | } 363 | 364 | void 365 | usb_read_fifo_5(unsigned char __xdata *pd, unsigned char count) 366 | { 367 | __asm; 368 | clr _DPS 369 | mov r0, #_usb_read_fifo_5_PARM_2 370 | movx a, @r0 371 | mov r0, a 372 | mov _DPL1, #_USBF5 373 | mov _DPH1, #_USBF5>>8 374 | 0001$: inc _DPS 375 | movx a, @dptr 376 | dec _DPS 377 | movx @dptr, a 378 | inc dptr 379 | djnz r0, 0001$ 380 | ret 381 | __endasm; 382 | } 383 | 384 | void 385 | usb_read_fifo_4(unsigned char __xdata *pd, unsigned char count) 386 | { 387 | __asm; 388 | clr _DPS 389 | mov r0, #_usb_read_fifo_4_PARM_2 390 | movx a, @r0 391 | mov r0, a 392 | mov _DPL1, #_USBF4 393 | mov _DPH1, #_USBF4>>8 394 | 0001$: inc _DPS 395 | movx a, @dptr 396 | dec _DPS 397 | movx @dptr, a 398 | inc dptr 399 | djnz r0, 0001$ 400 | ret 401 | __endasm; 402 | } 403 | 404 | void 405 | usb_read_fifo_3(unsigned char __xdata *pd, unsigned char count) 406 | { 407 | __asm; 408 | clr _DPS 409 | mov r0, #_usb_read_fifo_3_PARM_2 410 | movx a, @r0 411 | mov r0, a 412 | mov _DPL1, #_USBF3 413 | mov _DPH1, #_USBF3>>8 414 | 0001$: inc _DPS 415 | movx a, @dptr 416 | dec _DPS 417 | movx @dptr, a 418 | inc dptr 419 | djnz r0, 0001$ 420 | ret 421 | __endasm; 422 | } 423 | 424 | void 425 | usb_read_fifo_2(unsigned char __xdata *pd, unsigned char count) 426 | { 427 | __asm; 428 | clr _DPS 429 | mov r0, #_usb_read_fifo_2_PARM_2 430 | movx a, @r0 431 | mov r0, a 432 | mov _DPL1, #_USBF2 433 | mov _DPH1, #_USBF2>>8 434 | 0001$: inc _DPS 435 | movx a, @dptr 436 | dec _DPS 437 | movx @dptr, a 438 | inc dptr 439 | djnz r0, 0001$ 440 | ret 441 | __endasm; 442 | } 443 | 444 | void 445 | usb_read_fifo_1(unsigned char __xdata *pd, unsigned char count) 446 | { 447 | __asm; 448 | clr _DPS 449 | mov r0, #_usb_read_fifo_1_PARM_2 450 | movx a, @r0 451 | mov r0, a 452 | mov _DPL1, #_USBF1 453 | mov _DPH1, #_USBF1>>8 454 | 0001$: inc _DPS 455 | movx a, @dptr 456 | dec _DPS 457 | movx @dptr, a 458 | inc dptr 459 | djnz r0, 0001$ 460 | ret 461 | __endasm; 462 | } 463 | 464 | void 465 | usb_write_fifo_0(unsigned char __xdata *pd, unsigned char count) 466 | { 467 | __asm; 468 | mov r0, #_usb_write_fifo_0_PARM_2 469 | movx a, @r0 470 | jz 0002$ 471 | mov r0, a 472 | mov _DPL1, #_USBF0 473 | mov _DPH1, #_USBF0>>8 474 | 0001$: movx a, @dptr 475 | inc dptr 476 | inc _DPS 477 | movx @dptr, a 478 | dec _DPS 479 | djnz r0, 0001$ 480 | 0002$: 481 | ret 482 | __endasm; 483 | } 484 | 485 | static unsigned char __xdata xtmp[32]; 486 | 487 | static void usb_has_data_1() 488 | { 489 | for (;;) { 490 | unsigned char c; 491 | unsigned char l, x, x2; 492 | 493 | EA=0; 494 | c = USBINDEX; 495 | USBINDEX = 1; 496 | if (!(USBCSOL&USBCSOL_OUTPKT_RDY)) { 497 | USBINDEX = c; 498 | EA=1; 499 | return; 500 | } 501 | x = USBCNTL; 502 | x2 = USBCNTH; 503 | if (x2 || x > sizeof(xtmp)) { 504 | l = sizeof(xtmp); 505 | } else { 506 | l = x; 507 | } 508 | usb_read_fifo_1(&xtmp[0], l); 509 | if (l == x && !x2) { 510 | USBINDEX = 1; 511 | USBCSOL = 0; 512 | } 513 | EA=1; 514 | } 515 | } 516 | static void usb_has_data_2() 517 | { 518 | 519 | for (;;) { 520 | unsigned char c; 521 | unsigned char l, x, x2; 522 | 523 | EA=0; 524 | c = USBINDEX; 525 | USBINDEX = 2; 526 | if (!(USBCSOL&USBCSOL_OUTPKT_RDY)) { 527 | USBINDEX = c; 528 | EA=1; 529 | return; 530 | } 531 | x = USBCNTL; 532 | x2 = USBCNTH; 533 | if (x2 || x > sizeof(xtmp)) { 534 | l = sizeof(xtmp); 535 | } else { 536 | l = x; 537 | } 538 | usb_read_fifo_2(&xtmp[0], l); 539 | if (l == x && !x2) { 540 | USBINDEX = 2; 541 | USBCSOL = 0; 542 | } 543 | EA=1; 544 | } 545 | 546 | } 547 | static void usb_has_data_3() 548 | { 549 | 550 | for (;;) { 551 | unsigned char c; 552 | unsigned char l, x, x2; 553 | 554 | EA=0; 555 | c = USBINDEX; 556 | USBINDEX = 3; 557 | if (!(USBCSOL&USBCSOL_OUTPKT_RDY)) { 558 | USBINDEX = c; 559 | EA=1; 560 | return; 561 | } 562 | x = USBCNTL; 563 | x2 = USBCNTH; 564 | if (x2 || x > sizeof(xtmp)) { 565 | l = sizeof(xtmp); 566 | } else { 567 | l = x; 568 | } 569 | usb_read_fifo_3(&xtmp[0], l); 570 | if (l == x && !x2) { 571 | USBINDEX = 3; 572 | USBCSOL = 0; 573 | } 574 | EA=1; 575 | } 576 | 577 | } 578 | static void usb_has_data_4() 579 | { 580 | 581 | for (;;) { 582 | unsigned char c; 583 | unsigned char l, x, x2; 584 | 585 | EA=0; 586 | c = USBINDEX; 587 | USBINDEX = 4; 588 | if (!(USBCSOL&USBCSOL_OUTPKT_RDY)) { 589 | USBINDEX = c; 590 | EA=1; 591 | return; 592 | } 593 | x = USBCNTL; 594 | x2 = USBCNTH; 595 | if (x2 || x > sizeof(xtmp)) { 596 | l = sizeof(xtmp); 597 | } else { 598 | l = x; 599 | } 600 | usb_read_fifo_4(&xtmp[0], l); 601 | if (l == x && !x2) { 602 | USBINDEX = 4; 603 | USBCSOL = 0; 604 | } 605 | EA=1; 606 | } 607 | 608 | } 609 | 610 | static unsigned char 611 | change_feature(unsigned char set) 612 | { 613 | unsigned char endpoint; 614 | 615 | if (setup_header.length || usbState != DEV_CONFIGURED && (setup_header.index != 0)) { 616 | ep0Status = EP_STALL; 617 | } else { 618 | switch (setup_header.requestType&RT_MASK_RECIP) { 619 | case RT_RECIP_DEV: 620 | if ((setup_header.value&0xff) != DEVICE_REMOTE_WAKEUP) 621 | return 0; 622 | remoteWakeup = set; 623 | break; 624 | case RT_RECIP_IF: 625 | return 0; 626 | case RT_RECIP_EP: 627 | endpoint = setup_header.index&0x7F; 628 | if ((setup_header.value&0xff) != ENDPOINT_HALT) 629 | return 0; 630 | if (endpoint > 5) { 631 | ep0Status = EP_STALL; 632 | } else { 633 | USBINDEX = endpoint; 634 | if (setup_header.index&0x80) { 635 | USBCSIL = set ? USBCSIL_SEND_STALL : USBCSIL_CLR_DATA_TOG; 636 | pEpInStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE; 637 | } else { 638 | USBCSOL = set ? USBCSOL_SEND_STALL : USBCSOL_CLR_DATA_TOG; 639 | pEpOutStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE; 640 | } 641 | USBINDEX = 0; 642 | } 643 | break; 644 | default: 645 | ep0Status = EP_STALL; 646 | break; 647 | } 648 | } 649 | return 1; 650 | } 651 | 652 | static void 653 | config_endpoints(struct interface_desc __code *pi) 654 | { 655 | unsigned char n; 656 | 657 | for (n = 0; n < pi->bNumEndpoints; n++) { 658 | struct endpoint_desc __code *pe; 659 | if (pe = (struct endpoint_desc __code *)find_next(DESC_TYPE_ENDPOINT, 0)) { 660 | unsigned char endpoint; 661 | unsigned int maxpRegValue; 662 | unsigned char csRegValue; 663 | 664 | endpoint = pe->bEndpointAddress & 0x0F; 665 | USBINDEX = endpoint; 666 | csRegValue = 0x00; 667 | maxpRegValue = (pe->wMaxPacketSize + 7) >> 3; 668 | 669 | if (pe->bEndpointAddress&0x80) { // in 670 | USBCSIL = USBCSIL_CLR_DATA_TOG | USBCSIL_FLUSH_PACKET; 671 | USBCSIL = USBCSIL_FLUSH_PACKET; 672 | if ((pe->bmAttributes&EP_ATTR_TYPE_BM) == EP_ATTR_ISO) 673 | csRegValue |= USBCSIH_ISO; // ISO flag 674 | if (endpoint >= 4) 675 | csRegValue |= USBCSIH_IN_DBL_BUF; // Double buffering 676 | USBCSIH = csRegValue; 677 | USBMAXI = maxpRegValue; 678 | pEpInStatus[endpoint - 1] = EP_IDLE; 679 | } else { 680 | USBCSOL = USBCSOL_CLR_DATA_TOG | USBCSOL_FLUSH_PACKET; 681 | USBCSOL = USBCSOL_FLUSH_PACKET; 682 | if ((pe->bmAttributes&EP_ATTR_TYPE_BM) == EP_ATTR_ISO) 683 | csRegValue |= USBCSOH_ISO; // ISO flag 684 | if (endpoint >= 4) 685 | csRegValue |= USBCSOH_OUT_DBL_BUF; // Double buffering 686 | USBCSOH = csRegValue; 687 | USBMAXO = maxpRegValue; 688 | pEpOutStatus[endpoint - 1] = EP_IDLE; 689 | } 690 | USBINDEX = 0; 691 | } 692 | } 693 | } 694 | 695 | 696 | static unsigned int __xdata status; 697 | 698 | static void 699 | usb_handler(struct task __xdata *p) 700 | { 701 | 702 | for (;;) { 703 | EA = 0; 704 | if (eventMaskCtrl&USBCIF_RSTIF) { 705 | u8 i; 706 | eventMaskCtrl &= ~USBCIF_RSTIF; 707 | EA = 1; 708 | usbState = DEV_DEFAULT; 709 | configurationValue = 0; 710 | 711 | ep0Status = EP_IDLE; 712 | for (i = 0; i < sizeof(pEpInStatus); i++) 713 | pEpInStatus[i] = EP_HALT; 714 | for (i = 0; i < sizeof(pEpOutStatus); i++) 715 | pEpOutStatus[i] = EP_HALT; 716 | ProcessFunc = NULL; 717 | continue; 718 | } 719 | 720 | if (eventMaskIn&USBIIE_EP0IE) { 721 | unsigned char controlReg; 722 | unsigned char bytesNow; 723 | unsigned char oldEndpoint; 724 | eventMaskIn &= ~USBIIE_EP0IE; 725 | EA = 1; 726 | 727 | oldEndpoint = USBINDEX; 728 | USBINDEX = 0; 729 | controlReg = USBCS0; 730 | if (controlReg&USBCS0_SETUP_END) { 731 | USBCS0 = USBCS0_CLR_SETUP_END; 732 | ep0Status = EP_CANCEL; 733 | if (ProcessFunc) 734 | ProcessFunc(); 735 | ep0Status = EP_IDLE; 736 | } 737 | 738 | if (controlReg&USBCS0_SENT_STALL) { 739 | USBCS0 = 0x00; 740 | ep0Status = EP_IDLE; 741 | } 742 | 743 | if (ep0Status == EP_RX) { 744 | bytesNow = USBCNT0; 745 | usb_read_fifo_0(pData, bytesNow); 746 | bytes_left -= bytesNow; 747 | pData += bytesNow; 748 | 749 | USBCS0 = bytes_left ? USBCS0_CLR_OUTPKT_RDY : (USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END); 750 | if (bytes_left == 0) { 751 | if (ProcessFunc) 752 | ProcessFunc(); 753 | ep0Status = EP_IDLE; 754 | } 755 | USBINDEX = oldEndpoint; 756 | EA=0; 757 | goto do_next; 758 | } else 759 | if (ep0Status == EP_IDLE) { 760 | if (controlReg&USBCS0_OUTPKT_RDY) { 761 | usb_read_fifo_0_p((unsigned char __pdata *)&setup_header, 8); 762 | ProcessFunc = NULL; 763 | switch (setup_header.requestType & (RT_MASK_TYPE | RT_MASK_DIR)) { 764 | case RT_STD_OUT: 765 | switch (setup_header.request) { 766 | case SET_ADDRESS: 767 | if (setup_header.index || setup_header.length || setup_header.value&0xff80) { 768 | ep0Status = EP_STALL; 769 | break; 770 | } 771 | { 772 | unsigned char a = setup_header.value; 773 | USBADDR = a; 774 | if (a != 0) { 775 | if (usbState == DEV_DEFAULT) 776 | usbState = DEV_ADDRESS; 777 | } else { 778 | if (usbState == DEV_ADDRESS) 779 | usbState = DEV_DEFAULT; 780 | } 781 | } 782 | break; 783 | case SET_FEATURE: 784 | if (change_feature(1)) 785 | ep0Status = EP_STALL; 786 | break; 787 | case CLEAR_FEATURE: 788 | if (change_feature(0)) 789 | ep0Status = EP_STALL; 790 | break; 791 | case SET_CONFIGURATION: 792 | if (usbState == DEV_DEFAULT || setup_header.index || setup_header.length || setup_header.value&0xff00) { 793 | ep0Status = EP_STALL; 794 | break; 795 | } 796 | if (setup_header.value&0xff) { 797 | struct configuration_desc __xdata *pConfiguration; 798 | 799 | pConfiguration = (struct configuration_desc __xdata *)get_config_desc(setup_header.value&0xff, 0); 800 | if (pConfiguration) { 801 | unsigned char n; 802 | usbState = DEV_CONFIGURED; 803 | configurationValue = setup_header.value&0xff; 804 | for (n = 0; n < pConfiguration->bNumInterfaces; n++) { 805 | struct interface_desc __code *pi; 806 | pAlternateSetting[n] = 0x00; 807 | do { 808 | pi = (struct interface_desc __code *)find_next(DESC_TYPE_INTERFACE, 0); 809 | } while (pi->bAlternateSetting != pAlternateSetting[n]); 810 | config_endpoints(pi); 811 | } 812 | } else { 813 | ep0Status = EP_STALL; 814 | } 815 | } else { 816 | u8 i; 817 | configurationValue = setup_header.value; 818 | usbState = DEV_ADDRESS; 819 | for (i = 0; i < sizeof(pEpInStatus); i++) 820 | pEpInStatus[i] = EP_HALT; 821 | for (i = 0; i < sizeof(pEpOutStatus); i++) 822 | pEpOutStatus[i] = EP_HALT; 823 | } 824 | break; 825 | case SET_INTERFACE: 826 | if (usbState != DEV_CONFIGURED || setup_header.requestType != RT_OUT_INTERFACE || setup_header.length) { 827 | ep0Status = EP_STALL; 828 | break; 829 | } 830 | { 831 | struct interface_desc __code *pi; 832 | if (pi = (struct interface_desc __code *)get_interface_desc(configurationValue, setup_header.index, setup_header.value)) { 833 | pAlternateSetting[setup_header.index] = setup_header.value; 834 | config_endpoints(pi); 835 | } else { 836 | ep0Status = EP_STALL; 837 | } 838 | } 839 | break; 840 | case SET_DESCRIPTOR: 841 | default: 842 | ep0Status = EP_STALL; 843 | break; 844 | } 845 | break; 846 | case RT_STD_IN: 847 | switch (setup_header.request) { 848 | case GET_STATUS: 849 | if (setup_header.value || setup_header.index&0xff00 || setup_header.length != 2) { 850 | ep0Status = EP_STALL; 851 | break; 852 | } 853 | switch (setup_header.requestType) { 854 | case RT_IN_DEVICE: 855 | if (setup_header.index&0xff) { 856 | ep0Status = EP_STALL; 857 | break; 858 | } 859 | status = selfPowered ? 0x0001 : 0x0000; 860 | if (remoteWakeup) 861 | status |= 0x0002; 862 | break; 863 | case RT_IN_INTERFACE: 864 | if (usbState != DEV_CONFIGURED) { 865 | ep0Status = EP_STALL; 866 | } else { 867 | status = 0x0000; 868 | } 869 | break; 870 | case RT_IN_ENDPOINT: 871 | { 872 | unsigned char endpoint; 873 | endpoint = setup_header.index&0x7F; 874 | if (usbState != DEV_CONFIGURED || endpoint > 5) { 875 | ep0Status = EP_STALL; 876 | break; 877 | } 878 | if (setup_header.index&0x80) { 879 | status = (pEpInStatus[endpoint-1] == EP_HALT) ? 0x0001 : 0x0000; 880 | } else { 881 | status = (pEpOutStatus[endpoint-1] == EP_HALT) ? 0x0001 : 0x0000; 882 | } 883 | } 884 | break; 885 | default: 886 | ep0Status = EP_STALL; 887 | break; 888 | } 889 | if (ep0Status != EP_STALL) { 890 | pData = (unsigned char __xdata *)&status; 891 | bytes_left = 2; 892 | ep0Status = EP_TX; 893 | } 894 | break; 895 | case GET_DESCRIPTOR: 896 | switch (setup_header.value>>8) { 897 | case DESC_TYPE_DEVICE: 898 | pData = get_device_desc(); 899 | bytes_left = pData[0]; 900 | break; 901 | case DESC_TYPE_CONFIG: 902 | pData = get_config_desc(0, setup_header.value); 903 | bytes_left = pData[2]; // never more than 255 904 | break; 905 | case DESC_TYPE_STRING: 906 | pData = get_string_desc(setup_header.value); 907 | bytes_left = pData[0]; 908 | break; 909 | default: 910 | { 911 | pData = NULL; 912 | bytes_left = 0; 913 | } 914 | } 915 | if (pData == NULL) 916 | ep0Status = EP_STALL; 917 | if (ep0Status != EP_STALL) { 918 | if (bytes_left > setup_header.length) 919 | bytes_left = setup_header.length; 920 | ep0Status = EP_TX; 921 | } 922 | break; 923 | case GET_CONFIGURATION: 924 | if (setup_header.value || setup_header.index || setup_header.length != 1) { 925 | ep0Status = EP_STALL; 926 | break; 927 | } 928 | pData = &configurationValue; 929 | bytes_left = 1; 930 | ep0Status = EP_TX; 931 | break; 932 | case GET_INTERFACE: 933 | if (usbState != DEV_CONFIGURED || setup_header.requestType != RT_IN_INTERFACE || setup_header.value || (setup_header.length != 1)) { 934 | ep0Status = EP_STALL; 935 | break; 936 | } 937 | pData = (unsigned char __xdata *)&pAlternateSetting[setup_header.index]; 938 | bytes_left = 1; 939 | ep0Status = EP_TX; 940 | break; 941 | case SYNCH_FRAME: 942 | default: 943 | ep0Status = EP_STALL; 944 | break; 945 | } 946 | break; 947 | case RT_VEND_OUT: 948 | ep0Status = EP_STALL; 949 | break; 950 | case RT_VEND_IN: 951 | ep0Status = EP_STALL; 952 | break; 953 | case RT_CLASS_OUT: 954 | ProcessFunc = class_out; 955 | class_out(); 956 | break; 957 | case RT_CLASS_IN: 958 | ProcessFunc = class_in; 959 | class_in(); 960 | break; 961 | default: 962 | ep0Status = EP_STALL; 963 | break; 964 | } 965 | USBCS0 = (ep0Status == EP_STALL) ? (USBCS0_CLR_OUTPKT_RDY | USBCS0_SEND_STALL) : USBCS0_CLR_OUTPKT_RDY; 966 | } 967 | } 968 | if (ep0Status == EP_TX) { 969 | controlReg = USBCS0_INPKT_RDY; 970 | if (bytes_left < EP0_PACKET_SIZE) { 971 | bytesNow = bytes_left; 972 | controlReg |= USBCS0_DATA_END; 973 | } else { 974 | bytesNow = EP0_PACKET_SIZE; 975 | } 976 | usb_write_fifo_0(pData, bytesNow); 977 | pData += bytesNow; 978 | bytes_left -= bytesNow; 979 | 980 | USBCS0 = controlReg; 981 | 982 | if (bytesNow < EP0_PACKET_SIZE) { 983 | if (ProcessFunc) 984 | ProcessFunc(); 985 | ep0Status = EP_IDLE; 986 | } 987 | 988 | } 989 | USBINDEX = oldEndpoint; 990 | EA=0; 991 | } 992 | do_next: 993 | if (eventMaskIn&USBIIE_INEP5IE) { 994 | USBINDEX = 5; 995 | if (!(USBCSIL&USBCSIL_INPKT_RDY)) { 996 | EA = 1; 997 | usb_can_send_5(); 998 | EA=0; 999 | } 1000 | } 1001 | if (eventMaskOut&USBOIE_OUTEP5IE) { 1002 | eventMaskOut &= ~USBOIE_OUTEP5IE; 1003 | USBINDEX = 5; 1004 | if (USBCSOL&USBCSOL_OUTPKT_RDY) { 1005 | EA = 1; 1006 | usb_has_data_5(); 1007 | EA=0; 1008 | } 1009 | } 1010 | if (eventMaskOut&USBOIE_OUTEP4IE) { 1011 | eventMaskOut &= ~USBOIE_OUTEP4IE; 1012 | } 1013 | if (eventMaskOut&USBOIE_OUTEP3IE) { 1014 | eventMaskOut &= ~USBOIE_OUTEP3IE; 1015 | } 1016 | if (eventMaskIn&USBIIE_INEP4IE) { 1017 | eventMaskIn &= ~USBIIE_INEP4IE; 1018 | USBINDEX = 4; 1019 | if (USBCSOL&USBCSOL_OUTPKT_RDY) { 1020 | EA = 1; 1021 | usb_has_data_4(); 1022 | EA=0; 1023 | } 1024 | } 1025 | if (eventMaskIn&USBIIE_INEP3IE) { 1026 | eventMaskIn &= ~USBIIE_INEP3IE; 1027 | USBINDEX = 3; 1028 | if (USBCSOL&USBCSOL_OUTPKT_RDY) { 1029 | EA = 1; 1030 | usb_has_data_3(); 1031 | EA=0; 1032 | } 1033 | } 1034 | if (eventMaskIn&USBIIE_INEP2IE) { 1035 | eventMaskIn &= ~USBIIE_INEP2IE; 1036 | USBINDEX = 2; 1037 | if (USBCSOL&USBCSOL_OUTPKT_RDY) { 1038 | EA = 1; 1039 | usb_has_data_2(); 1040 | EA=0; 1041 | } 1042 | } 1043 | if (eventMaskIn&USBIIE_INEP1IE) { 1044 | eventMaskIn &= ~USBIIE_INEP1IE; 1045 | USBINDEX = 1; 1046 | if (USBCSOL&USBCSOL_OUTPKT_RDY) { 1047 | EA = 1; 1048 | usb_has_data_1(); 1049 | EA=0; 1050 | } 1051 | } 1052 | if (eventMaskCtrl&USBCIF_SUSPENDIF) { 1053 | eventMaskCtrl &= ~USBCIF_SUSPENDIF; 1054 | EA=1; 1055 | 1056 | // Take the chip into PM1 until a USB resume is detected. 1057 | //usbsuspEnter(); 1058 | 1059 | EA=0; 1060 | eventMaskCtrl &= ~USBCIF_RESUMEIF; 1061 | EA=1; 1062 | continue; 1063 | } 1064 | EA=1; 1065 | break; 1066 | } 1067 | } 1068 | -------------------------------------------------------------------------------- /usb.h: -------------------------------------------------------------------------------- 1 | #ifndef USB_H 2 | #define USB_H 3 | // USBADDR 4 | #define USBADDR_UPDATE 0x80 5 | #define USBADDR_USBADDR 0x7F 6 | 7 | // USBPOW 8 | #define USBPOW_ISO_WAIT_SOF 0x80 9 | #define USBPOW_RST 0x08 10 | #define USBPOW_RESUME 0x04 11 | #define USBPOW_SUSPEND 0x02 12 | #define USBPOW_SUSPEND_EN 0x01 13 | 14 | // USBIIF 15 | #define USBIIF_INEP5IF 0x20 16 | #define USBIIF_INEP4IF 0x10 17 | #define USBIIF_INEP3IF 0x08 18 | #define USBIIF_INEP2IF 0x04 19 | #define USBIIF_INEP1IF 0x02 20 | #define USBIIF_EP0IF 0x01 21 | 22 | // USBOIF 23 | #define USBOIF_OUTEP5IF 0x20 24 | #define USBOIF_OUTEP4IF 0x10 25 | #define USBOIF_OUTEP3IF 0x08 26 | #define USBOIF_OUTEP2IF 0x04 27 | #define USBOIF_OUTEP1IF 0x02 28 | 29 | // USBCIF 30 | #define USBCIF_SOFIF 0x08 31 | #define USBCIF_RSTIF 0x04 32 | #define USBCIF_RESUMEIF 0x02 33 | #define USBCIF_SUSPENDIF 0x01 34 | 35 | // USBIIE 36 | #define USBIIE_INEP5IE 0x20 37 | #define USBIIE_INEP4IE 0x10 38 | #define USBIIE_INEP3IE 0x08 39 | #define USBIIE_INEP2IE 0x04 40 | #define USBIIE_INEP1IE 0x02 41 | #define USBIIE_EP0IE 0x01 42 | 43 | // USBOIE 44 | #define USBOIE_OUTEP5IE 0x20 45 | #define USBOIE_OUTEP4IE 0x10 46 | #define USBOIE_OUTEP3IE 0x08 47 | #define USBOIE_OUTEP2IE 0x04 48 | #define USBOIE_OUTEP1IE 0x02 49 | 50 | // USBCIE 51 | #define USBCIE_SOFIE 0x08 52 | #define USBCIE_RSTIE 0x04 53 | #define USBCIE_RESUMEIE 0x02 54 | #define USBCIE_SUSPENDIE 0x01 55 | 56 | // USBCS0 57 | #define USBCS0_CLR_SETUP_END 0x80 58 | #define USBCS0_CLR_OUTPKT_RDY 0x40 59 | #define USBCS0_SEND_STALL 0x20 60 | #define USBCS0_SETUP_END 0x10 61 | #define USBCS0_DATA_END 0x08 62 | #define USBCS0_SENT_STALL 0x04 63 | #define USBCS0_INPKT_RDY 0x02 64 | #define USBCS0_OUTPKT_RDY 0x01 65 | 66 | // USBCSIL 67 | #define USBCSIL_CLR_DATA_TOG 0x40 68 | #define USBCSIL_SENT_STALL 0x20 69 | #define USBCSIL_SEND_STALL 0x10 70 | #define USBCSIL_FLUSH_PACKET 0x08 71 | #define USBCSIL_UNDERRUN 0x04 72 | #define USBCSIL_PKT_PRESENT 0x02 73 | #define USBCSIL_INPKT_RDY 0x01 74 | 75 | // USBCSIH 76 | #define USBCSIH_AUTOSET 0x80 77 | #define USBCSIH_ISO 0x40 78 | #define USBCSIH_FORCE_DATA_TOG 0x08 79 | #define USBCSIH_IN_DBL_BUF 0x01 80 | 81 | // USBCSOL 82 | #define USBCSOL_CLR_DATA_TOG 0x80 83 | #define USBCSOL_SENT_STALL 0x40 84 | #define USBCSOL_SEND_STALL 0x20 85 | #define USBCSOL_FLUSH_PACKET 0x10 86 | #define USBCSOL_DATA_ERROR 0x08 87 | #define USBCSOL_OVERRUN 0x04 88 | #define USBCSOL_FIFO_FULL 0x02 89 | #define USBCSOL_OUTPKT_RDY 0x01 90 | 91 | // USBCSOH 92 | #define USBCSOH_AUTOCLEAR 0x80 93 | #define USBCSOH_ISO 0x40 94 | #define USBCSOH_OUT_DBL_BUF 0x01 95 | 96 | #define SLEEP_USB_EN 0x80 97 | 98 | // USBCTRL 99 | #define USBCTRL_PLL_LOCKED 0x80 100 | #define USBCTRL_PLL_EN 0x02 101 | #define USBCTRL_USB_EN 0x01 102 | 103 | struct device_desc { 104 | unsigned char bLength; 105 | unsigned char bDescriptorType; 106 | unsigned int bcdUSB; 107 | unsigned char bDeviceClass; 108 | unsigned char bDeviceSubClass; 109 | unsigned char bDeviceProtocol; 110 | unsigned char bMaxPacketSize0; 111 | unsigned int idVendor; 112 | unsigned int idProduct; 113 | unsigned int bcdDevice; 114 | unsigned char iManufacturer; 115 | unsigned char iProduct; 116 | unsigned char iSerialNumber; 117 | unsigned char bNumConfigurations; 118 | }; 119 | 120 | struct configuration_desc { 121 | unsigned char bLength; 122 | unsigned char bDescriptorType; 123 | unsigned int wTotalLength; 124 | unsigned char bNumInterfaces; 125 | unsigned char bConfigurationValue; 126 | unsigned char iConfiguration; 127 | unsigned char bmAttributes; 128 | unsigned char bMaxPower; 129 | }; 130 | 131 | struct interface_desc { 132 | unsigned char bLength; 133 | unsigned char bDescriptorType; 134 | unsigned char bInterfaceNumber; 135 | unsigned char bAlternateSetting; 136 | unsigned char bNumEndpoints; 137 | unsigned char bInterfaceClass; 138 | unsigned char bInterfaceSubClass; 139 | unsigned char bInterfaceProtocol; 140 | unsigned char iInterface; 141 | } ; 142 | 143 | struct endpoint_desc { 144 | unsigned char bLength; 145 | unsigned char bDescriptorType; 146 | unsigned char bEndpointAddress; 147 | unsigned char bmAttributes; 148 | unsigned int wMaxPacketSize; 149 | unsigned char bInterval; 150 | }; 151 | 152 | struct string_desc { 153 | unsigned char bLength; 154 | unsigned char bDescriptorType; 155 | unsigned int pString[1]; 156 | }; 157 | 158 | #define EP0_PACKET_SIZE 32 159 | 160 | #define DESC_TYPE_DEVICE 1 161 | #define DESC_TYPE_CONFIG 2 162 | #define DESC_TYPE_STRING 3 163 | #define DESC_TYPE_INTERFACE 4 164 | #define DESC_TYPE_ENDPOINT 5 165 | 166 | #define EP_ATTR_CTRL 0 167 | #define EP_ATTR_ISO 1 168 | #define EP_ATTR_BULK 2 169 | #define EP_ATTR_INT 3 170 | #define EP_ATTR_TYPE_BM 3 171 | 172 | #define CDC_SEND_ENCAPSULATED_COMMAND 0x00 173 | #define CDC_GET_ENCAPSULATED_RESPONSE 0x01 174 | #define CDC_SET_COMM_FEATURE 0x02 //optional 175 | #define CDC_GET_COMM_FEATURE 0x03 //optional 176 | #define CDC_CLEAR_COMM_FEATURE 0x04 //optional 177 | #define CDC_SET_LINE_CODING 0x20 //optional 178 | #define CDC_GET_LINE_CODING 0x21 //optional 179 | #define CDC_SET_CONTROL_LINE_STATE 0x22 //optional 180 | #define CDC_SEND_BREAK 0x23 //optional 181 | 182 | #define CDC_CHAR_FORMAT_1_STOP_BIT 0 183 | #define CDC_CHAR_FORMAT_1_5_STOP_BIT 1 184 | #define CDC_CHAR_FORMAT_2_STOP_BIT 2 185 | 186 | #define CDC_PARITY_TYPE_NONE 0 187 | #define CDC_PARITY_TYPE_ODD 1 188 | #define CDC_PARITY_TYPE_EVEN 2 189 | #define CDC_PARITY_TYPE_MARK 3 190 | #define CDC_PARITY_TYPE_SPACE 4 191 | 192 | #define CDC_DEVICE 0x02 193 | #define COMM_INTF 0x02 194 | 195 | #define ABSTRACT_CONTROL_MODEL 0x02 196 | #define V25TER 0x01 197 | #define DATA_INTF 0x0A 198 | #define NO_PROTOCOL 0x00 199 | 200 | #define ABSTRACT_STATE 0x01 201 | #define COUNTRY_SETTING 0x02 202 | 203 | #define CS_INTERFACE 0x24 204 | #define CS_ENDPOINT 0x25 205 | 206 | #define DSC_FN_HEADER 0x00 207 | #define DSC_FN_CALL_MGT 0x01 208 | #define DSC_FN_ACM 0x02 209 | #define DSC_FN_DLM 0x03 210 | #define DSC_FN_TELEPHONE_RINGER 0x04 211 | #define DSC_FN_RPT_CAPABILITIES 0x05 212 | #define DSC_FN_UNION 0x06 213 | #define DSC_FN_COUNTRY_SELECTION 0x07 214 | #define DSC_FN_TEL_OP_MODES 0x08 215 | #define DSC_FN_USB_TERMINAL 0x09 216 | 217 | #define CDC_COMM_INTF_ID 0x00 218 | #define CDC_DATA_INTF_ID 0x01 219 | 220 | 221 | 222 | extern unsigned char __code descs[]; 223 | extern unsigned char __xdata * __data pData; 224 | extern unsigned int __data bytes_left; 225 | extern unsigned char __pdata usbState; ///< USB device state 226 | extern unsigned char __xdata configurationValue; ///< Current configuration value 227 | extern unsigned char __xdata pAlternateSetting[5]; ///< Current alternate settings 228 | extern unsigned char __pdata ep0Status; ///< Endpoint 0 status 229 | extern unsigned char __pdata pEpInStatus[5]; ///< Endpoint 1-5 IN status 230 | extern unsigned char __pdata pEpOutStatus[5]; 231 | extern unsigned char __pdata remoteWakeup; 232 | #define selfPowered 0 233 | 234 | struct sh { 235 | unsigned char requestType; 236 | unsigned char request; 237 | unsigned int value; 238 | unsigned int index; 239 | unsigned int length; 240 | }; 241 | extern struct sh __pdata setup_header; 242 | 243 | struct lc { 244 | unsigned long baudRate; 245 | unsigned char charFormat; 246 | unsigned char parityType; 247 | unsigned char dataBits; 248 | }; 249 | 250 | extern struct lc __xdata line_config; 251 | 252 | void usb_read_fifo_5(unsigned char __xdata *p, unsigned char l); 253 | void usb_read_fifo_4(unsigned char __xdata *p, unsigned char l); 254 | void usb_read_fifo_3(unsigned char __xdata *p, unsigned char l); 255 | void usb_write_fifo_5(unsigned char __xdata *p, unsigned char l); 256 | void usb_write_fifo_4(unsigned char __xdata *p, unsigned char l); 257 | void usb_write_fifo_3(unsigned char __xdata *p, unsigned char l); 258 | void usb_has_data_5(); 259 | void usb_has_data_4(); 260 | void usb_has_data_3(); 261 | void usb_can_send_5(); 262 | void usb_can_send_4(); 263 | void usb_can_send_3(); 264 | void flush_in_3(); 265 | void flush_in_4(); 266 | void flush_in_5(); 267 | void cdc_init(unsigned long baudrate); 268 | void usb_init(); 269 | 270 | extern __bit cdcRTS_3, cdcRTS_4, cdcRTS_5; 271 | 272 | #define EP_IDLE 0 273 | #define EP_TX 1 274 | #define EP_RX 2 275 | #define EP_HALT 3 276 | #define EP_STALL 4 277 | #define EP_MANUAL_TX 5 278 | #define EP_MANUAL_RX 6 279 | #define EP_CANCEL 7 280 | 281 | #define DEV_ATTACHED 0 282 | #define DEV_POWERED 1 283 | #define DEV_DEFAULT 2 284 | #define DEV_ADDRESS 3 285 | #define DEV_CONFIGURED 4 286 | #define DEV_SUSPENDED 5 287 | 288 | #define RT_MASK_DIR 0x80 289 | #define RT_MASK_TYPE 0x60 290 | #define RT_MASK_RECIP 0x1F 291 | 292 | #define RT_DIR_IN 0x80 293 | #define RT_DIR_OUT 0x00 294 | 295 | #define RT_TYPE_STD 0x00 296 | #define RT_TYPE_CLASS 0x20 297 | #define RT_TYPE_VEND 0x40 298 | 299 | #define RT_RECIP_DEV 0x00 300 | #define RT_RECIP_IF 0x01 301 | #define RT_RECIP_EP 0x02 302 | #define RT_RECIP_OTHER 0x03 303 | 304 | #define RT_STD_OUT (RT_TYPE_STD | RT_DIR_OUT) 305 | #define RT_STD_IN (RT_TYPE_STD | RT_DIR_IN) 306 | #define RT_VEND_OUT (RT_TYPE_VEND | RT_DIR_OUT) 307 | #define RT_VEND_IN (RT_TYPE_VEND | RT_DIR_IN) 308 | #define RT_CLASS_OUT (RT_TYPE_CLASS | RT_DIR_OUT) 309 | #define RT_CLASS_IN (RT_TYPE_CLASS | RT_DIR_IN) 310 | 311 | #define RT_OUT_DEVICE (RT_DIR_OUT | RT_RECIP_DEV) 312 | #define RT_IN_DEVICE (RT_DIR_IN | RT_RECIP_DEV) 313 | #define RT_OUT_INTERFACE (RT_DIR_OUT | RT_RECIP_IF) 314 | #define RT_IN_INTERFACE (RT_DIR_IN | RT_RECIP_IF) 315 | #define RT_OUT_ENDPOINT (RT_DIR_OUT | RT_RECIP_EP) 316 | #define RT_IN_ENDPOINT (RT_DIR_IN | RT_RECIP_EP) 317 | 318 | 319 | #define GET_STATUS 0x00 320 | #define CLEAR_FEATURE 0x01 321 | #define SET_FEATURE 0x03 322 | #define SET_ADDRESS 0x05 323 | #define GET_DESCRIPTOR 0x06 324 | #define SET_DESCRIPTOR 0x07 325 | #define GET_CONFIGURATION 0x08 326 | #define SET_CONFIGURATION 0x09 327 | #define GET_INTERFACE 0x0A 328 | #define SET_INTERFACE 0x0B 329 | #define SYNCH_FRAME 0x0C 330 | 331 | #define ENDPOINT_HALT 0x00 332 | #define DEVICE_REMOTE_WAKEUP 0x01 333 | 334 | extern void class_in(); 335 | extern void class_out(); 336 | extern void change_uart_mode(); 337 | extern void prog_setup(); 338 | #endif 339 | 340 | -------------------------------------------------------------------------------- /val/validate.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2015 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | // 20 | // This code handles the extra anti-tamper feature of RNG 21 | // essentially it works this way: 22 | // 23 | // 1) OneRNG device flash is protected so we can't read it from the debug interface 24 | // but we can erase (all of) it 25 | // 26 | // 2) when we program it we put a known random value in the first 96 bytes of 27 | // the last 128 bytes of it 16 bytes 'ID, 16 bytes 'K', 64 bytes 'S' 28 | // 29 | // 3) user asks device for a its 'ID' from bytes 0:15 of this area 'cmdI' 30 | // returns '!!iiiiii....iiii!' where iiii...iiii is 32 hex digits 31 | // 32 | // 4) user provides 'ID' to the OneRNG web site 33 | // a) it generates a 16 byte token 'T' 34 | // b) caches the tuple ('ID'/'T') - TTL 2 minutes 35 | // c) and returns 'T' to the user 36 | // 37 | // 5) when asked for a confirmation a OneRNG is given the token 'T' 'cmdRtttt....tttt' 38 | // (ttt....tttt is 32 hex digits) and: 39 | // a) use the bytes 16:31 of the region as an AES128 key 'K' 40 | // b) encrypt a 2 block nonce of random data 'R' (32 bytes) -> 'ER' 41 | // c) encrypt (chained) 2 blocks of token 'T' (32 bytes) -> 'ET' 42 | // d) encrypt (chained) the final 32:95 bytes of the region 'S' (64 bytes) -> 'ES' 43 | // e) offer the resulting 128 bytes from the encryption to the host 'ER'+'ET'+'ES' 44 | // 45 | // 6) user presents bytes 0:15 of the user data 'ID' and bytes 0:63 of the encrypted data 'ER'+'ET' to OneRNG's web page 46 | // 47 | // 7) OneRNG's server: 48 | // a) wait a random time (to hide error cause info) 49 | // b) inspects its database of manufactured devices using the key from bytes 16-31 'ID' 50 | // c) if 'ID' isn't in the DB return an error 51 | // d) retrieves bytes 0-95 'K'+'ID'+'S' that were programmed into the device 52 | // e) decrypts 'ER' using 'K' giving nonce 'R' (discarded) 53 | // f) decrypts (chained) 'ET' using 'K' giving 'T' 54 | // g) if 'T' doesn't match returns an error 55 | // h) reencrypts 'R'+'T'+'S' using 'K' giving 'ER'+'ET'+'ES' 56 | // i) returns 'ES' to user 57 | // j) tells user how many times it has offered up results for this id (to record 58 | // potential replay attacks) 59 | // 60 | // 8) User compares 'ES' from user's OneRNG with value that OneRNG delivered in step 5d) 61 | // gets worried if they are not the same 62 | // 63 | // (we allow this to be done manually but we also provide a python script) 64 | // 65 | // The basic idea is that we have a shared secret K+S (ID is essentially a secret id) 66 | // we tell the server we know the key by encrypting something it does know with K (T) and return 67 | // the encrypted second secret S - the user compares the encrypted second secret (ES) with the 68 | // one the OneRNG gave it 69 | // 70 | // We also use T to stop replay attacks (where someone records a good transaction from another 71 | // OneRNG and replays it from a compromised one) 72 | // 73 | // In other words: 74 | // 75 | // step OneRNG web host/user User's OneRNG 76 | // 77 | // 3) 'ID'<-'ID' 78 | // 79 | // 4) 'ID'<-'ID' 80 | // 'T'->'T' 81 | // 82 | // 5) 'T'->'T' 83 | // 'ER'+'ET'+'ESa'<-'R'+'T'+'S' 84 | // 85 | // 6) 'ID'+'ER'+'ET'<-'ID'+''ER'+'ET' 86 | // 87 | // 7) 'ID'+'ER'+'ET'->'R'+'T'->'ESb' 88 | // 'ESa'=='ESb' 89 | // 90 | 91 | #include 92 | #include 93 | #include "task.h" 94 | #include "interface.h" 95 | 96 | #define AES_ENCRYPT 0x00 97 | #define AES_DECRYPT 0x02 98 | #define AES_LOAD_KEY 0x04 99 | #define AES_LOAD_IV 0x06 100 | #define AES_MODE_CBC 0x00 101 | 102 | unsigned char __xdata token[16]; 103 | static __bit tmpb; 104 | extern __bit no_avalanche; 105 | extern __xdata unsigned char *__data pool_out; 106 | extern unsigned char __xdata pool[]; 107 | extern unsigned int __data pool_count; 108 | static void out_hex(); 109 | 110 | void 111 | start_encrypt() __naked 112 | { 113 | __asm; // u8 i; 114 | mov _FMAP, #7 // ptr = 0x 115 | mov dptr, #0xff80+16 116 | mov _ENCCS, #AES_LOAD_KEY|AES_MODE_CBC // ENCCS = ES_LOAD_KEY|AES_MODE_CBC 117 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 118 | mov r0, #16 // for (i=0; i<16; i++) 119 | 0002$: clr a 120 | movc a, @a+dptr// ENCDI = *key++; 121 | inc dptr 122 | mov _ENCDI, a 123 | djnz r0, 0002$ 124 | 0001$: mov a, _ENCCS // aes_done(); 125 | jnb _ACC_3, 0001$ 126 | 127 | mov dptr, #0xff80 128 | mov _ENCCS, #AES_LOAD_IV|AES_MODE_CBC // ENCCS = ES_LOAD_IV|AES_MODE_CBC 129 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 130 | mov r0, #16 // for (i=0; i<16; i++) 131 | 0004$: clr a 132 | movc a, @a+dptr// ENCDI = *key++; 133 | inc dptr 134 | mov _ENCDI, a 135 | djnz r0, 0004$ 136 | 0003$: mov a, _ENCCS // aes_done(); 137 | jnb _ACC_3, 0003$ 138 | ret 139 | __endasm; 140 | } 141 | 142 | void 143 | sync_header() __naked 144 | { 145 | __asm; 146 | mov dptr, #_USBF5 // start with '@@@@@@@@' 147 | mov a, #'@' 148 | mov r0, #8 // for (i = 0; i < 8; i++) 149 | 0044$: movx @dptr, a // USBF5 = '@' 150 | djnz r0, 0044$ 151 | ret 152 | __endasm; 153 | } 154 | 155 | void 156 | send_id_block() __naked 157 | { 158 | __asm; 159 | mov dptr, #_USBF5 160 | inc _DPS 161 | mov dptr, #0xff80 162 | mov r0, #16 // for (i = 0; i < 16; i++) 163 | 0004$: clr a 164 | movc a, @a+dptr // USBF5 = *id++; 165 | inc dptr 166 | dec _DPS 167 | lcall _out_hex 168 | inc _DPS 169 | djnz r0, 0004$ 170 | 171 | dec _DPS 172 | ret 173 | __endasm; 174 | } 175 | 176 | void 177 | encrypt_random_block() __naked 178 | { 179 | __asm; 180 | mov dptr, #_USBF5 // start with '@@@@@@@@' 181 | mov a, #'@' 182 | mov r0, #8 // for (i = 0; i < 8; i++) 183 | 0044$: movx @dptr, a // USBF5 = '@' 184 | djnz r0, 0044$ 185 | mov c, _no_avalanche // tmpb = no_avalanche; 186 | mov _tmpb, c 187 | clr _no_avalanche // no_avalanche = 0; 188 | 0002$: mov a, _pool_count+1 // while (pool_count < 32) 189 | jnz 0001$ 190 | mov a, _pool_count 191 | anl a, #0xe0 192 | jnz 0001$ 193 | lcall _idle_pool // idle_pool(); 194 | sjmp 0002$ 195 | 0001$: 196 | mov c, _tmpb // idle_pool = tmpb; 197 | mov _no_avalanche, c 198 | 199 | mov r1, #2 // for (j = 0 j < 2; j++) { 200 | 0077$: 201 | mov dpl, _pool_out 202 | mov dph, _pool_out+1 203 | 204 | mov _ENCCS, #AES_MODE_CBC|AES_ENCRYPT // ENCCS = AES_MODE_CBC|AES_ENCRYPT 205 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 206 | mov r0, #16 // for (i=0; i<16; i++) 207 | 0004$: movx a, @dptr // ENCDI = *pool_out++; 208 | mov _ENCDI, a 209 | inc dptr 210 | mov a, dpl // if (pool_out == &pool[POOL_SIZE]) 211 | cjne a, #_pool+POOL_SIZE, 0011$ 212 | mov a, dph // pool_out = &pool[0]; 213 | cjne a, #(_pool+POOL_SIZE)>>8, 0011$ 214 | mov dptr, #_pool 215 | 0011$: 216 | djnz r0, 0004$ 217 | mov _pool_out, dpl 218 | mov _pool_out+1, dph 219 | 220 | clr c 221 | mov a, _pool_count // pool_count -= 16; 222 | subb a, #16 223 | mov _pool_count, a 224 | mov a, _pool_count+1 225 | subb a, #0 226 | mov _pool_count+1, a 227 | 228 | mov r0, #32 // wait_us(1); 229 | 0111$: djnz r0, 0111$ 230 | 231 | mov dptr, #_USBF5 232 | mov r0, #16 // for (i=0; i<16; i++) 233 | 0014$: mov a, _ENCDO // *USBF5 = hex(*ENCDO) 234 | lcall _out_hex 235 | djnz r0, 0014$ 236 | 0013$: mov a, _ENCCS // aes_done(); 237 | jnb _ACC_3, 0013$ 238 | djnz r1, 0077$ // } 239 | 240 | ret 241 | __endasm; 242 | } 243 | 244 | static void 245 | out_hex() __naked // dptr is dest, a is value, r7 is free 246 | { 247 | __asm; 248 | mov r7, a 249 | swap a 250 | anl a, #0x0f 251 | cjne a, #9, 1$ 252 | 2$: add a, #'0' 253 | sjmp 3$ 254 | 1$: jc 2$ 255 | add a, #('A'-10) 256 | 3$: movx @dptr, a 257 | 258 | mov a, r7 259 | anl a, #0x0f 260 | cjne a, #9, 11$ 261 | 12$: add a, #'0' 262 | sjmp 13$ 263 | 11$: jc 12$ 264 | add a, #('A'-10) 265 | 13$: movx @dptr, a 266 | ret 267 | __endasm; 268 | } 269 | 270 | void 271 | encrypt_token() __naked 272 | { 273 | __asm; 274 | mov dptr, #_token 275 | mov _ENCCS, #AES_MODE_CBC|AES_ENCRYPT // ENCCS = AES_MODE_CBC|AES_ENCRYPT 276 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 277 | mov r0, #16 // for (i=0; i<16; i++) 278 | 0004$: movx a, @dptr // ENCDI = *pool_out++; 279 | mov _ENCDI, a 280 | inc dptr 281 | djnz r0, 0004$ 282 | 283 | mov r0, #32 // wait_us(1); 284 | 0011$: djnz r0, 0011$ 285 | 286 | mov dptr, #_USBF5 287 | mov r0, #16 // for (i=0; i<16; i++) 288 | 0014$: mov a, _ENCDO // *USBF5 = hex(*ENCDO) 289 | lcall _out_hex 290 | djnz r0, 0014$ 291 | 0013$: mov a, _ENCCS // aes_done(); 292 | jnb _ACC_3, 0013$ 293 | // 294 | 295 | ret 296 | __endasm; 297 | } 298 | 299 | 300 | void 301 | encrypt_secret_blocks() __naked 302 | { 303 | __asm; 304 | mov _FMAP, #7 // ptr = 0x 305 | //mov dptr, #0xff80+32 // in dptr at call time 306 | mov _DPL, #_USBF5 307 | mov _DPH, #_USBF5>>8 308 | 309 | mov r1, #2 // for (j = 0 j < 4; j++) { 310 | 0077$: 311 | 312 | mov _ENCCS, #AES_MODE_CBC|AES_ENCRYPT// ENCCS = AES_MODE_CBC|AES_ENCRYPT 313 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 314 | mov r0, #16 // for (i=0; i<16; i++) 315 | 0004$: clr a 316 | movc a, @a+dptr // ENCDI = *secret++; 317 | mov _ENCDI, a 318 | inc dptr 319 | djnz r0, 0004$ 320 | 321 | mov r0, #32 // wait_us(1); 322 | 0011$: djnz r0, 0011$ 323 | 324 | inc _DPS 325 | mov r0, #16 // for (i=0; i<16; i++) 326 | 0014$: mov a, _ENCDO // *USBF5 = hex(*ENCDO) 327 | lcall _out_hex 328 | djnz r0, 0014$ 329 | dec _DPS 330 | 0013$: mov a, _ENCCS // aes_done(); 331 | jnb _ACC_3, 0013$ 332 | djnz r1, 0077$ // } 333 | 334 | ret 335 | __endasm; 336 | } 337 | -------------------------------------------------------------------------------- /validate.c: -------------------------------------------------------------------------------- 1 | // (c) Copyright Paul Campbell paul@taniwha.com 2015 2 | // 3 | // This library is free software; you can redistribute it and/or 4 | // modify it under the terms of the GNU Lesser General Public 5 | // License as published by the Free Software Foundation; either 6 | // version 2.1 of the License, or (at your option) version 3, or any 7 | // later version accepted by Paul Campbell , who shall 8 | // act as a proxy defined in Section 6 of version 3 of the license. 9 | // 10 | // This library 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 GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library. If not, see . 17 | // 18 | 19 | // 20 | // This code handles the extra anti-tamper feature of RNG 21 | // essentially it works this way: 22 | // 23 | // 1) OneRNG device flash is protected so we can't read it from the debug interface 24 | // but we can erase (all of) it 25 | // 26 | // 2) when we program it we put a known random value in the first 96 bytes of 27 | // the last 128 bytes of it 16 bytes 'ID, 16 bytes 'K', 64 bytes 'S' 28 | // 29 | // 3) user asks device for a its 'ID' from bytes 0:15 of this area 'cmdI' 30 | // returns '@@@@@@iiiiii....iiii!' where iiii...iiii is 32 hex digits 31 | // 32 | // 4) user provides 'ID' to the OneRNG web site 33 | // a) it generates a 16 byte token 'T' 34 | // b) caches the tuple ('ID'/'T') - TTL 2 minutes 35 | // c) and returns 'T' to the user 36 | // 37 | // 5) when asked for a confirmation a OneRNG is given the token 'T' 'cmdRtttt....tttt' 38 | // (ttt....tttt is 32 hex digits) and: 39 | // a) use the bytes 16:31 of the region as an AES128 key 'K' 40 | // b) encrypt a 1 block nonce of random data 'R' (16 bytes) -> 'ER' 41 | // c) encrypt (chained) 1 blocks of token 'T' (16 bytes) -> 'ET' 42 | // d) encrypt (chained) the final 32:95 bytes of the region 'S' (64 bytes) -> 'ES' 43 | // e) offer the resulting 96 bytes from the encryption to the host 'ER'+'ET'+'ES' 44 | // 45 | // 6) user presents bytes 0:15 of the user data 'ID' and bytes 0:31 of the encrypted data 'ER'+'ET' to OneRNG's web page 46 | // 47 | // 7) OneRNG's server: 48 | // a) wait a random time (to hide error cause info) 49 | // b) inspects its database of manufactured devices using the key from bytes 16-31 'ID' 50 | // c) if 'ID' isn't in the DB return an error 51 | // d) retrieves bytes 0-95 'K'+'ID'+'S' that were programmed into the device 52 | // e) decrypts 'ER' using 'K' giving nonce 'R' (discarded) 53 | // f) decrypts (chained) 'ET' using 'K' giving 'T' 54 | // g) if 'T' doesn't match returns an error 55 | // h) reencrypts 'R'+'T'+'S' using 'K' giving 'ER'+'ET'+'ES' 56 | // i) returns 'ES' to user 57 | // j) tells user how many times it has offered up results for this id (to record 58 | // potential replay attacks) 59 | // 60 | // 8) User compares 'ES' from user's OneRNG with value that OneRNG delivered in step 5d) 61 | // gets worried if they are not the same 62 | // 63 | // (we allow this to be done manually but we also provide a python script) 64 | // 65 | // The basic idea is that we have a shared secret K+S (ID is essentially a secret id) 66 | // we tell the server we know the key by encrypting something it does know with K (T) and return 67 | // the encrypted second secret S - the user compares the encrypted second secret (ES) with the 68 | // one the OneRNG gave it 69 | // 70 | // We also use T to stop replay attacks (where someone records a good transaction from another 71 | // OneRNG and replays it from a compromised one) 72 | // 73 | // In other words: 74 | // 75 | // step OneRNG web host/user User's OneRNG 76 | // 77 | // 3) 'ID'<-'ID' 78 | // 79 | // 4) 'ID'<-'ID' 80 | // 'T'->'T' 81 | // 82 | // 5) 'T'->'T' 83 | // 'ER'+'ET'+'ESa'<-'R'+'T'+'S' 84 | // 85 | // 6) 'ID'+'ER'+'ET'<-'ID'+''ER'+'ET' 86 | // 87 | // 7) 'ID'+'ER'+'ET'->'R'+'T'->'ESb' 88 | // 'ESa'=='ESb' 89 | // 90 | 91 | #include 92 | #include 93 | #include "task.h" 94 | #include "interface.h" 95 | 96 | #define AES_ENCRYPT 0x00 97 | #define AES_DECRYPT 0x02 98 | #define AES_LOAD_KEY 0x04 99 | #define AES_LOAD_IV 0x06 100 | #define AES_MODE_CBC 0x00 101 | 102 | unsigned char __xdata token[16]; 103 | static __bit tmpb; 104 | extern __bit no_avalanche; 105 | extern __xdata unsigned char *__data pool_out; 106 | extern unsigned char __xdata pool[]; 107 | extern unsigned int __data pool_count; 108 | static void out_hex(); 109 | 110 | void 111 | start_encrypt() __naked 112 | { 113 | __asm; // u8 i; 114 | mov _FMAP, #7 // ptr = 0x 115 | mov dptr, #0xff80+16 116 | mov _ENCCS, #AES_LOAD_KEY|AES_MODE_CBC // ENCCS = ES_LOAD_KEY|AES_MODE_CBC 117 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 118 | mov r0, #16 // for (i=0; i<16; i++) 119 | 0002$: clr a 120 | movc a, @a+dptr// ENCDI = *key++; 121 | inc dptr 122 | mov _ENCDI, a 123 | djnz r0, 0002$ 124 | 0001$: mov a, _ENCCS // aes_done(); 125 | jnb _ACC_3, 0001$ 126 | 127 | mov dptr, #0xff80 128 | mov _ENCCS, #AES_LOAD_IV|AES_MODE_CBC // ENCCS = ES_LOAD_IV|AES_MODE_CBC 129 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 130 | mov r0, #16 // for (i=0; i<16; i++) 131 | 0004$: clr a 132 | movc a, @a+dptr// ENCDI = *key++; 133 | inc dptr 134 | mov _ENCDI, a 135 | djnz r0, 0004$ 136 | 137 | 0003$: mov a, _ENCCS // aes_done(); 138 | jnb _ACC_3, 0003$ 139 | ret 140 | __endasm; 141 | } 142 | 143 | void 144 | crlf() __naked 145 | { 146 | __asm; 147 | mov dptr, #_USBF5 // start with '/n@@@@@@@@' 148 | mov a, #'\r' 149 | movx @dptr, a // USBF5 = '\r' 150 | mov a, #'\n' 151 | movx @dptr, a // USBF5 = '\n' 152 | ret 153 | __endasm; 154 | } 155 | void 156 | sync_header() __naked 157 | { 158 | __asm; 159 | mov dptr, #_USBF5 // start with '/n@@@@@@@@' 160 | mov a, #'_' 161 | mov r0, #8 // for (i = 0; i < 8; i++) 162 | 0044$: movx @dptr, a // USBF5 = '@' 163 | djnz r0, 0044$ 164 | ret 165 | __endasm; 166 | } 167 | 168 | void 169 | send_id_block() __naked 170 | { 171 | __asm; 172 | mov dptr, #_USBF5 173 | inc _DPS 174 | mov dptr, #0xff80 175 | mov r0, #16 // for (i = 0; i < 16; i++) 176 | 0004$: clr a 177 | movc a, @a+dptr // USBF5 = *id++; 178 | inc dptr 179 | dec _DPS 180 | lcall _out_hex 181 | inc _DPS 182 | djnz r0, 0004$ 183 | 184 | dec _DPS 185 | ret 186 | __endasm; 187 | } 188 | 189 | void 190 | encrypt_random_block() __naked 191 | { 192 | __asm; 193 | mov dptr, #_USBF5 // start with '@@@@@@@@' 194 | 0077$: 195 | mov _ENCCS, #AES_MODE_CBC|AES_ENCRYPT // ENCCS = AES_MODE_CBC|AES_ENCRYPT 196 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 197 | mov r0, #16 // for (i=0; i<16; i++) { 198 | 0004$: mov r1, #16 // rand = 0 199 | clr a // for (j = 0; j < 16; j++) { 200 | 0005$: mov c, p1.7 // rand = (rand<<1)|p1.7 201 | rlc a 202 | jnc 0015$ // rand = (rand&0xff)^(rand>>8) 203 | xrl a, #1 204 | 0015$: // } 205 | djnz r1, 0005$ 206 | mov _ENCDI, a // ENCDI = rand 207 | 0011$: // } 208 | djnz r0, 0004$ 209 | 210 | mov r0, #255 // wait_us(1); 211 | 0111$: djnz r0, 0111$ 212 | 213 | mov dptr, #_USBF5 214 | mov r0, #16 // for (i=0; i<16; i++) 215 | 0014$: mov a, _ENCDO // *USBF5 = hex(*ENCDO) 216 | lcall _out_hex 217 | djnz r0, 0014$ 218 | 0013$: mov a, _ENCCS // aes_done(); 219 | jnb _ACC_3, 0013$ 220 | ret 221 | __endasm; 222 | } 223 | 224 | static void 225 | out_hex() __naked // dptr is dest, a is value, r7 is free 226 | { 227 | __asm; 228 | mov r7, a 229 | swap a 230 | anl a, #0x0f 231 | cjne a, #9, 1$ 232 | 2$: add a, #'0' 233 | sjmp 3$ 234 | 1$: jc 2$ 235 | add a, #('A'-10) 236 | 3$: movx @dptr, a 237 | 238 | mov a, r7 239 | anl a, #0x0f 240 | cjne a, #9, 11$ 241 | 12$: add a, #'0' 242 | sjmp 13$ 243 | 11$: jc 12$ 244 | add a, #('A'-10) 245 | 13$: movx @dptr, a 246 | ret 247 | __endasm; 248 | } 249 | 250 | void 251 | encrypt_token() __naked 252 | { 253 | __asm; 254 | mov dptr, #_token 255 | mov _ENCCS, #AES_MODE_CBC|AES_ENCRYPT // ENCCS = AES_MODE_CBC|AES_ENCRYPT 256 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 257 | mov r0, #16 // for (i=0; i<16; i++) 258 | 0004$: movx a, @dptr // ENCDI = *pool_out++; 259 | mov _ENCDI, a 260 | inc dptr 261 | djnz r0, 0004$ 262 | 263 | mov r0, #255 // wait_us(1); 264 | 0011$: djnz r0, 0011$ 265 | 266 | mov dptr, #_USBF5 267 | mov r0, #16 // for (i=0; i<16; i++) 268 | 0014$: mov a, _ENCDO // *USBF5 = hex(*ENCDO) 269 | lcall _out_hex 270 | djnz r0, 0014$ 271 | 0013$: mov a, _ENCCS // aes_done(); 272 | jnb _ACC_3, 0013$ 273 | ret 274 | 275 | __endasm; 276 | } 277 | 278 | 279 | void 280 | encrypt_secret_blocks() __naked 281 | { 282 | __asm; 283 | clr _DPS 284 | mov _FMAP, #7 // ptr = 0x 285 | //mov dptr, #0xff80+32 // in dptr at call time 286 | mov _DPL1, #_USBF5 287 | mov _DPH1, #_USBF5>>8 288 | 289 | mov r1, #2 // for (j = 0 j < 4; j++) { 290 | 0077$: 291 | mov _ENCCS, #AES_MODE_CBC|AES_ENCRYPT// ENCCS = AES_MODE_CBC|AES_ENCRYPT 292 | orl _ENCCS, #1 // ENCCS |= 0x01; // start 293 | mov r0, #16 // for (i=0; i<16; i++) 294 | 0004$: clr a 295 | movc a, @a+dptr // ENCDI = *secret++; 296 | mov _ENCDI, a 297 | inc dptr 298 | djnz r0, 0004$ 299 | 300 | mov r0, #255 // wait_us(1); 301 | 0011$: djnz r0, 0011$ 302 | 303 | inc _DPS 304 | mov r0, #16 // for (i=0; i<16; i++) 305 | 0014$: mov a, _ENCDO // *USBF5 = hex(*ENCDO) 306 | lcall _out_hex 307 | djnz r0, 0014$ 308 | dec _DPS 309 | 0013$: mov a, _ENCCS // aes_done(); 310 | jnb _ACC_3, 0013$ 311 | djnz r1, 0077$ // } 312 | ret 313 | __endasm; 314 | } 315 | --------------------------------------------------------------------------------