├── .gitignore ├── BUILD.txt ├── COPYING.txt ├── LICENSE_GPL.txt ├── Makefile ├── Makefile.inc ├── README.md ├── TODO ├── config ├── config.ini ├── devices.dat ├── fx2_kim_dump.hex ├── fx2lp_fw.hex └── nm.hex ├── docs ├── gen_config └── romdata.txt └── src ├── Makefile ├── Makefile.inc ├── libhex ├── HexData.cpp ├── HexData.h ├── Makefile ├── testmyhex.cpp └── utils.h ├── libini ├── HierINIReader.cpp ├── HierINIReader.h ├── INIReader.cpp ├── INIReader.h ├── LICENSE.txt ├── Makefile ├── README.kim ├── ini.c └── ini.h ├── programmer ├── AppData.cpp ├── AppData.h ├── DeviceData.cpp ├── DeviceData.h ├── HexFileFormat.h ├── Makefile ├── Programmer.cpp ├── Programmer.h ├── fx2.cpp ├── fx2.h ├── prog.cpp ├── usb.c ├── usb.h ├── utils.c ├── utils.h └── version.h ├── support ├── app_config.c └── config_data.h ├── tests ├── Makefile └── support │ ├── Makefile │ ├── config_data.c │ ├── test.bin │ ├── test.conf │ ├── test.hex │ ├── test1.ref │ └── test_config_data.c └── tools ├── Makefile ├── freehex2other.py ├── gen_config.py ├── hex2bin.cpp ├── hexinfo.cpp └── mergehex.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | lib*.a 10 | 11 | # Packages # 12 | ############ 13 | # it's better to unpack these files and commit the raw source 14 | # git has its own built in compression methods 15 | *.7z 16 | *.dmg 17 | *.gz 18 | *.iso 19 | *.jar 20 | *.rar 21 | *.tar 22 | *.zip 23 | 24 | # Logs and databases # 25 | ###################### 26 | *.log 27 | #*.sql 28 | #*.sqlite 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | .DS_Store? 34 | ._* 35 | .Spotlight-V100 36 | .Trashes 37 | ehthumbs.db 38 | Thumbs.db 39 | 40 | # specific files 41 | hex2bin 42 | hexinfo 43 | mergehex 44 | prog 45 | testmyhex 46 | bin 47 | -------------------------------------------------------------------------------- /BUILD.txt: -------------------------------------------------------------------------------- 1 | make 2 | make install 3 | 4 | As configured 'make install' creates a local bin directory (at the top level dir) and this folder is assumed as the path used by PSOC_compiler demos. 5 | Note that make install only works from the top level folder. 6 | 7 | Other targets 8 | make clean 9 | 10 | some folder have test programs that can be built. They are not built by default. 11 | -------------------------------------------------------------------------------- /COPYING.txt: -------------------------------------------------------------------------------- 1 | All is published under GPL with the exception of libini. 2 | libini is published under the New BSD license. See the libini directory. 3 | 4 | Copyright (C) 2014 Kim Lester 5 | http://www.dfusion.com.au/ 6 | 7 | This Program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This Program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this Program. If not, see . 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | 3 | export TOPDIR := $(shell echo $$PWD) 4 | export INSTALL_DIR=$(TOPDIR)/bin 5 | 6 | .PHONY: all install clean 7 | 8 | all install clean:: 9 | for dir in $(SUBDIRS); do \ 10 | $(MAKE) -C $$dir $@; \ 11 | done 12 | 13 | clean:: 14 | $(RM) ./bin/* 15 | -------------------------------------------------------------------------------- /Makefile.inc: -------------------------------------------------------------------------------- 1 | SUBDIRS ?= 2 | 3 | .PHONY: all install clean 4 | 5 | all install clean:: 6 | @for dir in $(SUBDIRS); do \ 7 | echo Make $@ in subdir: $$dir; \ 8 | $(MAKE) -C $$dir $(DEFS) $@; \ 9 | done 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##PSOC_programmer 2 | 3 | #####Summary 4 | Open source Unix tools to manipulate hex files and program a PSoC5 (ARM) via FX2 USB interface. 5 | 6 | #####Purpose 7 | * Tools to manipulate Intel hex files 8 | * Configure the FX2 USB interface on the CY8CKIT. 9 | * Program a hex file into a PSoC5 (ARM). 10 | 11 | 12 | #####Requirements 13 | * A Cypress CY8CKIT-050 dev kit, however some of the tools are of more general use. 14 | * Developed on OS X, however it is expected to run under Linux (not yet tested) 15 | 16 | #####See Also 17 | * https://github.com/kiml/PSOC_compiler.git 18 | * http://dfusion.com.au/wiki/ The ARM Embedded pages: 19 | - PSoC5 bare metal 20 | - PSoC5 programmer 21 | - GCC Linker 22 | 23 | #####Additional Uses 24 | * A useful general purpose Intel hex manipulation library (libhex) 25 | 26 | #####License 27 | * All code is released under GPL v3 except for: 28 | - libini a the third party library that is released with changes under its original New BSD license. 29 | 30 | #####Raison d'Etre 31 | * Cypress put out a free but closed source MS Windows development environment. They do provide GCC but pretty much everything else is proprietary which is fine but: 32 | - I like the PSoC feature set (basically ARM CPU, mxied signal FPGA, decent analogue) 33 | - I wanted to learn more about internals of the ARM Cortex M3 chip used 34 | - I wanted to program the PSoC under Unix. 35 | 36 | Short version - the mountain was there so I climbed it :-) 37 | 38 | #####Tools 39 | 40 | `prog CMD` 41 | Talk to a PSoC ARM device. CMD is: 42 | ``` 43 | program filename - program device 44 | upload filename - read device and save in file 45 | verify filename - verify device 46 | reset - reset device 47 | erase - erase device 48 | id - get jtag id 49 | usb_clear - clear USB error on device 50 | help - display help 51 | ``` 52 | 53 | `hex2bin infile.hex outfile.bin` 54 | Converts intel hex files into binary files (note binary files may be quite large) 55 | 56 | `hexinfo filename.hex` 57 | Dumps PSoC specific hex file into something slighly more readable. 58 | 59 | ``` 60 | mergehex (-[cdemnp] infile.hex)+ [-o outfile.hex] 61 | mergehex (-[cdemnp] infile.hex)+ > outfile.hex 62 | Eg: mergehex -c infile.hex -nm config.hex > outfile.hex 63 | ``` 64 | Merge a newly compiled .hex program file with additional PSoC specific .hex 65 | configuration info to create a programmable hex file. 66 | This is an interim tool - ideally the additional configuration info comes 67 | from human readable config files rather than .hex snippets. 68 | 69 | `freehex2other[.py] [-h] -f OUTPUT_FORMAT [-i INFILE] [-o OUTFILE]` 70 | Convert ASCII hex bytes to other formats 71 | 72 | optional arguments: 73 | -h, --help show this help message and exit 74 | -f OUTPUT_FORMAT output format: hex,intelhex,binary 75 | -i INFILE input file. Default stdin 76 | -o OUTFILE output file. Default stdout 77 | 78 | 79 | `gen_config[.py] [-h] -f OUTPUT_FORMAT [-i INFILE] [-o OUTFILE]` 80 | Compile config data into freehex file format 81 | 82 | optional arguments: 83 | -h, --help show this help message and exit 84 | -i INFILE input file 85 | -o OUTFILE output file. Default stdout 86 | 87 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | ** LICENSE 2 | ** set confi dir = bindir/../config 3 | ** clean up source 4 | 5 | * As at Aug14 running program once results in a stall. If i run ataing I get timeouts. clearing stall fixes this so prog 0; prog 0 (FAILS). prog 0; prog 9; prog 0; WORKS. Also replace 0 with 8.... 6 | 7 | * NOTE: my remainder code for fractions of blocks etc may have a bug in it. Check completion on exactly boundary cases 8 | Corrected: int count = (remainder && i==num_blocks-1) ? remainder : blocksize; !? 9 | * need a tool to convert bin to augmented hex (note can use objcopy to convert elf to bin or hex but not enough for programming). Maybe take multiple files as imputs (eg program, config_data, registers 10 | * move configuration code into a hex file - DONE 11 | * read hex file to write flash (check 001-81290 pdf A.1 for details of hex format files and header lines) 12 | * verify 13 | * Maybe add a num cmds counter to request so we can auto-pop the correct number of replies (although we need to understand which have data... 14 | * annotate a hex file (to std out) also for reader. Define config settings etc. A.4 and TRM 43.4 etc 15 | * exit programming mode. 16 | * make sure we don't get timeouts (ie add robustness) 17 | * compare functionality of programmer with windows version 18 | * Can I access Software SW* debug? 19 | * When interface falls over (STALL): "The host tells the firmware to set or clear the stall condition for an end- point using the Set Feature/Stall and Clear Feature/Stall requests. Once the firmware stalls an endpoint, it should not remove the stall until the host issues a Clear Feature/Stall request. An exception to this rule is endpoint 0, which reports a stall condition only for the current transaction and then automatically clears the stall condition." 20 | * Using SWD I may be able to actually control peripherals... 42.3.4 21 | 22 | * Handle 256 and 288 byte data formats - 256 NOT TESTED 23 | * read psoc and put into a hex file. - DONE but need to test reflashing uploaded file 24 | * simplify control info sent to programmer device. - DONE !? 25 | * write config_flash - DONE !? 26 | 27 | * write_flash - DONE 28 | * compile arm code and download it to PSOC. (what arm set etc) - DONE 29 | * Doesn't know where to find hex config file - done 30 | * erase sector, all - DONE 31 | * sort out command line options - DONE 32 | * create a program struct that contains all data (config checksum etc. I think currently it's place in magic locations in HEX file) - DONE !? 33 | 34 | 35 | PSoC programming need 36 | ---------------- 37 | * register list header file of all regs 38 | * mapping of jtag id to device name 39 | * maybe copies of precanned logic blocks 40 | * need a config file format for each I/O pin 41 | 42 | 43 | * Demos 44 | * Use UDB PLDs (ch 23.3) to create logic . Can data path be memory mapped ? Can I write a value and read logic results? Can I attach UDB to memory bus and trigger a counter on a certain variable being changed !? 45 | pg 155. Could do a CRC hardware engine in for s/w. Dynamic config etc. 46 | 47 | 48 | ============ 49 | Tools 50 | 51 | 1) psoc_ctrl CMD args 52 | // * load file.hex 53 | // * save file.hex 54 | * program/download [file.hex] 55 | * upload [file.hex] 56 | * verify [file.hex] 57 | * psoc_reset 58 | * enter_programming_mode 59 | // * exit_programming_mode 60 | * usb_reset 61 | * debug... 62 | * read_mem ... 63 | * read_reg [NVL|WOL...]... 64 | // * write_mem ... 65 | Option to ';' separate commands on command line: "load file.x;download;verify;reset;" 66 | next only works if prev succeeds 67 | 68 | * CMD: file:file.hex to psoc[:subsystem] 69 | * CMD: file.hex:prog, file.hex:data, file.hex:prot file.hex:regs to psoc[:subsystem] 70 | * CMD: psoc[:subsystem] to file:file.hex 71 | 72 | 73 | 1) psoc_hexfile CMD args 74 | Any file can have extension .hex for hex or .bin for binary or do I determine input type auto but not so output type... ? 75 | * CMD: -c psoc5lp-xyz -p file.hex -d file.hex -s file.hex -r file.hex [-o file.hex] or stdout 76 | * CMD: -c config -i file.hex [-o file.hex|bin] 77 | * CMD: file.hex, -d file.hex, -s file.hex -r file.hex -o file.hex 78 | also a splitter... ? 79 | 80 | * CMD: -c config -i|-ip|-id|-is|-ir file.hex [-o|-op|-od|-os|-or file.hex|bin] 81 | * CMD: -c config [-i(.pdsr) file]* [-o(.pdsr) file]* 82 | 83 | ------- 84 | 85 | buildhex could take a config file for misc args also on command line rather than from hex files 86 | -------------------------------------------------------------------------------- /config/config.ini: -------------------------------------------------------------------------------- 1 | [Programmer] 2 | 3 | fx2_config_file = fx2_kim_dump.hex 4 | -------------------------------------------------------------------------------- /config/devices.dat: -------------------------------------------------------------------------------- 1 | flash_rows_per_array = 256; 2 | 3 | flash_code_bytes_per_row = 256; 4 | flash_config_bytes_per_row = 32; 5 | 6 | flash_rows_per_protection_byte = 4; 7 | 8 | eeprom_bytes_per_row = 16; 9 | 10 | flash_code_base_address = 0x000000; 11 | flash_config_base_address = 0x800000; // 0x4..800000 ? 12 | eeprom_base_address = 0x40008000; 13 | 14 | [PSOC5LP-xxx] 15 | 16 | flash_num_arrays = 4; 17 | flash_size = 262144; 18 | eeprom_size = 2048; // FIXME: CORRECT THIS (depends on part #) 19 | -------------------------------------------------------------------------------- /config/fx2lp_fw.hex: -------------------------------------------------------------------------------- 1 | :03000000020357A1 2 | :03000B00021D686B 3 | :0200330061FA70 4 | :03004300020500B3 5 | :03005300020500A3 6 | :10020000BB010689828A83E0225002E722BBFE02FC 7 | :10021000E32289828A83E49322BB010CE58229F5DB 8 | :1002200082E5833AF583E0225006E92582F8E6224A 9 | :10023000BBFE06E92582F8E222E58229F582E58304 10 | :100240003AF583E49322BB010689828A83F0225027 11 | :1002500002F722BBFE01F322F8BB010DE58229F56E 12 | :1002600082E5833AF583E8F0225006E92582C8F654 13 | :1002700022BBFE05E92582C8F222BC000BBE002984 14 | :10028000EF8DF084FFADF022E4CCF875F008EF2F8D 15 | :10029000FFEE33FEEC33FCEE9DEC984005FCEE9D4A 16 | :1002A000FE0FD5F0E9E4CEFD22EDF8F5F0EE842066 17 | :1002B000D21CFEADF075F008EF2FFFED33FD4007C7 18 | :1002C000985006D5F0F222C398FD0FD5F0EA22A38C 19 | :1002D000F8E0C5F025F0F0E582158270021583E0A4 20 | :1002E000C838F0E8227401FF3395E0FEFDFC0808F1 21 | :1002F00008E62FFFF618E63EFEF618E63DFDF61876 22 | :10030000E63CFCF622D083D082F8E49370127401AC 23 | :1003100093700DA3A393F8740193F5828883E4731B 24 | :100320007402936860EFA3A3A380DFEF4E6012EF27 25 | :1003300060010EEDBB010B89828A83F0A3DFFCDE36 26 | :10034000FA2289F05007F709DFFCA9F022BBFEFC76 27 | :10035000F309DFFCA9F022787FE4F6D8FD75812F40 28 | :1003600002039E0206EFE493A3F8E493A34003F68E 29 | :100370008001F208DFF48029E493A3F85407240CE9 30 | :10038000C8C333C4540F4420C8834004F4568001CA 31 | :1003900046F6DFE4800B010204081020408090053F 32 | :1003A000B8E47E019360BCA3FF543F30E509541FBD 33 | :1003B000FEE493A360010ECF54C025E060A840B8CE 34 | :1003C000E493A3FAE493A3F8E493A3C8C582C8CA4C 35 | :1003D000C583CAF0A3C8C582C8CAC583CADFE9DE1F 36 | :1003E000E780BE00010202030304040505E5AA201C 37 | :1003F000E003121D9F22D322D32253D8EF32D322FF 38 | :100400001201000200000040B4042BF13900010386 39 | :1004100002010A06000200000040010009023C003F 40 | :1004200001010080FA0904000006FF000000070532 41 | :100430000103400010070581034000100705020278 42 | :100440000002000705840200020007058602000280 43 | :10045000000705080200020009023C0001010080BB 44 | :10046000320904000006FF000000070501034000F8 45 | :100470001007058103400010070502024000000735 46 | :1004800005840240000007058602400000070508B9 47 | :1004900002400000040309041003430079007000C7 48 | :1004A0007200650073007300260347004600580081 49 | :1004B00032004C0050003500350035003500350065 50 | :1004C000350035003500370038003900410014038D 51 | :1004D0004600580032004C0050002D0047004500F7 52 | :1004E0004E00000090E60AE054F0600A90E50DE04E 53 | :1004F000C330E403D322D322C20490E6BAE022320E 54 | :100500000212000002122E0002121C000212400011 55 | :1005100002125400021280000204FF000212BD0009 56 | :100520000212BE000212BF000212C0000212C1007D 57 | :100530000212C2000212C3000212C4000212C5005D 58 | :100540000212C6000212BD000212C7000212C80049 59 | :100550000212C9000212CA000212CB000212CC0021 60 | :100560000212CD000212BD000212BD000212BD0037 61 | :100570000212CE000212CF000212D0000212D100ED 62 | :100580000212D2000212D3000212D4000212D500CD 63 | :100590000212D6000212D7000212D8000212D900AD 64 | :1005A0000212DA000212DB000212DC000212DD008D 65 | :1005B0000212DE000212DF0041E0B00144E09DDEE5 66 | :1005C000ADBEEF41E0980041E0990041E09A00495A 67 | :1005D000E049373131316900000E3149E02B3737BE 68 | :1005E0003737000000003744E0381002050044E0CF 69 | :1005F00042A9307EEA41E0B50041E0B601008E0C30 70 | :100600008F0D90E600E054187012E50D2401FFE410 71 | :10061000350CC313F50CEF13F50D801590E600E0D3 72 | :100620005418FFBF100BE50D25E0F50DE50C33F573 73 | :100630000CE50D150DAE0C7002150C4E6005120682 74 | :10064000DE80EE2230040990E680E0440AF0800764 75 | :1006500090E680E04408F07FDC7E051205FE90E61F 76 | :100660005D74FFF090E65FF05391EF90E680E05408 77 | :10067000F7F02290E682E030E004E020E60B90E61E 78 | :1006800082E030E119E030E71590E680E04401F0C7 79 | :100690007F147E001205FE90E680E054FEF022A951 80 | :1006A00007AE2DAF2E8F828E83A3E064037017AD4B 81 | :1006B0000119ED7001228F828E83E07C002FFDEC0A 82 | :1006C0003EFEAF0580DFE4FEFF2290E682E044C0FC 83 | :1006D000F090E681F04387010000000000227400E2 84 | :1006E000F58690FDA57C05A3E582458370F922E49B 85 | :1006F000F50BF50AF509F508C203C200C202C201F2 86 | :10070000120BB8752304752400752B04752C127513 87 | :10071000210475221C752904752A58752D04752E1F 88 | :1007200094D2E843D82090E668E04409F090E65C73 89 | :10073000E0443DF0D2AF12115490E680E020E10495 90 | :10074000D204D14490E680E054F7F0538EF8C2030F 91 | :1007500071ED300104F183C2013003F471F650F001 92 | :10076000C203D1CA20001690E682E030E704E02000 93 | :10077000E1F090E682E030E604E020E0E5D173713C 94 | :10078000F880CD90E6B9E0700302083314700302DC 95 | :10079000087C24FE70030208CF24FB700302082F9C 96 | :1007A00014700302082B14607A14607B2405600324 97 | :1007B000020907120F79400302091290E6BBE024F8 98 | :1007C000FE602914603A24FD60111460292406702B 99 | :1007D00050E52390E6B3F0E524803E91E440030227 100 | :1007E0000902E52B90E6B3F0E52C802DE52590E697 101 | :1007F000B3F0E5268023E52790E6B3F0E5288019DD 102 | :1008000090E6BAE0FF12069FAA06A9077B01EA4913 103 | :100810004B600CEE90E6B3F0EF90E6B4F0211221BD 104 | :10082000022102D1A52112F1902112F1882112D1C9 105 | :10083000902112F17B4002211290E6B8E0247F6003 106 | :100840001514601924027032A200E43325E0FFA2DF 107 | :1008500002E4334F8016E490E740F08014B1F44096 108 | :10086000047D0180027D00D11AE0540190E740F040 109 | :10087000E4A3F0D19D7402F021122102F17D400227 110 | :10088000211290E6B8E024FE6013240260022112D7 111 | :1008900090E6BAE0B40104C2008077806590E6BAC1 112 | :1008A000E0702AB1F440047D0180027D00D11AE09D 113 | :1008B00054FEF090E6BCE05480131313541FFFE085 114 | :1008C000540F2F90E683F0E04420F080458033F110 115 | :1008D0007F503F90E6B8E024FE6019240270239018 116 | :1008E000E6BAE0B40104D200802890E6BAE06402DF 117 | :1008F0006020800EB1F440047D0180027D00D11A99 118 | :10090000800C90E6A080073114500790E6A0E044E8 119 | :1009100001F0C112D204C20590E6B9E01203050944 120 | :10092000834009854109834209904309C74409CDA1 121 | :100930004509CD4609CD4709CD4809CD490A874A21 122 | :100940000A874B0A874C0A874D0A874E09CD4F0903 123 | :10095000D15009EC5109EC520A87530A875409F027 124 | :10096000550A34560A6E570A76580A875B0A875C1E 125 | :100970000A8F5F0AA9600ABA610A1F640B2D6A0018 126 | :10098000000A8780481204F8543F90E097F0411D18 127 | :100990001204F830E70CA3E090E0A7F0D14B9111DE 128 | :1009A000800F90E6BAE0543FFF7B017AE079A7918F 129 | :1009B0003890E0A8EFF090E0A8E0B40104D14B41FA 130 | :1009C000837D017F0161B3C20491B161B5C204802E 131 | :1009D0004CC204E490E68BF090E6A0E020E1F97BC5 132 | :1009E000017AE77940F1A212115441B2C20441B236 133 | :1009F0001204F890E056F0E024F9601724FA600B36 134 | :100A000014701890E027745AF0801290E027747DDB 135 | :100A1000F0800A90E02774FAF08002D1C141B2124E 136 | :100A200004F8600843B3045390FB800643900453DA 137 | :100A3000B3FB807EC20490E6B9E0FD90E027E0FBC6 138 | :100A4000E4F510F511FF915A90E6B9E0FD90E056FB 139 | :100A5000E0F510E4F511FB7F01915A90E6B9E0FD55 140 | :100A6000751001751101E4FB7F02915A61B5120402 141 | :100A7000F8FD7F39802FC2047F39B1E090E0A7E014 142 | :100A8000FD7F39D1AD61B5C2047D037F0261B31230 143 | :100A900004F890E0B6F07F11B1E090E0A7E04414D4 144 | :100AA000F0E0FD7F1191116129C20490E092E030E5 145 | :100AB000E20280757D067F0461B31204F8703591FF 146 | :100AC00030EF70067D027F0361B390E0A7E054F73A 147 | :100AD000B1D970067D027F0361B3B1E870067D0273 148 | :100AE0007F0361B390E0A7E0543FB1D2703B7D0239 149 | :100AF0007F0361B39130EF70067D027F0361B39095 150 | :100B0000E0A7E04408B1D970067D027F0361B3B16C 151 | :100B1000E870067D027F0361B390E0A7E044C0B1B6 152 | :100B2000D270067D027F0361B3D13B61B5E4F50C61 153 | :100B30007440250CF582E434E7F583E4F0050CE518 154 | :100B40000CB440EC90E740746AF0E4A3F090E03C11 155 | :100B5000E090E742F090E03DE090E743F090E03E27 156 | :100B6000E090E744F090E03FE090E745F090E098B7 157 | :100B7000E090E746F090E099E090E747F090E09A47 158 | :100B8000E090E748F0E490E68AF000000090E68B01 159 | :100B90007410F0000000C204D112E490E03CF0A315 160 | :100BA000F0A3F0A3F090E09AF090E099F090E09834 161 | :100BB000F08002D158A2042290E600E054E74412EB 162 | :100BC000F090E60174C0F090E60B7403F0D1CEF122 163 | :100BD00098C2061212E0E490E09BF090E03604F038 164 | :100BE000E490E035F090E0B2F090E0B1F090E0B643 165 | :100BF000F090E0AFF090E026F0D1C153B1FE53B1D8 166 | :100C0000FD43B60F90E029E4F0A37440F043AF0732 167 | :100C100022AE07AF05EEC39440501274582ED1880F 168 | :100C2000EFF0EE24F070031213417F01227F0022C7 169 | :100C30007AE079A77B017F10EFC394405019EF242D 170 | :100C4000EE700890E09CE090E06AF074582FD18834 171 | :100C5000E01202467F01227F00228F0D8D0E8B0F46 172 | :100C6000EF75F004A42440F974E735F0FA7B01E451 173 | :100C7000120246D16BE50E120258900002E50F12E7 174 | :100C80000258E510D1B5E50D90E0B770057404F099 175 | :100C90008004E02404F0E5116016E490E68AF00098 176 | :100CA000000090E0B7E090E68BF0E490E0B7D1115F 177 | :100CB00022750D01750EE7750F407E007F0E7D00D9 178 | :100CC000B1CB12032BD13F12020054F7120246445B 179 | :100CD000101202464420120246440412024654FCFA 180 | :100CE000440212024690E056E0B1CB90000212029C 181 | :100CF0005890E027E0900003120258900004E4129C 182 | :100D0000025890E097E0543F90000512025890007E 183 | :100D10000512021914601024FD600C24FC600824E4 184 | :100D2000FC6004240C705A7AE079A99134EF7027A2 185 | :100D3000D13F120200FFC413135401FDEF54BFFF53 186 | :100D4000ED44015401C4333354C04F120246B1CBB9 187 | :100D500074031202468033B1CB900005120219646D 188 | :100D600001600D90E0A9E07F0120E3027F00800B8D 189 | :100D700090E0A9E07F0020E3027F0190000BEF806C 190 | :100D800006B1CB90000BE4120258B1CB90000C746A 191 | :100D9000FF12025890000D74FF1202589000087460 192 | :100DA000FF12025890000974FF12025890E058E0B8 193 | :100DB00090000A120258900006E4120258900007B0 194 | :100DC0007401120258D19C740E8046AB0DAA0EA974 195 | :100DD0000F22FD7F119111EF22FD7F109111EF2263 196 | :100DE0007B017AE079A781387B017AE079A77F11CE 197 | :100DF0009138EF2290E6BCE0547EFF7E00E0D39471 198 | :100E0000807C0022120258E490E68AF0740290E698 199 | :100E10008BF090E6A0E04480F022EC4EFEED4F24F3 200 | :100E2000E3F58274033EF583E493FF3395E0FEEF30 201 | :100E300024A1FFEE34E68F82F58322D16480C5AB16 202 | :100E40000DE50F2401F9E4350EFA2290E6BAE054DC 203 | :100E50003FFF90E0A7E0FD227B017AE77940EFD1E8 204 | :100E60006BED80A07B017AE77940E41202469000A6 205 | :100E70000122AE03D164EF120258900002ED12027B 206 | :100E800058EED1B574048086F582E434E0F583220F 207 | :100E9000E51AD19804F0D32290E740F0E490E68A76 208 | :100EA000F090E68B22E519D19804F0D322AB05AD82 209 | :100EB000077F4380BD900003120258E490E68AF059 210 | :100EC0002290E02774A5F090E056740BF02290E693 211 | :100ED000047480F00000007402F00000007404F05C 212 | :100EE0000000007406F00000007408F0000000E448 213 | :100EF000F000000090E682E054FCF0E044C4F0E42E 214 | :100F000090E670F000000090E61074A0F000000081 215 | :100F100090E611F000000090E61274A2F0000000CC 216 | :100F200090E61374E2F000000090E614F000000078 217 | :100F300090E6157420F0000000E490E618F0000040 218 | :100F40000090E619F000000090E61AF00000009012 219 | :100F5000E61BF000000000000090E602F000000038 220 | :100F600090E603F000000090E6497482F000000073 221 | :100F7000F0000000F1810203FED322D322D322D35A 222 | :100F800022E4F5B175B6FF2290E6BAE0F51AD32255 223 | :100F900090E6BAE0F519D3225389F1438901538EC3 224 | :100FA000F722AB017512067D087C007F508F0D8CF7 225 | :100FB0000E8D0F8A108B11E4F513E513C3951250B3 226 | :100FC0004B1210F4400122C3E50E94014008E50ED7 227 | :100FD0001210FE4001221210FC40081210EC1210F8 228 | :100FE00024C3220511E511AE107002051014F5821C 229 | :100FF0008E83E01210CE4001221210ECAF0D110EC4 230 | :10100000050FE50F7002050E051380AED3228F1475 231 | :101010001124AF14312111D211EC112490E678E0A3 232 | :1010200030E1EF2290E678E020E6F9228F0D8C0E79 233 | :101030008D0F8B108A11891290E67AE054FEF01120 234 | :10104000F4400790E6787440F022C3E50E94014026 235 | :1010500007E50E11FE40012211FC400411EC80C492 236 | :1010600090E6787480F0E50D25E0440111CE400152 237 | :1010700022E513B4010690E6787420F090E679E05A 238 | :10108000F51411D2400122E4F514E514C395135070 239 | :101090003BE51314FFB5140690E6787440F0E513B1 240 | :1010A00024FEB5140690E6787420F090E679E0AB63 241 | :1010B00010AA11A912851482758300120258EF65D7 242 | :1010C00014600511D2400122051480BED32290E69F 243 | :1010D00079F0313B90E678E0FB20E004312F70F4AA 244 | :1010E000EB20E20431477002C322D32290E678E07D 245 | :1010F0004440F0221124AF0D31218006E50F90E627 246 | :1011000079F0313B90E678E0FB20E004312F70F479 247 | :10111000EB20E20431477002C322EBD320E101C38C 248 | :101120002290E6787480F0EF25E090E679F022785E 249 | :101130001574FF1202E7EC4D4E4F2274FFF518F5BF 250 | :1011400017F51675150022AF18AE17AD16AC15ECD5 251 | :101150004D4E4F2290E0A97404F0A374B6F07B01C9 252 | :101160007AE079A17513067D087C007F50112C5020 253 | :1011700062E4F9E9C39418505CE91313543F24A1C5 254 | :1011800031E9C431E040027E07E91313543FFDEF1B 255 | :1011900024302EFF31D729F582E43AF583EFF0E9C8 256 | :1011A000240131F2F074A12D31E931E040027E07D3 257 | :1011B000EF24302EFFE92402FDE433FC31D72DF576 258 | :1011C00082EA3CF583EFF0E9240331F2F07404295C 259 | :1011D000F980A0C322D32290E0A9E0FAA3E0FB2289 260 | :1011E000540FFFD394097E0022F582E434E0F583A6 261 | :1011F000E022FFE433FEEB2FF582EA3EF583E422A2 262 | :10120000C0E0C083C082D20151157401F0D082D0F9 263 | :1012100083D0E032F05391EF90E65D22C0E0C083CE 264 | :10122000C08251157404F0D082D083D0E032C0E087 265 | :10123000C083C08251157402F0D082D083D0E032D6 266 | :10124000C0E0C083C082D20351157408F0D082D0B0 267 | :1012500083D0E032C0E0C083C082852925852A265C 268 | :1012600051B2852127852228517651147410F0D06F 269 | :1012700082D083D0E032852882852783A374072219 270 | :10128000C0E0C083C08290E680E030E71185212570 271 | :1012900085222651B2852927852A285176F090E0AB 272 | :1012A000297402F0A3E451147420F0D082D083D0CA 273 | :1012B000E032852682852583A37402F02232323201 274 | :1012C00032323232323232323232323232323232FE 275 | :1012D00032323232323232323232323232323232EE 276 | :1012E000E490E028F090E09C7421F0E490E037F086 277 | :1012F00090E048F090E047F090E057F0FF743C2F0A 278 | :10130000F582E434E0F583E4F074522FF582E4349E 279 | :10131000E0F583E4F00FBF04E47F3F90E059E4F090 280 | :10132000A3DFFC90E05874FFF090E0927403F0E4C7 281 | :1013300090E040F053B5FD53B5FE43B00143B00219 282 | :101340002290E037EFF030E708E0C4540790E04027 283 | :10135000F090E037E04404F022913F715FB1045314 284 | :10136000B5FE90E037E05403601414600D1460067D 285 | :101370008000C2B1D2B1C2B1D2B1C2B1D2B1C2B198 286 | :10138000D2B1228E0F8F10B1DCB1F324FE60201495 287 | :10139000600714601A2403704091E453B0FDE5B077 288 | :1013A0005401F51143B002B1BF602CD113802890D5 289 | :1013B000E037E030E21491E4C2B1D2B1E5B05401BB 290 | :1013C000F511B1BF6011D113800D715FE4FFE4909E 291 | :1013D000E67CF00FBF04F7E149715FD144F022C20F 292 | :1013E000B1A2B092F0D2B1C2B1A2B092F1D2B1C268 293 | :1013F000B1A2B092F2D2B1C2B1A2B092F3D2B1C254 294 | :10140000B1A2B092F4D2B1C2B1A2B092F5D2B1C23F 295 | :10141000B1A2B092F6D2B1C2B1A2B092F7D2B1AF3E 296 | :10142000F02243B50190E67BE0FF913F90E67BE040 297 | :10143000FF913F90E67BE0FF913F90E67BE0FF8FDE 298 | :101440001F851FF0C2B1A2F092B0D2B1C2B1A2F119 299 | :1014500092B0D2B1C2B1A2F292B0D2B1C2B1A2F3F3 300 | :1014600092B0D2B1C2B1A2F492B0D2B1C2B1A2F5DF 301 | :1014700092B0D2B1C2B1A2F692B0D2B1C2B1A2F7CB 302 | :1014800092B0D2B1228D0FEB4A6006B1138F10805B 303 | :101490000690E041E0F510E50F6002B1DCB1F371B8 304 | :1014A0005F90E057E024FE601C24FE601824037067 305 | :1014B0002F9122E510600543B001800353B0FEC2B6 306 | :1014C000B1D2B1801990E037E030E2129122E510FC 307 | :1014D000600543B001800353B0FEC2B1D2B1E1490F 308 | :1014E000D144F02253B5FE71DF90E67CEFF071DF5E 309 | :1014F00090E67CEFF071DF90E67CEFF071DF90E634 310 | :101500007CEFF022B1D590E098B1D2A3B1D2A3F094 311 | :10151000D2B1228E128F13E4F5140513E513700275 312 | :101520000512B140B1CB70020512B140B1CB7002CF 313 | :101530000512B140B1CB70020512B1405401FF2237 314 | :1015400014F5828E83E0FFB14FEF2514F514228F3E 315 | :101550001D751E00E51D30E002051EE51DC313F5D7 316 | :101560001DE51D30E002051EE51DC313F51DE51D3B 317 | :1015700030E002051EE51DC313F51DE51D30E00238 318 | :10158000051EE51DC313F51DE51D30E002051EE532 319 | :101590001DC313F51DE51D30E002051EE51DC31337 320 | :1015A000F51DE51D30E002051EE51DC313F51DE523 321 | :1015B0001D30E002051EE51DC313F51DAF1E22718F 322 | :1015C0005FAF10AE0FB113EF6511220513E513AE37 323 | :1015D0001222F0D2B1C2B1A2B0E4332253B0FE4322 324 | :1015E000B5010000D11BD11B90E028E0FF913F53D3 325 | :1015F000B5FE22715FB10490E099E025E0FF90E034 326 | :1016000098E04FFF90E09AE0FE25E025E04F90E063 327 | :1016100057F02290E09CE04408F022C2B1D2B1C25F 328 | :10162000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C2E2 329 | :10163000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C2D2 330 | :10164000B1D2B12253B5FE43B00143B00290E09C49 331 | :10165000E0440722D16443B5017F9E913F7FE7912B 332 | :101660003F53B5FE43B50290E036E0FFEF7002E174 333 | :101670004243B00143B501C2B1D2B1C2B1D2B1C28D 334 | :10168000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C282 335 | :10169000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C272 336 | :1016A000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C262 337 | :1016B000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C252 338 | :1016C000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C242 339 | :1016D000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C232 340 | :1016E000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C222 341 | :1016F000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C212 342 | :10170000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C201 343 | :10171000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C2F1 344 | :10172000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B1C2E1 345 | :10173000B1D2B1C2B1D2B1C2B1D2B1C2B1D2B15340 346 | :10174000B5FE90E0477401F02253B5FE43B001436B 347 | :10175000B00290E09CE090E057FFE0FEEF4E90E09A 348 | :101760009CF0228B0F8A108911E4FFE4FEF1A05453 349 | :1017700001AB12AA13A914120246F1A0C31312025C 350 | :101780004674012514F514E43513F5130EBE08DD77 351 | :1017900074012511F511E43510F5100FBF04CC22AA 352 | :1017A000AB0FAA10A91102020090E037E0FF90E011 353 | :1017B00000EFF090E001E4F090E037E0FFEF440448 354 | :1017C000FF90E037EFF090E0287499F090E0027419 355 | :1017D00099F090E03C74DBF090E03D7406F090E00E 356 | :1017E0003E740CF090E03F747BF07EE07F3CB113E0 357 | :1017F00090E041EFF07B017AE0793CC003C002C089 358 | :10180000017B017AE079038B128A138914D001D00D 359 | :1018100002D0031217637B017AE0790390E023EB97 360 | :10182000F0A3EAF0A3E9F0751B00E51BC3940440A4 361 | :1018300002414D90E001E0FFEF6002414DE51B7079 362 | :101840003C43B3045390FB43B50243B50143B0019D 363 | :1018500043B002751C00E51CC394045012AF1C7405 364 | :10186000522FF582E434E0F583E4F0051C80E77F35 365 | :10187000647E0091A543900453B3FB800343B501FC 366 | :1018800075F099C2B1A2F092B0D2B1C2B1A2F192F8 367 | :10189000B0D2B1C2B1A2F292B0D2B1C2B1A2F392AF 368 | :1018A000B0D2B1C2B1A2F492B0D2B1C2B1A2F5929B 369 | :1018B000B0D2B1C2B1A2F692B0D2B1C2B1A2F79287 370 | :1018C000B0D2B153B5FEC2B1D2B1C2B1A2B0E4330D 371 | :1018D000FF90E098EFF0D2B1C2B1A2B0E433FF9034 372 | :1018E000E099EFF0D2B1C2B1A2B0E433FF90E09A38 373 | :1018F000EFF0D2B1C2B1D2B143B50175F0DBC2B1E4 374 | :10190000A2F092B0D2B1C2B1A2F192B0D2B1C2B142 375 | :10191000A2F292B0D2B1C2B1A2F392B0D2B1C2B12E 376 | :10192000A2F492B0D2B1C2B1A2F592B0D2B1C2B11A 377 | :10193000A2F692B0D2B1C2B1A2F792B0D2B175F014 378 | :1019400006C2B1A2F092B0D2B1C2B1A2F192B0D2AD 379 | :10195000B1C2B1A2F292B0D2B1C2B1A2F392B0D2EE 380 | :10196000B1C2B1A2F492B0D2B1C2B1A2F592B0D2DA 381 | :10197000B1C2B1A2F692B0D2B1C2B1A2F792B0D2C6 382 | :10198000B175F00CC2B1A2F092B0D2B1C2B1A2F165 383 | :1019900092B0D2B1C2B1A2F292B0D2B1C2B1A2F3AE 384 | :1019A00092B0D2B1C2B1A2F492B0D2B1C2B1A2F59A 385 | :1019B00092B0D2B1C2B1A2F692B0D2B1C2B1A2F786 386 | :1019C00092B0D2B175F07BC2B1A2F092B0D2B1C2E6 387 | :1019D000B1A2F192B0D2B1C2B1A2F292B0D2B1C270 388 | :1019E000B1A2F392B0D2B1C2B1A2F492B0D2B1C25C 389 | :1019F000B1A2F592B0D2B1C2B1A2F692B0D2B1C248 390 | :101A0000B1A2F792B0D2B1C2B190E041E0FFEF24B1 391 | :101A1000FF92B0D2B1C2B153B5FE90E098E0FFEFB3 392 | :101A2000601690E099E0FFEF700E90E09AE0FFEF13 393 | :101A3000700690E0017401F07B017AE0790390E098 394 | :101A400023EBF0A3EAF0A3E9F0051B012A90E001E3 395 | :101A5000E0FFEF7002817B43B5017F8B1213594386 396 | :101A6000B5017B017AE0793890E023EBF0A3EAF04E 397 | :101A7000A3E9F090E023E0FBA3E475F0011202CFAC 398 | :101A8000A9F0FA120200FF12143F90E023E0FBA33A 399 | :101A9000E475F0011202CFA9F0FA120200FF12144D 400 | :101AA0003F90E023E0FBA3E475F0011202CFA9F020 401 | :101AB000FA120200FF12143F90E023E0FBA3E4754A 402 | :101AC000F0011202CFA9F0FA120200FF12143F53E4 403 | :101AD000B0FEC2B1D2B1000053B0FD90E098E0FF7B 404 | :101AE000EF601690E099E0FFEF700E90E09AE0FF53 405 | :101AF000EF700690E0017401F090E001E0FFEF70FC 406 | :101B000002817B43B5017FBB12135943B5017B01B1 407 | :101B10007AE0794290E023EBF0A3EAF0A3E9F090B9 408 | :101B2000E023E0FBA3E475F0011202CFA9F0FA1262 409 | :101B30000200FF12143F90E023E0FBA3E475F001E4 410 | :101B40001202CFA9F0FA120200FF12143F90E02314 411 | :101B5000E0FBA3E475F0011202CFA9F0FA12020033 412 | :101B6000FF12143F90E023E0FBA3E475F0011202A2 413 | :101B7000CFA9F0FA120200FF12143F43B001C2B124 414 | :101B8000D2B1000053B0FD90E098E0FFEF601890F4 415 | :101B9000E099E0FFEF701090E09AE0FFEF7008909E 416 | :101BA000E0017401F080617B017AE07942AE02AF1E 417 | :101BB00001EEFF7E00EF54FFF59A7B017AE0794257 418 | :101BC000AF01EF54FFF59B7FBB12135943B5019052 419 | :101BD000E67BE0FF12143F90E67BE0FF12143F909B 420 | :101BE000E67BE0FF12143F90E67BE0FF12143F908B 421 | :101BF000E041E0FFEF600543B001800353B0FEC257 422 | :101C0000B1D2B1000053B0FD90E001E0FFEF606B96 423 | :101C100090E03CE4F090E02874A5F07B017AE07954 424 | :101C20003CAE02AF01EEFF7E00EF54FFF59D7B015D 425 | :101C30007AE0793CAF01EF54FFF59E7EE07F3C12E5 426 | :101C4000138390E09CE0FFEF20E230751C00E51C60 427 | :101C5000C394045020AF1C743C2FF582E434E0F5AB 428 | :101C600083E0FFAE1C744D2EF582E434E0F583EF83 429 | :101C7000F0051C80D990E0017401F090E001E0FFD4 430 | :101C8000EF600E90E09C7431F090E0477401F080BA 431 | :101C90000B90E09C7427F090E047E4F090E001E0C6 432 | :101CA000FFEF24FF22C20690E0B3E4F0A304F0911A 433 | :101CB000B8200603208CFA22AD07AC06ED4C700369 434 | :101CC000D20622C206ECD3943F40067C007D018000 435 | :101CD00015EDAE047802C333CE33CED8F9FDAC0691 436 | :101CE0006305FF6304FFEDF58AECF58CC28DD2A984 437 | :101CF000D2AFD28C22C20674BFF58A746380EB7FA8 438 | :101D0000107E277C007D0A12027A90E0B3EEF0A3E9 439 | :101D1000EFF04E700790E0B3F0A304F080D7E5AA8F 440 | :101D200020E002D32291FF000000000000E5AA306D 441 | :101D3000E0033006F2300602C322B163D322ED90F5 442 | :101D4000E695F0E5AA20E302D32291FF000000000F 443 | :101D50000000E5AA30E3033006F2300602C322B1E8 444 | :101D600063D322C28CC28D22C0E0C083C082C0D0A7 445 | :101D700075D000C00690E0B4E024FFF090E0B3E03E 446 | :101D800034FFF0E07002A3E07008C28CC28DD2066E 447 | :101D9000800291F5D006D0D0D082D083D0E032E45A 448 | :101DA00090E09CF090E069E0FF20E202C171122116 449 | :101DB000CDEF54FB90E069F090F001E090E038F056 450 | :101DC00090F002E090E039F090F003E090E03AF01B 451 | :101DD00090F004E090E03BF090F006E090E042F0FC 452 | :101DE00090F007E090E043F090F008E090E044F0DD 453 | :101DF00090F009E090E045F01217A990E092E050D1 454 | :101E00000F4404F090E0A774E0F0A37449F0800D53 455 | :101E100054FBF090E0A774E0F0A3742BF01221CDF6 456 | :101E200090E0AD12212C9409EE9400502D90E0A783 457 | :101E3000E475F0011202CF85F082F583E0FD7400B5 458 | :101E40002FF58274F43EF583EDF090E0AEE004F0FF 459 | :101E5000700690E0ADE004F080C6E490E694F000F7 460 | :101E6000000090E0ADA3E090E695F00000000221B4 461 | :101E70001AE5AA30E30302211412219E0000001289 462 | :101E80002171A3F0A3F074F0F59A7400F59B7AF435 463 | :101E900079007EF47F0074F4F59D7400F59EA3E054 464 | :101EA0007004A3E0641E703290F000E0B4F02BA345 465 | :101EB000E0B4F02612165412215590E67C742112DB 466 | :101EC0002137700312212190E0ABE07004A3E0649D 467 | :101ED0000F70E71221BE740F805190E0ADE07004E6 468 | :101EE000A3E06410702D90F000E0B40F26A3E0B4DE 469 | :101EF000012112215590E67B12213370031221211A 470 | :101F000090E0ABE07004A3E0641070E91221BE74AD 471 | :101F100010801890E0ADE07002A3E0701590E09C96 472 | :101F20007440F090E67CF01221BE04F012211A02F7 473 | :101F30002103750D01E50D700302210390E0ADE072 474 | :101F4000FEA3E090E0A912218740030220ECE49078 475 | :101F5000E09C122128ED9FEC9E400A12211AB11E2E 476 | :101F6000500312217F1221AC90E0281221C5700687 477 | :101F700090E0A9E004F090E028E030E20302203F86 478 | :101F8000E4F50C12212990E0AAE09F90E0A9E09EE0 479 | :101F9000401012211AB11E500912219E0000001299 480 | :101FA00021711221ACFF122192EF1221C57006900F 481 | :101FB000E0A9E004F0050CE50CC3940440C590E0F2 482 | :101FC00037E030E72C90E03CE090E06CF090E03DB2 483 | :101FD000E090E06DF090E03EE090E06EF090E03F49 484 | :101FE000E090E06FF090E09CE090E04012175980A4 485 | :101FF00026750E0A74E0F59A743CF59BE490E09C1B 486 | :10200000F07EE07F3C7B01FA7D01121485150EE520 487 | :102010000E6004315D60DD90E09CE04420312831A9 488 | :10202000664010313F000000121D3E50067AF479E0 489 | :1020300000314D90E09C313370023121021F3C9001 490 | :10204000E037E030E73090E06CE090E03CF090E08A 491 | :102050006DE090E03DF090E06EE090E03EF090E0CA 492 | :102060006FE090E03FF090E09CE0FF90E040E044C3 493 | :102070002012175B8026750E0AE490E09CF074E055 494 | :10208000F59D743CF59E7EE0FF121383150EE50E60 495 | :102090006004315D60E390E09CE0442090E040F01B 496 | :1020A00090E029E0FEA3E090E0AB3187501374008C 497 | :1020B0002DF58274F43CF59D74002DF582E582F5D2 498 | :1020C0009EE4F50CE50CC394054003021F3C312946 499 | :1020D0003166400C313F000000121D3E5002314D70 500 | :1020E0003192313370023121050C80D8311AE5AAC2 501 | :1020F00020E00A319E0000003171021F35E4F50D29 502 | :10210000021F3590E0AB3142000000ED90E695F003 503 | :102110000000002290E09C7480F090E6497482F008 504 | :102120002290E0ABE004F022F090E029E0FEA3E092 505 | :10213000FFC322E090E67CF090E0ACE004F0229057 506 | :10214000E029E0FCA3E0FDEC90E694F02274F4F5C5 507 | :102150009D7400F59EE490E0ABF0A3F02290E09C2B 508 | :10216000E0540764072290E0ACE09F90E0ABE09E73 509 | :102170002290E690E0FE90E0ADE04EF0A3E0F0E4C7 510 | :1021800090E0A9F0A3F022FFE0FCA3E0FDC39FECE8 511 | :102190009E22743C250CF582E434E0F5832290E61F 512 | :1021A00091E0FF90E0ADE4F0A3EFF02290E0A9E031 513 | :1021B000FEA3E02400F58274F03EF583E02290E077 514 | :1021C000ABE4F0A322F090E0AAE004F022E490E077 515 | :0521D000ADF0A3F022B8 516 | :00000001FF 517 | -------------------------------------------------------------------------------- /config/nm.hex: -------------------------------------------------------------------------------- 1 | :0200000490006A 2 | :0400000000004005B7 3 | :0200000490105A 4 | :04000000AFAC90BC55 5 | :0200000490501A 6 | :0C00000000012BA014770000000000009D 7 | :00000001FF 8 | -------------------------------------------------------------------------------- /docs/gen_config: -------------------------------------------------------------------------------- 1 | Utility: gen_config(.py) 2 | 3 | Overview 4 | -------- 5 | 6 | This utility is used to create configuration data (address and data) values 7 | to initialise microcontroller configuration registers. 8 | It creates a list of various data structures. Each structure is designed 9 | to optimise one common type of data initialisation requirement (eg constant 10 | fill, data copy etc). The data may be stored anywayre in FLASH but on PSOC 11 | is typically stored in the so called FLASH "configuration" area. A C function 12 | is supplied to walk the list, decode and action each entry. 13 | 14 | Source File Format 15 | ------------------ 16 | 17 | Grammer: 18 | #include "filename.h" 19 | #define NAME VALUE 20 | #label NAME ADDRESS 21 | 22 | addr : value * count # Source type 1 23 | addr : value # Source type 2 24 | addr : hex bytes.... [ @ width ] # Source type 3 NOTE: dest width not currently supported 25 | addr : [src_addr] [* count] # Source type 4 Default count 1 26 | 27 | Future: ?? 28 | addr : [off:value]+ # Source type 5 29 | 30 | Labels: 31 | * Labels are an additional construct. They are output unchanged in the 32 | freehex output format. Their purpose is to add metadata to the output file (eg data load address) 33 | 34 | * FIXME: True or not: only one label is currently permitted and it must occur before any "addr:" lines. 35 | * FIXME: Should any coalescence be prevented from crossing label locations so that labels can be used to 36 | create distinct config data sets (eg with diff load addresses) in a single file. 37 | 38 | 39 | Notes: 40 | * addr, value, count may be expressed in standard C (well Python) 41 | format, decimal, hex (0x...) etc. 42 | 43 | * normal C include files can be used to pull in #define lines. 44 | FIXME: This tool does not currently support #define macros or defines with expressions on RHS. 45 | 46 | * A count == 0 in the source file is not valid. 47 | 48 | * Source Types and Output types more or less match trivially. 49 | Source Type -> Output Table Type (TT) 50 | 1 1 CF Constant Fill 51 | 2 ** 3 or 2. It depends. See below ** 52 | 3 3 DA Data Array (single value is most compact) 53 | 4 4 AC Address Copy (memcpy) 54 | 55 | * A single byte value could be INPUT using Source Types 1, 2 or 3 56 | * For a single byte Source Type 3 syntactically reduces to Source Type 2. 57 | * For a single byte all three source types (1,2,3) reduce to the same 58 | internal format. Therefore single bytes will always be output in a 59 | consistent format regardless of source construct. 60 | 61 | * A single byte may be OUTPUT using Output Types 1 (CF), 2 (OV), 3(DA) 62 | The most compact representation for a single byte happens to be DA. 63 | Thus DA is the canonical format for outputting a single byte. 64 | 65 | However a group of single byte values in a config file will often be 66 | within a small address range. Therefore a run of single byte values 67 | within an address range of 256 bytes can be efficiently coded using 68 | output type 2 offset,value (OV). 69 | Thus Output Type 2 (OV) is automatically generated as needed and 70 | cannot be explicitly specified in the Source File unless Source Type 5 71 | is implemented (to support entering small address offsets). 72 | 73 | Limits: 74 | Constant Fill: count <= 65536 75 | Data Array: <= 256 bytes 76 | Address Copy: <= 256 bytes 77 | Offset Value: address offset range <= 255 (count <=256 but offset <= 255) 78 | 79 | 80 | Output Modes 81 | ------------ 82 | * there are two output modes - strictly in source order and optimised 83 | (within a label group?). The optimisation mode groups multiple 84 | single value type 2 items into a CFG_TT_OV structure where possible. 85 | 86 | * It is possible to write an address twice. A realistic use case is to zero 87 | a large block (CF) and then sparse write values into it later. 88 | With output mode preserving source order it is up to the data file creator 89 | to put the block fill before any sparse fill of individual values. 90 | * Optimised mode gathers Source Type 2 entries together to compress storage space. 91 | To permit bulk fills and sparse writes to the same space the general 92 | rule is bulk fills first then sparse. 93 | In practice the key rule is probably only: 94 | In output file put CF (bulk fill) before others. 95 | An additional refinement might be CF before AC before others too. 96 | 97 | To ensure results are determinant between version the following order is 98 | used when output is optimised (LHS output/executed first): 99 | 100 | CF -> AC -> DA(multi) -> OV -> DA(single) 101 | 102 | Note that DA multi is like AC so it comes before OV and DA single 103 | 104 | 105 | Output/Memory Data Structure 106 | ---------------------------- 107 | 108 | The top level entity is a list of data structures. The first byte of a 109 | structure contains the structure type, the list ends with an element 110 | type of CFG_TT_END. There are 4 types of initialisation structure: 111 | Type: 1: constant fill, 2: data fill, 3:offset,value, 4: mem to mem copy 112 | 113 | Note: to permit count to handle common values of 256/65536 the stored count value has 1 added to it. 114 | Therefore a count of 0 is not possible. 115 | 116 | list structure: 117 | [ HEADER ELEMENT ]* 0000 118 | -> 119 | [ ttcc aaaa aaaa ELEMENT ]* 0000 120 | tt: type 121 | cc: count_low - 1 # add 1 to get real count (ie stored 0 -> count=1, 1->2 etc) 122 | a...a: 32 bit address 123 | 0000 is the list terminating value of ttcc 124 | 125 | 126 | ELEMENT tt == 1: constant fill (CF) 127 | ccvv 128 | cc: count_hi 129 | vv: value 130 | 131 | ELEMENT tt == 2: offset value (OV) 132 | [ oovv ]+ 133 | oo: offset 134 | vv: value 135 | "oovv" structure repeats cc (count_low) times 136 | 137 | ELEMENT tt == 3: data array (DA) 138 | [ vv ]+ 139 | vv: value 140 | "vv" structure repeats cc (count_low) times 141 | 142 | ELEMENT tt == 4: address copy (AC) 143 | ssss ssss 144 | s...s: 32 bit (source) address 145 | 146 | 147 | Note: 148 | * For compactness addresses (eg 32 bit addresses) are NOT aligned on usual 149 | memory boundaries. Note that ARMv7-M can handle unaligned 16/32 bit reads (not 64) IIRC, 150 | Form ARMv6 and earlier can do byte reads and reconstruct any 16/32 bit values. 151 | -------------------------------------------------------------------------------- /docs/romdata.txt: -------------------------------------------------------------------------------- 1 | Overview 2 | -------- 3 | 4 | This utility is used to create configuration data (address and data) values 5 | to initialise microcontroller configuration registers. 6 | It creates a list of various data structures. Each structure is designed 7 | to optimise one common type of data initialisation requirement (eg constant 8 | fill, data copy etc). The data may be stored anywayre in FLASH but on PSOC 9 | is typically stored in the so called FLASH "configuration" area. A C function 10 | is supplied to walk the list, decode and action each entry. 11 | 12 | 13 | Memory Data Structure 14 | --------------------- 15 | 16 | The top level entity is a list of data structures. The first byte of a 17 | structure contains the structure type, the list ends with an element 18 | type of CFG_TT_UNDEF. There are 4 types of initialisation structure: 19 | Type: 1: constant fill, 2: offset,value, 3: data fill, 4: mem to mem copy 20 | 21 | list structure: 22 | [ HEADER ELEMENT ]* 0000 23 | -> 24 | [ ttcc aaaa aaaa ELEMENT ]* 0000 25 | tt: type 26 | cc: count_low 27 | a...a: 32 bit address 28 | 0000 is the list terminating value of ttcc 29 | 30 | ELEMENT tt == 1: constant fill 31 | ccvv 32 | cc: count_hi 33 | vv: value 34 | 35 | ELEMENT tt == 2: offset value 36 | [ oovv ]+ 37 | oo: offset 38 | vv: value 39 | "oovv" structure repeats cc (count_low) times 40 | 41 | ELEMENT tt == 3: data array 42 | [ vv ]+ 43 | vv: value 44 | "vv" structure repeats cc (count_low) times 45 | 46 | ELEMENT tt == 4: address copy 47 | ssss ssss 48 | s...s: 32 bit (source) address 49 | 50 | Note: 51 | * For compactness addresses (eg 32 bit addresses) are NOT aligned on usual 52 | memory boundaries. 53 | 54 | 55 | Source File Format 56 | ------------------ 57 | 58 | Grammer: 59 | #include "filename.h" 60 | #define NAME VALUE 61 | #label NAME [@ADDRESS] 62 | 63 | addr : value [* count] # type 1 64 | addr : value # type 2 65 | addr : hex bytes.... [ @ width ] # type 3 NOTE: width not currently supported 66 | addr : [src_addr] [* count] # type 4 67 | 68 | Notes: 69 | * addr, value, count may be expressed in standard C (well Python) 70 | format, decimal, hex (0x...) etc. 71 | 72 | * normal C include files should work to pull in #define lines 73 | 74 | * only one label (before "addr:" lines) is currently permitted. 75 | 76 | * there are two output modes - strictly in source order and optimised 77 | (within a label group). The optimisation groups multiple 78 | single value type 2 items into a CFG_TT_OV structure where possible. 79 | 80 | * A single value could be stored via types 1, 2 or 3. The canoncial format is 81 | type 2XXX to allow grouping of other single values. 82 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = libhex libini programmer tools 2 | 3 | include ../Makefile.inc 4 | -------------------------------------------------------------------------------- /src/Makefile.inc: -------------------------------------------------------------------------------- 1 | LIBNAME ?= 2 | PROGNAMES ?= 3 | TESTPROGNAMES ?= 4 | TARGETS = $(LIBNAME) $(PROGNAMES) $(TESTPROGNAMES) 5 | 6 | CC=gcc 7 | CXX=g++ 8 | CFLAGS += $(INC) 9 | CPPFLAGS += $(INC) 10 | INSTALL=install 11 | COPY=cp 12 | 13 | 14 | # General Targets 15 | 16 | .PHONY: all install clean 17 | 18 | all: $(TARGETS) 19 | 20 | install:: 21 | ifdef PROGNAMES 22 | @if [ x"$(INSTALL_DIR)" = x"" ] ; then \ 23 | echo INSTALL_DIR is not set; \ 24 | exit 1; \ 25 | else \ 26 | echo Install directory: $(INSTALL_DIR); \ 27 | echo Installing: $(PROGNAMES); \ 28 | mkdir -p $(INSTALL_DIR); \ 29 | $(INSTALL) $(PROGNAMES) $(INSTALL_DIR); \ 30 | fi 31 | endif 32 | ifdef SCRIPTNAMES 33 | @if [ x"$(INSTALL_DIR)" = x"" ] ; then \ 34 | echo INSTALL_DIR is not set; \ 35 | exit 1; \ 36 | else \ 37 | echo Install directory: $(INSTALL_DIR); \ 38 | echo Installing: $(SCRIPTNAMES); \ 39 | mkdir -p $(INSTALL_DIR); \ 40 | $(INSTALL) $(SCRIPTNAMES) $(INSTALL_DIR); \ 41 | fi 42 | endif 43 | 44 | 45 | 46 | clean:: 47 | rm -f *.o $(TARGETS) 48 | 49 | 50 | # General Rules 51 | 52 | $(LIBNAME): $(OBJS) 53 | $(RM) -f $(LIBNAME) 54 | $(AR) cr $(LIBNAME) $(OBJS) 55 | 56 | 57 | %.o: %.cpp 58 | $(CXX) $(CPPFLAGS) -c $< 59 | 60 | %.o: %.cc 61 | $(CXX) $(CPPFLAGS) -c $< 62 | 63 | %.o: %.c 64 | $(CC) $(CFLAGS) -c $< 65 | 66 | #%.a: %.o 67 | # $(RM) -f $@ 68 | # $(AR) cr $@ $.*o 69 | 70 | .o.a: 71 | $(RM) -f $@ 72 | $(AR) cr $@ $.*o 73 | 74 | %.d: %.c 75 | $(SHELL) -ec '$(CC) -M $(CFLAGS) $< \ 76 | | sed '\"s/$*\\.o[ :]*/& $@/g'\" > $@' 77 | 78 | -------------------------------------------------------------------------------- /src/libhex/HexData.h: -------------------------------------------------------------------------------- 1 | #ifndef _MYHEX_H 2 | #define _MYHEX_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | typedef std::vector v_uint8_t; 28 | 29 | //#include "types.h" 30 | //#include "utils.h" 31 | 32 | 33 | // Intel Hex File Format. 34 | // :CCAAAATTDDDDD...DDDKK 35 | // where 36 | // ':' literal character (start code) 37 | // CC line data byte count (hex) 38 | // AAAA address (hex) 39 | // TT record type (hex) (see below) 40 | // DD.. data 41 | // KK checksum : 2's compl. of LSB of sum of line contents (binary byte values) except ':' and KK 42 | 43 | // Record (Block) Type 44 | #define RT_DATA 0 45 | #define RT_END 1 46 | #define RT_EXT_SEG_ADDR 2 47 | #define RT_START_SEG_ADDR 3 48 | #define RT_EXT_LIN_ADDR 4 49 | #define RT_START_LIN_ADDR 5 50 | 51 | struct HexData; 52 | 53 | 54 | struct Block 55 | { 56 | v_uint8_t data; 57 | unsigned max_len; 58 | uint32_t base_address; 59 | uint8_t type; 60 | 61 | Block(unsigned _max_len); 62 | Block(uint32_t address, const uint8_t *src, uint32_t src_len, uint8_t type=RT_DATA); 63 | Block(uint32_t address, v_uint8_t vdata); 64 | 65 | uint8_t calculate_checksum(void) const; 66 | void clear(void); 67 | void dump(FILE *fp=NULL, int max_bytes=0) const; 68 | int length(void) const { return data.size(); } 69 | uint8_t *ptr(void) { return data.data(); } 70 | }; 71 | 72 | 73 | // ============ 74 | typedef std::vector Blockset; 75 | 76 | struct HexData 77 | { 78 | Blockset blockset; 79 | 80 | public: 81 | 82 | enum {BIGENDIAN, LITTLEENDIAN}; 83 | 84 | HexData(); 85 | //HexData(const char *filename=NULL, uint32_t default_base_address=0); 86 | // HexData(uint32_t base_address, uint8_t *data, int len); 87 | HexData(uint32_t base_address, v_uint8_t vdata); 88 | 89 | // HexData& operator=(const HexData& other); 90 | // HexData (const HexData& other); 91 | 92 | // high level 93 | bool read_hex(const char *filename, uint32_t default_base_address=0); 94 | bool write_hex(const char *filename) const; 95 | bool write_hex_data(FILE *fp, unsigned int width=0) const; 96 | void _write_hex_data(FILE *fp) const; 97 | 98 | void add(const Block &block); 99 | void add(uint32_t base_address, v_uint8_t vdata); 100 | void add_hex(uint32_t base_address, const char *hex_str); 101 | HexData *reshape(int new_max_len) const; 102 | HexData *canonicalise(void) const { return reshape(0); } 103 | 104 | HexData *extract(uint32_t start_address, uint32_t address_length) const; 105 | v_uint8_t extract2vector(uint32_t start_address, uint32_t address_length) const; 106 | uint8_t *extract2bin(uint32_t start_address, uint32_t address_length, uint8_t *data=NULL) const; 107 | 108 | //Block &operator[](std::size_t i) { return (*blockset)[i]; } 109 | //const Block &operator[](std::size_t i) const { return const_cast(*blockset)[i]; } 110 | Block *operator[](std::size_t i) { return blockset[i]; } 111 | const Block *operator[](std::size_t i) const { return const_cast(blockset[i]); } 112 | 113 | // support 114 | void dump(FILE *fp=NULL, int max_bytes=0) const; 115 | int nblocks(void) const { return blockset.size(); } 116 | int length(void) const; 117 | //int length(uint32_t start_address, uint32_t address_length) const; 118 | bool minmax_address(uint32_t range_start_address, uint32_t range_address_length, uint32_t *min_address, uint32_t *max_address) const; 119 | 120 | void trim(void); 121 | void clear(void) { blockset.clear(); } 122 | uint32_t uint_at(uint32_t address, unsigned int len, uint8_t endian) const; 123 | 124 | static uint32_t parse_hex_int(const char **hex_buffer, int num_hex_digits); 125 | static uint8_t *hexstr2bin(const char *hex_buffer, int num_hex_digits, uint8_t *bin_buffer); 126 | static const char *type_str(int type); 127 | 128 | static void write_block_record(FILE *fp, const Block *block); 129 | static void write_ext_address_record(FILE *fp, uint32_t high_address); 130 | static void write_end_record(FILE *fp); 131 | static void write_raw_record(FILE *fp, uint32_t address, uint8_t type, const uint8_t *data, int len); 132 | static void write_raw_record(FILE *fp, uint32_t address, uint8_t type, const v_uint8_t data); 133 | static void write_hex_record(FILE *fp, uint32_t address, uint8_t type, const uint8_t *data, int len); 134 | static void write_hex_record(FILE *fp, uint32_t address, uint8_t type, const v_uint8_t data); 135 | }; 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/libhex/Makefile: -------------------------------------------------------------------------------- 1 | LIBNAME=libhex.a 2 | OBJS = HexData.o 3 | TESTPROGNAMES=testmyhex 4 | 5 | testmyhex: testmyhex.o libhex.a 6 | $(CXX) -o $@ $< -L. -lhex 7 | 8 | include ../Makefile.inc 9 | -------------------------------------------------------------------------------- /src/libhex/testmyhex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "HexData.h" 26 | #include "utils.h" 27 | 28 | 29 | #if 0 30 | void f(const char *msg, int block_start_address, int block_len, int start_address, int end_address) 31 | { 32 | fprintf(stderr,"%s: BSA:%d, BL:%d, SA:%d, EA:%d\n", msg, block_start_address, block_len, start_address, end_address); 33 | int block_end_address = block_start_address + block_len; 34 | int start_offset = block_start_address - start_address; 35 | int end_offset = end_address - block_end_address; 36 | int max_0_so = MAX(0, start_offset); 37 | int num_bytes = block_len + MIN(0, start_offset) + MIN(0, end_offset); 38 | 39 | fprintf(stderr,"%s COPY(data + %d, bsid + %d, len=%d)\n\n", num_bytes <= 0 ? "Don't" : "", 40 | max_0_so, MAX(0,-start_offset), num_bytes); 41 | 42 | } 43 | #endif 44 | 45 | bool testcheck(int testnum, const uint8_t *testdata, const uint8_t *refdata, int n) 46 | { 47 | if (memcmp(testdata, refdata, n) == 0) 48 | { 49 | fprintf(stderr, "Test %d: Passed\n", testnum); 50 | return true; 51 | } 52 | 53 | int i; 54 | fprintf(stderr, "Test %d: Failed\n", testnum); 55 | // print differencecs 56 | fprintf(stderr, "TestData: "); 57 | for (i=0;iextract2bin(addr_start, len); 199 | testcheck(testnum, data, refdata, len); 200 | free(data); 201 | 202 | testnum = 11; // above 203 | addr_start = 512; 204 | len = 64; 205 | fprintf(stderr, "Test %d: %s, %d - %d\n", testnum, "above", addr_start, addr_start + len); 206 | hdata = test1.extract(addr_start, len); 207 | data = hdata->extract2bin(addr_start, len); 208 | testcheck(testnum, data, refdata, len); 209 | free(data); 210 | 211 | testnum = 12; // across lower boundary 212 | addr_start = 128; 213 | len = 200; 214 | fprintf(stderr, "Test %d: %s, %d - %d\n", testnum, "across lower boundary", addr_start, addr_start+len); 215 | hdata = test1.extract(addr_start, len); 216 | data = hdata->extract2bin(addr_start, len); 217 | setref(refdata, 256 - addr_start, 256 - (256 - addr_start), 0, true); 218 | testcheck(testnum, data, refdata, len); 219 | free(data); 220 | 221 | testnum = 13; 222 | addr_start = 511; 223 | len = 64; // across upper boundary 224 | fprintf(stderr, "Test %d: %s, %d - %d\n", testnum, "across upper boundary", addr_start, addr_start+len); 225 | hdata = test1.extract(addr_start, len); 226 | data = hdata->extract2bin(addr_start, len); 227 | memset(refdata, 0, 256); 228 | refdata[0] = 255; 229 | testcheck(testnum, data, refdata, len); 230 | free(data); 231 | 232 | testnum = 14; // exact length 233 | addr_start = 256; 234 | len = 256; 235 | fprintf(stderr, "Test %d: %s, %d - %d\n", testnum, "exact length", addr_start, addr_start+len); 236 | hdata = test1.extract(addr_start, len); 237 | data = hdata->extract2bin(addr_start, len); 238 | setref(refdata, 0, len, 0, true); 239 | testcheck(testnum, data, refdata, len); 240 | free(data); 241 | 242 | testnum = 15; // inside 243 | addr_start = 300; 244 | len = 64; 245 | fprintf(stderr, "Test %d: %s, %d - %d\n", testnum, "inside", addr_start, addr_start+len); 246 | hdata = test1.extract(addr_start, len); 247 | data = hdata->extract2bin(addr_start, len); 248 | setref(refdata, 0, len, 300-256, true); 249 | testcheck(testnum, data, refdata, len); 250 | free(data); 251 | 252 | testnum = 16; // outside 253 | addr_start = 128; 254 | len = 512; 255 | fprintf(stderr, "Test %d: %s, %d - %d\n", testnum, "outside", addr_start, addr_start+len); 256 | hdata = test1.extract(addr_start, len); 257 | data = hdata->extract2bin(addr_start, len); 258 | memset(refdata, 0, 512); 259 | setref(refdata+128, 0, 256, 0, false); 260 | testcheck(testnum, data, refdata, 512); 261 | free(data); 262 | 263 | testnum = 17; // exact length (one block) 264 | addr_start = 288; 265 | len = 32; 266 | fprintf(stderr,"Test %d: %s, %d - %d\n", testnum, "exact length (one block)", addr_start, addr_start+len); 267 | hdata = test1.extract(addr_start, len); 268 | data = hdata->extract2bin(addr_start, len); 269 | setref(refdata, 0, len, 288-256, true); 270 | testcheck(testnum, data, refdata, len); 271 | free(data); 272 | 273 | testnum = 18; // inside (one block) 274 | addr_start = 290; 275 | len = 12; 276 | fprintf(stderr,"Test %d: %s, %d - %d\n", testnum, "inside (one block)", addr_start, addr_start+len); 277 | hdata = test1.extract(addr_start, len); 278 | data = hdata->extract2bin(addr_start, len); 279 | setref(refdata, 0, len, 290-256, true); 280 | testcheck(testnum, data, refdata, len); 281 | free(data); 282 | 283 | 284 | #if 0 285 | // HexData hexdata("test.hex"); 286 | // HexData hexdata("fx2lp_fw.hex"); 287 | HexData hexdata("CapSense_CSD_Design01.hex"); 288 | hexdata.dump(stdout); 289 | // hexdata.write_hex("tst.hex"); 290 | 291 | //HexData *newhexdata = hexdata.reshape(32); 292 | int newsize = 0; // 32 293 | HexData *newhexdata = hexdata.reshape(newsize); 294 | assert(newhexdata); 295 | #endif 296 | 297 | #if 0 298 | int size = newhexdata->blockset.size(); 299 | int i; 300 | for(i=0; iblockset[i]; 303 | assert(block != NULL); 304 | block->dump(); 305 | } 306 | #else 307 | // newhexdata->dump(stdout); 308 | // if (newsize > 0 && newsize < 256) 309 | // newhexdata->write_hex("testout.hex"); 310 | #endif 311 | 312 | #if 0 313 | uint8_t * data = hexdata.extract2bin(32, 0x1000); 314 | dump_data(stdout, data, 512); 315 | 316 | f("b above", 20,10, 10, 18); 317 | f("b encomp", 20,10, 22, 28); 318 | f("b below", 20,10, 31, 38); 319 | f("b border top", 20,10, 15, 22); 320 | f("b border bottom", 20,10, 25, 32); 321 | f("b inside", 20,10, 18, 33); 322 | #endif 323 | } 324 | -------------------------------------------------------------------------------- /src/libhex/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H 2 | #define _UTILS_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | // FIXME: Don't actually have dest types so to_Uxx is academic 23 | #define B4LE_to_U32(c) (((c)[3]<<24) | ((c)[2] << 16) | ((c)[1] << 8) | (c)[0] ) 24 | #define B4BE_to_U32(c) (((c)[0]<<24) | ((c)[1] << 16) | ((c)[2] << 8) | (c)[3] ) 25 | #define B2LE_to_U32(c) (((c)[1] << 8) | (c)[0] ) 26 | #define B2BE_to_U16(c) (((c)[0] << 8) | (c)[1] ) 27 | 28 | #ifndef MIN 29 | #define MIN(a,b) ((a) <= (b) ? (a) : (b)) 30 | #endif 31 | 32 | #ifndef MAX 33 | #define MAX(a,b) ((a) >= (b) ? (a) : (b)) 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/libini/HierINIReader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Kim Lester 2 | // All rights reserved. 3 | // This code is released under same license (New BSD) as the inih reader it is based upon. 4 | 5 | #include 6 | 7 | #include "HierINIReader.h" 8 | 9 | using std::string; 10 | 11 | 12 | string HierINIReader::Get(string section, string name, string default_value)/*, bool search_parent)*/ 13 | { 14 | // Hierarchy is dotted. Eg: [a.b.c].name -> [a.b].name -> [a].name -> [""].name 15 | // where [""] is any initial unnamed section if it exists. 16 | 17 | string key = MakeKey(section, name); 18 | 19 | if (_values.count(key)) 20 | return _values[key]; 21 | 22 | // if (!search_parent) 23 | // return default_value; 24 | if (section.length() == 0) // already looked at top level - give up 25 | return default_value; 26 | 27 | size_t pos = section.rfind("."); 28 | section = (pos == string::npos) ? "" : section.substr(0,pos-1); 29 | 30 | //return Get(section, name, default_value, search_parent); 31 | return Get(section, name, default_value); 32 | } 33 | 34 | 35 | uint32_t HierINIReader::GetUint32(string section, string name, uint32_t default_value) 36 | { 37 | string valstr = Get(section, name, ""); 38 | const char* value = valstr.c_str(); 39 | char* end; 40 | // This parses "1234" (decimal) and also "0x4D2" (hex) 41 | uint32_t n = (uint32_t) strtol(value, &end, 0); 42 | return end > value ? n : default_value; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/libini/HierINIReader.h: -------------------------------------------------------------------------------- 1 | #ifndef __HIERINIREADER_H__ 2 | #define __HIERINIREADER_H__ 3 | 4 | #include 5 | #include "INIReader.h" 6 | 7 | class HierINIReader: public INIReader 8 | { 9 | public: 10 | HierINIReader(std::string filename) : INIReader(filename) {}; 11 | 12 | // Get a string value from INI file, returning default_value if not found. 13 | // Hierarchy is dotted. Eg: [a.b.c].name -> [a.b].name -> [a].name -> [""].name 14 | // where [""] is any initial unnamed section if it exists. 15 | std::string Get(std::string section, std::string name, 16 | std::string default_value); // , bool search_parent=true); 17 | 18 | uint32_t GetUint32(std::string section, std::string name, uint32_t default_value); 19 | }; 20 | 21 | #endif // __HIERINIREADER_H__ 22 | -------------------------------------------------------------------------------- /src/libini/INIReader.cpp: -------------------------------------------------------------------------------- 1 | // Read an INI file into easy-to-access name/value pairs. 2 | 3 | #include 4 | #include 5 | #include 6 | #include "ini.h" 7 | #include "INIReader.h" 8 | 9 | using std::string; 10 | 11 | INIReader::INIReader(string filename) 12 | { 13 | _error = ini_parse(filename.c_str(), ValueHandler, this); 14 | } 15 | 16 | int INIReader::ParseError() 17 | { 18 | return _error; 19 | } 20 | 21 | string INIReader::Get(string section, string name, string default_value) 22 | { 23 | string key = MakeKey(section, name); 24 | return _values.count(key) ? _values[key] : default_value; 25 | } 26 | 27 | long INIReader::GetInteger(string section, string name, long default_value) 28 | { 29 | string valstr = Get(section, name, ""); 30 | const char* value = valstr.c_str(); 31 | char* end; 32 | // This parses "1234" (decimal) and also "0x4D2" (hex) 33 | long n = strtol(value, &end, 0); 34 | return end > value ? n : default_value; 35 | } 36 | 37 | double INIReader::GetReal(string section, string name, double default_value) 38 | { 39 | string valstr = Get(section, name, ""); 40 | const char* value = valstr.c_str(); 41 | char* end; 42 | double n = strtod(value, &end); 43 | return end > value ? n : default_value; 44 | } 45 | 46 | bool INIReader::GetBoolean(string section, string name, bool default_value) 47 | { 48 | string valstr = Get(section, name, ""); 49 | // Convert to lower case to make string comparisons case-insensitive 50 | std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower); 51 | if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1") 52 | return true; 53 | else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0") 54 | return false; 55 | else 56 | return default_value; 57 | } 58 | 59 | string INIReader::MakeKey(string section, string name) 60 | { 61 | string key = section + "=" + name; 62 | // Convert to lower case to make section/name lookups case-insensitive 63 | std::transform(key.begin(), key.end(), key.begin(), ::tolower); 64 | return key; 65 | } 66 | 67 | int INIReader::ValueHandler(void* user, const char* section, const char* name, 68 | const char* value) 69 | { 70 | INIReader* reader = (INIReader*)user; 71 | string key = MakeKey(section, name); 72 | if (reader->_values[key].size() > 0) 73 | reader->_values[key] += "\n"; 74 | reader->_values[key] += value; 75 | return 1; 76 | } 77 | -------------------------------------------------------------------------------- /src/libini/INIReader.h: -------------------------------------------------------------------------------- 1 | // Read an INI file into easy-to-access name/value pairs. 2 | 3 | // inih and INIReader are released under the New BSD license (see LICENSE.txt). 4 | // Go to the project home page for more info: 5 | // 6 | // http://code.google.com/p/inih/ 7 | 8 | #ifndef __INIREADER_H__ 9 | #define __INIREADER_H__ 10 | 11 | #include 12 | #include 13 | 14 | // Read an INI file into easy-to-access name/value pairs. (Note that I've gone 15 | // for simplicity here rather than speed, but it should be pretty decent.) 16 | class INIReader 17 | { 18 | public: 19 | // Construct INIReader and parse given filename. See ini.h for more info 20 | // about the parsing. 21 | INIReader(std::string filename); 22 | 23 | // Return the result of ini_parse(), i.e., 0 on success, line number of 24 | // first error on parse error, or -1 on file open error. 25 | int ParseError(); 26 | 27 | // Get a string value from INI file, returning default_value if not found. 28 | virtual std::string Get(std::string section, std::string name, 29 | std::string default_value); 30 | 31 | // Get an integer (long) value from INI file, returning default_value if 32 | // not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2"). 33 | long GetInteger(std::string section, std::string name, long default_value); 34 | 35 | // Get a real (floating point double) value from INI file, returning 36 | // default_value if not found or not a valid floating point value 37 | // according to strtod(). 38 | double GetReal(std::string section, std::string name, double default_value); 39 | 40 | // Get a boolean value from INI file, returning default_value if not found or if 41 | // not a valid true/false value. Valid true values are "true", "yes", "on", "1", 42 | // and valid false values are "false", "no", "off", "0" (not case sensitive). 43 | bool GetBoolean(std::string section, std::string name, bool default_value); 44 | 45 | protected: 46 | int _error; 47 | std::map _values; 48 | static std::string MakeKey(std::string section, std::string name); 49 | static int ValueHandler(void* user, const char* section, const char* name, 50 | const char* value); 51 | }; 52 | 53 | #endif // __INIREADER_H__ 54 | -------------------------------------------------------------------------------- /src/libini/LICENSE.txt: -------------------------------------------------------------------------------- 1 | http://code.google.com/p/inih/ 2 | The "inih" library is distributed under the New BSD license: 3 | 4 | Copyright (c) 2009, Brush Technology 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | * Neither the name of Brush Technology nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/libini/Makefile: -------------------------------------------------------------------------------- 1 | LIBNAME=libini.a 2 | OBJS = INIReader.o HierINIReader.o ini.o 3 | 4 | include ../Makefile.inc 5 | -------------------------------------------------------------------------------- /src/libini/README.kim: -------------------------------------------------------------------------------- 1 | This directory contains the core code from http://code.google.com/p/inih/ 2 | Minor changes have been made to the original class to allow dervived classes 3 | 4 | New features in derived class: 5 | * hierarchical functionality (see below) 6 | * A uint32 type (to avoid potential casting problems from existing signed integer) 7 | 8 | 9 | This hierarchical INI file format supports sections of the form 10 | [a.b.c] 11 | key = value 12 | 13 | If the hierarchical searching is used then key will be searched for in: 14 | [a.b.c].key 15 | [a.b].key 16 | [a].key 17 | [].key 18 | 19 | where the last case is the "global" section - ie the region before the first explicit file section [] 20 | -------------------------------------------------------------------------------- /src/libini/ini.c: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | http://code.google.com/p/inih/ 7 | 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "ini.h" 15 | 16 | #if !INI_USE_STACK 17 | #include 18 | #endif 19 | 20 | #define MAX_SECTION 50 21 | #define MAX_NAME 50 22 | 23 | /* Strip whitespace chars off end of given string, in place. Return s. */ 24 | static char* rstrip(char* s) 25 | { 26 | char* p = s + strlen(s); 27 | while (p > s && isspace((unsigned char)(*--p))) 28 | *p = '\0'; 29 | return s; 30 | } 31 | 32 | /* Return pointer to first non-whitespace char in given string. */ 33 | static char* lskip(const char* s) 34 | { 35 | while (*s && isspace((unsigned char)(*s))) 36 | s++; 37 | return (char*)s; 38 | } 39 | 40 | /* Return pointer to first char c or ';' comment in given string, or pointer to 41 | null at end of string if neither found. ';' must be prefixed by a whitespace 42 | character to register as a comment. */ 43 | static char* find_char_or_comment(const char* s, char c) 44 | { 45 | int was_whitespace = 0; 46 | while (*s && *s != c && !(was_whitespace && *s == ';')) { 47 | was_whitespace = isspace((unsigned char)(*s)); 48 | s++; 49 | } 50 | return (char*)s; 51 | } 52 | 53 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ 54 | static char* strncpy0(char* dest, const char* src, size_t size) 55 | { 56 | strncpy(dest, src, size); 57 | dest[size - 1] = '\0'; 58 | return dest; 59 | } 60 | 61 | /* See documentation in header file. */ 62 | int ini_parse_file(FILE* file, 63 | int (*handler)(void*, const char*, const char*, 64 | const char*), 65 | void* user) 66 | { 67 | /* Uses a fair bit of stack (use heap instead if you need to) */ 68 | #if INI_USE_STACK 69 | char line[INI_MAX_LINE]; 70 | #else 71 | char* line; 72 | #endif 73 | char section[MAX_SECTION] = ""; 74 | char prev_name[MAX_NAME] = ""; 75 | 76 | char* start; 77 | char* end; 78 | char* name; 79 | char* value; 80 | int lineno = 0; 81 | int error = 0; 82 | 83 | #if !INI_USE_STACK 84 | line = (char*)malloc(INI_MAX_LINE); 85 | if (!line) { 86 | return -2; 87 | } 88 | #endif 89 | 90 | /* Scan through file line by line */ 91 | while (fgets(line, INI_MAX_LINE, file) != NULL) { 92 | lineno++; 93 | 94 | start = line; 95 | #if INI_ALLOW_BOM 96 | if (lineno == 1 && (unsigned char)start[0] == 0xEF && 97 | (unsigned char)start[1] == 0xBB && 98 | (unsigned char)start[2] == 0xBF) { 99 | start += 3; 100 | } 101 | #endif 102 | start = lskip(rstrip(start)); 103 | 104 | if (*start == ';' || *start == '#') { 105 | /* Per Python ConfigParser, allow '#' comments at start of line */ 106 | } 107 | #if INI_ALLOW_MULTILINE 108 | else if (*prev_name && *start && start > line) { 109 | /* Non-black line with leading whitespace, treat as continuation 110 | of previous name's value (as per Python ConfigParser). */ 111 | if (!handler(user, section, prev_name, start) && !error) 112 | error = lineno; 113 | } 114 | #endif 115 | else if (*start == '[') { 116 | /* A "[section]" line */ 117 | end = find_char_or_comment(start + 1, ']'); 118 | if (*end == ']') { 119 | *end = '\0'; 120 | strncpy0(section, start + 1, sizeof(section)); 121 | *prev_name = '\0'; 122 | } 123 | else if (!error) { 124 | /* No ']' found on section line */ 125 | error = lineno; 126 | } 127 | } 128 | else if (*start && *start != ';') { 129 | /* Not a comment, must be a name[=:]value pair */ 130 | end = find_char_or_comment(start, '='); 131 | if (*end != '=') { 132 | end = find_char_or_comment(start, ':'); 133 | } 134 | if (*end == '=' || *end == ':') { 135 | *end = '\0'; 136 | name = rstrip(start); 137 | value = lskip(end + 1); 138 | end = find_char_or_comment(value, '\0'); 139 | if (*end == ';') 140 | *end = '\0'; 141 | rstrip(value); 142 | 143 | /* Valid name[=:]value pair found, call handler */ 144 | strncpy0(prev_name, name, sizeof(prev_name)); 145 | if (!handler(user, section, name, value) && !error) 146 | error = lineno; 147 | } 148 | else if (!error) { 149 | /* No '=' or ':' found on name[=:]value line */ 150 | error = lineno; 151 | } 152 | } 153 | 154 | #if INI_STOP_ON_FIRST_ERROR 155 | if (error) 156 | break; 157 | #endif 158 | } 159 | 160 | #if !INI_USE_STACK 161 | free(line); 162 | #endif 163 | 164 | return error; 165 | } 166 | 167 | /* See documentation in header file. */ 168 | int ini_parse(const char* filename, 169 | int (*handler)(void*, const char*, const char*, const char*), 170 | void* user) 171 | { 172 | FILE* file; 173 | int error; 174 | 175 | file = fopen(filename, "r"); 176 | if (!file) 177 | return -1; 178 | error = ini_parse_file(file, handler, user); 179 | fclose(file); 180 | return error; 181 | } 182 | -------------------------------------------------------------------------------- /src/libini/ini.h: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | http://code.google.com/p/inih/ 7 | 8 | */ 9 | 10 | #ifndef __INI_H__ 11 | #define __INI_H__ 12 | 13 | /* Make this header file easier to include in C++ code */ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | /* Parse given INI-style file. May have [section]s, name=value pairs 21 | (whitespace stripped), and comments starting with ';' (semicolon). Section 22 | is "" if name=value pair parsed before any section heading. name:value 23 | pairs are also supported as a concession to Python's ConfigParser. 24 | 25 | For each name=value pair parsed, call handler function with given user 26 | pointer as well as section, name, and value (data only valid for duration 27 | of handler call). Handler should return nonzero on success, zero on error. 28 | 29 | Returns 0 on success, line number of first error on parse error (doesn't 30 | stop on first error), -1 on file open error, or -2 on memory allocation 31 | error (only when INI_USE_STACK is zero). 32 | */ 33 | int ini_parse(const char* filename, 34 | int (*handler)(void* user, const char* section, 35 | const char* name, const char* value), 36 | void* user); 37 | 38 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't 39 | close the file when it's finished -- the caller must do that. */ 40 | int ini_parse_file(FILE* file, 41 | int (*handler)(void* user, const char* section, 42 | const char* name, const char* value), 43 | void* user); 44 | 45 | /* Nonzero to allow multi-line value parsing, in the style of Python's 46 | ConfigParser. If allowed, ini_parse() will call the handler with the same 47 | name for each subsequent line parsed. */ 48 | #ifndef INI_ALLOW_MULTILINE 49 | #define INI_ALLOW_MULTILINE 1 50 | #endif 51 | 52 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of 53 | the file. See http://code.google.com/p/inih/issues/detail?id=21 */ 54 | #ifndef INI_ALLOW_BOM 55 | #define INI_ALLOW_BOM 1 56 | #endif 57 | 58 | /* Nonzero to use stack, zero to use heap (malloc/free). */ 59 | #ifndef INI_USE_STACK 60 | #define INI_USE_STACK 1 61 | #endif 62 | 63 | /* Stop parsing on first error (default is to keep parsing). */ 64 | #ifndef INI_STOP_ON_FIRST_ERROR 65 | #define INI_STOP_ON_FIRST_ERROR 0 66 | #endif 67 | 68 | /* Maximum line length for any line in INI file. */ 69 | #ifndef INI_MAX_LINE 70 | #define INI_MAX_LINE 200 71 | #endif 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif /* __INI_H__ */ 78 | -------------------------------------------------------------------------------- /src/programmer/AppData.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "AppData.h" 26 | 27 | #include "HexFileFormat.h" 28 | #include "utils.h" 29 | 30 | 31 | #define DC_ECCEN_BIT (1 << 27) 32 | 33 | static int debug = 0; 34 | 35 | AppData::AppData() : 36 | code(0), config(0), eeprom(0), protection(0), 37 | device_config(0), 38 | security_WOL(0), 39 | checksum(0), 40 | hex_file_version(HexFileFormat::VERSION), 41 | device_id(0), 42 | silicon_revision(0), 43 | debug_enable(0), 44 | reserved(0) 45 | { 46 | } 47 | 48 | 49 | void AppData::clear(void) 50 | { 51 | if (code) delete code; // code.clear(); 52 | if (config) delete config; // config.clear(); 53 | if (protection) delete protection; // protection.clear(); 54 | if (eeprom) delete eeprom; // eeprom.clear(); 55 | 56 | security_WOL = 0; 57 | device_config = 0; 58 | checksum = 0; 59 | 60 | hex_file_version = HexFileFormat::VERSION; 61 | device_id = 0; 62 | silicon_revision = 0; 63 | debug_enable = 0; 64 | reserved = 0; 65 | } 66 | 67 | 68 | bool AppData::read_hex_file(const char *filename, uint32_t default_base_address) 69 | { 70 | // default base addr is only used in obscure cases when reading snippet hex files without a high_address record 71 | 72 | HexData raw; 73 | if (!raw.read_hex(filename, default_base_address)) return false; 74 | 75 | HexData *canon = raw.canonicalise(); 76 | if (!canon) return false; 77 | 78 | // canon->dump(stdout); 79 | 80 | clear(); 81 | 82 | code = canon->extract(HexFileFormat::FLASH_CODE_ADDRESS, HexFileFormat::FLASH_CODE_MAX_SIZE); 83 | config = canon->extract(HexFileFormat::CONFIG_ADDRESS, HexFileFormat::CONFIG_MAX_SIZE); 84 | protection = canon->extract(HexFileFormat::PROTECTION_ADDRESS, HexFileFormat::PROTECTION_MAX_SIZE); 85 | eeprom = canon->extract(HexFileFormat::EEPROM_ADDRESS, HexFileFormat::EEPROM_MAX_SIZE); 86 | 87 | checksum = canon->uint_at(HexFileFormat::CHECKSUM_ADDRESS, 2, HexData::BIGENDIAN); 88 | 89 | device_config = canon->uint_at(HexFileFormat::DEVCONFIG_ADDRESS, 4, HexData::LITTLEENDIAN); 90 | security_WOL = canon->uint_at(HexFileFormat::WOL_ADDRESS, 4, HexData::BIGENDIAN); // This seems to be encoded in hex file as BE 91 | 92 | // metadata 93 | hex_file_version = canon->uint_at(HexFileFormat::VERSION_ADDRESS, 2, HexData::BIGENDIAN); 94 | device_id = canon->uint_at(HexFileFormat::DEVICE_ID_ADDRESS, 4, HexData::BIGENDIAN); 95 | silicon_revision = canon->uint_at(HexFileFormat::SILICON_REV_ADDRESS, 1, HexData::BIGENDIAN); 96 | debug_enable = canon->uint_at(HexFileFormat::DEBUG_ENABLE_ADDRESS, 1, HexData::BIGENDIAN); 97 | reserved = canon->uint_at(HexFileFormat::METADATA_RESERVED_ADDRESS, 4, HexData::BIGENDIAN); 98 | 99 | // dump(true,NULL); 100 | 101 | #if 0 102 | // Note: may not want to output message here. 103 | uint32_t calc_cksum = calc_checksum(true); 104 | if (calc_cksum != checksum) 105 | fprintf(stderr, "Warning: Checksum mismatch! Calculated 0x%04x, expected 0x%04x\n", calc_cksum, checksum); 106 | #endif 107 | 108 | delete canon; 109 | return true; 110 | } 111 | 112 | 113 | bool AppData::write_hex_file(const char *filename) const 114 | { 115 | // NOTE: Does not currently calculate checksum - must be precalculated. 116 | 117 | // Doc: 001-81290 Appendix A.1.1 118 | //fprintf(stderr, "write_hex_file()\n"); 119 | 120 | FILE *fp = stdout; 121 | 122 | if (filename != NULL) 123 | { 124 | fp = fopen(filename, "w"); 125 | if (fp == NULL) 126 | { 127 | fprintf(stderr, "Failed to open hex file \'%s\' for writing\n", filename); 128 | return false; 129 | } 130 | } 131 | 132 | unsigned int width = 32; 133 | 134 | // Written in order of increasing Hex File Addresses 135 | if (code) code->write_hex_data(fp,width); 136 | 137 | if (config) config->write_hex_data(fp, width); 138 | 139 | uint8_t encoded_int[4]; 140 | uint32_to_b4_LE(device_config, encoded_int); 141 | HexData::write_hex_record(fp, HexFileFormat::DEVCONFIG_ADDRESS, RT_DATA, encoded_int, 4); 142 | 143 | uint32_to_b4_BE(security_WOL, encoded_int); // This seems to be encoded in hex file as BE !? 144 | HexData::write_hex_record(fp, HexFileFormat::WOL_ADDRESS, RT_DATA, encoded_int, 4); 145 | 146 | if (eeprom) eeprom->write_hex_data(fp, width); 147 | 148 | // we only save bottom two bytes 149 | uint16_to_b2_BE(checksum & 0xFFFF, encoded_int); 150 | HexData::write_hex_record(fp, HexFileFormat::CHECKSUM_ADDRESS, RT_DATA, encoded_int, 2); 151 | 152 | // NOTE: Ignoring docs that imply protection should be written as one hex row (note max is 255/6). 153 | if (protection) protection->write_hex_data(fp, width); 154 | 155 | uint8_t metadata[HexFileFormat::METADATA_SIZE]; 156 | _set_metadata(metadata); 157 | HexData::write_hex_record(fp, HexFileFormat::METADATA_ADDRESS, RT_DATA, (uint8_t *)metadata, HexFileFormat::METADATA_SIZE); 158 | 159 | HexData::write_end_record(fp); 160 | 161 | fclose(fp); 162 | //fprintf(stderr, "write_hex_file(%s) END\n", filename); 163 | return true; 164 | } 165 | 166 | 167 | void AppData::_set_metadata(uint8_t metadata[HexFileFormat::METADATA_SIZE]) const 168 | { 169 | memset(metadata, 0, HexFileFormat::METADATA_SIZE); 170 | 171 | uint16_to_b2_BE(hex_file_version, metadata+0); 172 | uint32_to_b4_BE(device_id, metadata+2); 173 | 174 | // 0006 Silicon revision (1 byte) 175 | // 1 ES1 (TM) 176 | // 2 ES2 (LP) 177 | metadata[6] = silicon_revision; 178 | 179 | // 0007 Debug Enable (1 byte) (advise only) 180 | // 0 debugging disabled in code 181 | // 1 debugging enabled in code 182 | metadata[7] = debug_enable; 183 | 184 | // 0008 Internal use by PSoC programmer (4 bytes) 185 | uint32_to_b4_BE(reserved, metadata+8); 186 | } 187 | 188 | 189 | uint32_t AppData::calc_checksum(bool truncate) const 190 | { 191 | // truncate to lowest 16 bits 192 | // Calculates code checksum. FIXME may need to include config data if ECC == 0 193 | // FIXME: should I just store it in checksum field !? 194 | // Simple whole of program summation checksum used by PSoC hex files 195 | 196 | // Note checksum of each row would include both main code (256) and any CONFIG/ECC code (32) 197 | // FIXME: should only include code not all data in hex file 198 | int checksum = 0; 199 | 200 | // code blocks 201 | int nblocks, i; 202 | 203 | nblocks = code ? code->blockset.size() : 0; 204 | 205 | for(i=0; iblockset[i]; 208 | int len = block->length(); 209 | int j; 210 | for (j=0; jdata[j]; 213 | } 214 | } 215 | 216 | // config blocks 217 | nblocks = config ? config->blockset.size() : 0; 218 | 219 | for(i=0; iblockset[i]; 222 | int len = block->length(); 223 | int j; 224 | for (j=0; jdata[j]; 227 | } 228 | } 229 | 230 | if (truncate) checksum &= 0xFFFF; 231 | 232 | // FIXME: what about data in CONFIG/ECC space !? 233 | if (debug) fprintf(stderr,"AppData: Calc checksum is: 0x%x\n", checksum); 234 | 235 | return checksum; 236 | } 237 | 238 | 239 | 240 | bool AppData::extra_flash_used_for_config(void) const 241 | { 242 | // assumes device_config is set 243 | return ((device_config & DC_ECCEN_BIT) == 0) ? true : false; 244 | } 245 | 246 | 247 | void AppData::dump(bool shortform, const char *filename) const 248 | { 249 | FILE *fp = stderr; 250 | if (filename != NULL) 251 | { 252 | fprintf(stderr, "creating dump file:%s\n", filename); 253 | fp = fopen(filename, "w"); 254 | assert(fp != NULL); 255 | } 256 | 257 | fprintf(fp, "DUMP:\n"); 258 | fprintf(fp, "Code:\n"); 259 | if (code) code->dump(fp, shortform ? 1024 : 0); // 0 = all 260 | else fprintf(fp, "NONE\n"); 261 | 262 | fprintf(fp, "Config:\n"); 263 | if (config) config->dump(fp, shortform? 1024: 0); // 0 = all 264 | else fprintf(fp, "NONE\n"); 265 | 266 | fprintf(fp, "EEPROM:\n"); 267 | if (eeprom) eeprom->dump(fp, shortform? 1024: 0); // 0 = all 268 | else fprintf(fp, "NONE\n"); 269 | 270 | fprintf(fp, "Protection:\n"); 271 | if (protection) protection->dump(fp, shortform? 1024: 0); // 0 = all 272 | else fprintf(fp, "NONE\n"); 273 | 274 | fprintf(fp, "Device Config: 0x%04x\n", device_config); 275 | fprintf(fp, " (b31-28) DIG_PHS_DLY: 0x%0x\n", (device_config & 0xf0000000) >> 28); 276 | fprintf(fp, " (b27) ECCEN: %d (area avail for config: %d)\n", ((device_config & 0x08000000) ? 1 : 0), extra_flash_used_for_config()); 277 | fprintf(fp, " (b26-25) DPS: %d\n", (device_config & 0x06000000) >> 25); 278 | fprintf(fp, " (b27) CFGSPEED: %d\n", (device_config & 0x01000000) ? 1 : 0); 279 | fprintf(fp, " (b23) XRESMEN: P1[2] is %s\n", (device_config & 0x800000) ? "XRES" : "GPIO"); 280 | fprintf(fp, " (b22) DEBUG_EN: %d\n", (device_config & 0x4000000) ? 1 : 0); 281 | fprintf(fp, "\n"); 282 | //dump_data(fp, device_config, 4, NULL); 283 | fprintf(fp, "WOL: 0x%04x\n", security_WOL); 284 | //dump_data(fp, security_WOL, 4, NULL); 285 | 286 | fprintf(fp, "code checksum: 0x%04x\n", checksum); 287 | uint32_t calc_cksum = calc_checksum(true); 288 | if (calc_cksum != checksum) 289 | fprintf(stderr, " Warning: Checksum mismatch! Calculated 0x%04x, expected 0x%04x\n", calc_cksum, checksum); 290 | fprintf(fp, "device_id: 0x%08x\n", device_id); 291 | fprintf(fp, "hex_file_version: 0x%02x\n", hex_file_version); 292 | fprintf(fp, "silicon_revision: %d\n", silicon_revision); 293 | fprintf(fp, "debug_enable: %d\n", debug_enable); 294 | fprintf(fp, "reserved: 0x%08x\n", reserved); 295 | 296 | fprintf(fp, "END DUMP\n"); 297 | 298 | if (fp != stderr) 299 | fclose(fp); 300 | } 301 | 302 | 303 | #if 0 304 | void AppData::program_geom(const struct device_geometry_s &device_geom, int code_len, int *num_arrays, int *remainder_rows) 305 | { 306 | //int num_bytes_per_array = device_geom.flash_max_code_size / device_geom.flash_num_arrays; 307 | int num_bytes_per_array = device_geom.flash_rows_per_array * device_geom.flash_code_bytes_per_row; 308 | //int remainder_bytes = fdata->code_length % num_bytes_per_array; 309 | // int code_len = fdata->code.length(); 310 | int remainder_bytes = code_len % num_bytes_per_array; 311 | 312 | if (code_len == 0) fprintf(stderr, "Warning: No program code in memory so geometry will be empty\n"); 313 | 314 | *num_arrays = code_len / num_bytes_per_array; 315 | *remainder_rows = 0; 316 | 317 | if (remainder_bytes == 0) 318 | return; 319 | 320 | (*num_arrays)++; 321 | 322 | *remainder_rows = remainder_bytes / device_geom.flash_code_bytes_per_row; 323 | 324 | if (remainder_bytes % device_geom.flash_code_bytes_per_row > 0) 325 | (*remainder_rows)++; 326 | } 327 | 328 | #endif 329 | -------------------------------------------------------------------------------- /src/programmer/AppData.h: -------------------------------------------------------------------------------- 1 | #ifndef _APPDATA_H 2 | #define _APPDATA_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include "HexData.h" 26 | 27 | 28 | struct AppData 29 | { 30 | HexData *code; 31 | HexData *config; 32 | HexData *protection; 33 | HexData *eeprom; 34 | 35 | uint32_t device_config; 36 | uint32_t security_WOL; 37 | uint32_t checksum; // only bottom two bytes are stored in hex file 38 | 39 | // metadata 40 | uint16_t hex_file_version; 41 | uint32_t device_id; 42 | uint8_t silicon_revision; 43 | uint8_t debug_enable; 44 | uint32_t reserved; 45 | 46 | // uint8_t metadata[12]; // not stored in PSoC 47 | 48 | // ... 49 | 50 | AppData(); 51 | 52 | void clear(void); 53 | 54 | // void set_device_id(uint32_t device_id) { m_device_id = device_id }; // for writing to hex file 55 | // void get_device_id(void) { return m_device_id; }; // generally read from read_hex_file 56 | 57 | bool read_hex_file(const char *filename, uint32_t default_base_address=0); 58 | bool write_hex_file(const char *filename=NULL) const; // NULL = stdout 59 | void dump(bool shortform, const char *filename=NULL) const; 60 | 61 | void _set_metadata(uint8_t metadata[12]) const; // utility function 62 | uint32_t calc_checksum(bool truncate=false) const; 63 | bool extra_flash_used_for_config(void) const; 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/programmer/DeviceData.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "DeviceData.h" 22 | 23 | #include "HierINIReader.h" 24 | 25 | 26 | #if 0 27 | DeviceData::DeviceData(const char *filename, const char *device) 28 | flash_max_code_size(0), 29 | flash_max_config_size(0), 30 | flash_code_bytes_per_row(0), 31 | flash_config_bytes_per_row(0), 32 | flash_code_base_address(0), 33 | flash_config_base_address(0), 34 | flash_rows_per_array(0), 35 | flash_num_arrays(0), 36 | flash_rows_per_protection_byte(0), 37 | eeprom_base_address(0), 38 | eeprom_size(0), 39 | eeprom_bytes_per_row(0) 40 | { 41 | } 42 | #endif 43 | 44 | bool DeviceData::read_file(const std::string filename, const std::string device) 45 | { 46 | HierINIReader reader(filename); 47 | 48 | if (reader.ParseError() < 0) { 49 | //std::cout << "Can't read '%s'\n" << filename; 50 | return false; 51 | } 52 | 53 | flash_size = reader.GetInteger(device, "flash_size", 0 ); 54 | flash_rows_per_array = reader.GetInteger(device, "flash_rows_per_array", 0); 55 | flash_num_arrays = reader.GetInteger(device, "flash_num_arrays", 0); // DERIVED - Easy to Calc ?? 56 | 57 | flash_rows_per_protection_byte = reader.GetInteger(device, "flash_rows_per_protection_byte", 0); 58 | 59 | int total_flash_rows = flash_rows_per_array * flash_num_arrays; 60 | 61 | flash_code_bytes_per_row = reader.GetInteger(device, "flash_code_bytes_per_row", 0); 62 | flash_code_max_size = total_flash_rows * flash_code_bytes_per_row; 63 | flash_code_base_address = reader.GetUint32(device, "flash_code_base_address", 0); 64 | 65 | flash_config_bytes_per_row = reader.GetInteger(device, "flash_config_bytes_per_row", 0); 66 | flash_config_max_size = total_flash_rows * flash_config_bytes_per_row; 67 | flash_config_base_address = reader.GetUint32(device, "flash_config_base_address", 0); 68 | 69 | eeprom_size = reader.GetInteger(device, "eeprom_size", 0); 70 | eeprom_bytes_per_row = reader.GetInteger(device, "eeprom_bytes_per_row", 0); 71 | eeprom_base_address = reader.GetUint32(device, "eeprom_base_address", 0); 72 | 73 | return true; 74 | } 75 | 76 | 77 | bool DeviceData::validate(void) const 78 | { 79 | // basic sanity checks 80 | if (flash_size == 0) return false; 81 | if (flash_rows_per_array == 0) return false; 82 | if (flash_num_arrays == 0) return false; 83 | if (flash_rows_per_protection_byte == 0) return false; 84 | 85 | if (flash_code_bytes_per_row == 0) return false; 86 | if (flash_code_max_size == 0) return false; 87 | 88 | if (flash_config_bytes_per_row == 0) return false; 89 | if (flash_config_max_size == 0) return false; 90 | 91 | if (eeprom_size == 0) return false; 92 | if (eeprom_bytes_per_row == 0) return false; 93 | 94 | // misc sanity checks 95 | if (flash_config_base_address == 0) return false; 96 | if (eeprom_base_address == 0) return false; 97 | if (flash_code_base_address == flash_config_base_address) return false; 98 | 99 | return true; 100 | } 101 | 102 | 103 | void DeviceData::dump(void) const 104 | { 105 | fprintf(stderr, "Flash size: %d\n", flash_size); 106 | fprintf(stderr, "Flash rows per array: %d\n", flash_rows_per_array); 107 | fprintf(stderr, "Flash num arrays: %d\n", flash_num_arrays); 108 | fprintf(stderr, "Flash rows per protection byte: %d\n", flash_rows_per_protection_byte); 109 | 110 | fprintf(stderr, "Flash code bytes per row: %d\n", flash_code_bytes_per_row); 111 | fprintf(stderr, "Flash code max size: %d\n", flash_code_max_size); 112 | fprintf(stderr, "Flash code base address: 0x%08x\n", flash_code_base_address); 113 | 114 | fprintf(stderr, "Flash config bytes per row: %d\n", flash_config_bytes_per_row); 115 | fprintf(stderr, "Flash config max size: %d\n", flash_config_max_size); 116 | fprintf(stderr, "Flash config base address: 0x%08x\n", flash_config_base_address); 117 | 118 | fprintf(stderr, "EEPROM size: %d\n", eeprom_size); 119 | fprintf(stderr, "EEPROM bytes per row: %d\n", eeprom_bytes_per_row); 120 | fprintf(stderr, "EEPROM base address: 0x%08x\n", eeprom_base_address); 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/programmer/DeviceData.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEVICEDATA_H 2 | #define _DEVICEDATA_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | struct DeviceData 28 | { 29 | // NV flash 30 | int flash_size; 31 | int flash_rows_per_array; 32 | int flash_num_arrays; 33 | // int flash_num_rows; // derived convenience 34 | 35 | int flash_code_bytes_per_row; 36 | int flash_code_max_size; // dervied 37 | uint32_t flash_code_base_address; 38 | 39 | int flash_config_bytes_per_row; 40 | int flash_config_max_size; // derived 41 | uint32_t flash_config_base_address; 42 | 43 | int flash_rows_per_protection_byte; 44 | 45 | int eeprom_size; 46 | int eeprom_bytes_per_row; 47 | uint32_t eeprom_base_address; 48 | 49 | // methods 50 | 51 | bool read_file(const std::string filename, const std::string devname); 52 | 53 | bool validate(void) const; 54 | void dump(void) const; 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/programmer/HexFileFormat.h: -------------------------------------------------------------------------------- 1 | #ifndef _HexFileFormat_H 2 | #define _HexFileFormat_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | 24 | 25 | namespace HexFileFormat 26 | { 27 | static const uint32_t VERSION = 0x0001; // 2 bytes 28 | 29 | static const uint32_t FLASH_CODE_ADDRESS = 0x00000000; // FIXME Consistency - remove flash or add to others ? 30 | static const uint32_t FLASH_CODE_MAX_SIZE = 0x80000000; // max address space size 31 | 32 | static const uint32_t CONFIG_ADDRESS = 0x80000000; // code or ECC/config typically 33 | static const uint32_t CONFIG_MAX_SIZE = 0x10000000; // max address space size 34 | 35 | static const uint32_t DEVCONFIG_ADDRESS = 0x90000000; // 4 bytes DEVCONFIG_SIZE 36 | static const uint32_t WOL_ADDRESS = 0x90100000; // 4 bytes 37 | 38 | static const uint32_t EEPROM_ADDRESS = 0x90200000; 39 | static const uint32_t EEPROM_MAX_SIZE = 0x00100000; 40 | 41 | static const uint32_t CHECKSUM_ADDRESS = 0x90300000; // 2 bytes 42 | 43 | static const uint32_t PROTECTION_ADDRESS = 0x90400000; 44 | static const uint32_t PROTECTION_MAX_SIZE = 0x00100000; 45 | 46 | static const uint32_t METADATA_ADDRESS = 0x90500000; // 12 bytes 47 | 48 | static const uint32_t METADATA_SIZE = 12; 49 | static const uint32_t VERSION_ADDRESS = METADATA_ADDRESS + 0; // 2 bytes 50 | static const uint32_t DEVICE_ID_ADDRESS = METADATA_ADDRESS + 2; // 4 bytes 51 | static const uint32_t SILICON_REV_ADDRESS = METADATA_ADDRESS + 6; // 1 byte 52 | static const uint32_t DEBUG_ENABLE_ADDRESS = METADATA_ADDRESS + 7; // 1 byte 53 | static const uint32_t METADATA_RESERVED_ADDRESS = METADATA_ADDRESS + 8; // 4 bytes 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/programmer/Makefile: -------------------------------------------------------------------------------- 1 | PROGNAMES=prog 2 | 3 | OBJS= prog.o AppData.o DeviceData.o Programmer.o fx2.o utils.o usb.o 4 | 5 | INC = -I ../libhex -I ../libini 6 | LIBS = ../libhex/libhex.a ../libini/libini.a -L /usr/local/lib -lusb-1.0 7 | 8 | include ../Makefile.inc 9 | 10 | prog: $(OBJS) 11 | $(CXX) $(OBJS) $(LIBS) -o $@ 12 | 13 | install:: prog 14 | -------------------------------------------------------------------------------- /src/programmer/Programmer.h: -------------------------------------------------------------------------------- 1 | #ifndef _PROGRAMMER_H 2 | #define _PROGRAMMER_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "AppData.h" 28 | #include "DeviceData.h" 29 | 30 | //#define SUCCESS true 31 | //#define FAILURE false 32 | #define SUCCESS 0 33 | #define FAILURE -1 34 | 35 | #define DEBUG_REQUEST 0x01 36 | #define DEBUG_REPLY 0x02 37 | #define DEBUG_SPC 0x04 38 | 39 | 40 | #define RD_TRIM_FLASH 0x01 41 | #define RD_TRIM_EEPROM 0x02 42 | #define RD_TRIM_ALL (RD_TRIM_FLASH | RD_TRIM_EEPROM) 43 | 44 | 45 | // verify device return code 46 | #define VERIFY_MATCH 0x00 47 | #define VERIFY_MISMATCH_CODE 0x01 48 | #define VERIFY_MISMATCH_CONFIG 0x02 49 | #define VERIFY_MISMATCH_PROTECTION 0x04 50 | #define VERIFY_MISMATCH_EEPROM 0x08 51 | #define VERIFY_MISMATCH_WOL 0x10 52 | #define VERIFY_MISMATCH_DEVCONFIG 0x20 53 | #define VERIFY_MISMATCH_JTAGID 0x40 54 | 55 | #define VERIFY_MISSING_FILE_DATA 0x1000 56 | #define VERIFY_DEVICE_READ_FAILED 0x2000 57 | 58 | 59 | 60 | struct programmer_priv_s; 61 | 62 | 63 | class Programmer 64 | { 65 | // state 66 | struct programmer_priv_s *m_priv; 67 | bool m_programmer_configured; 68 | DeviceData *m_devdata; 69 | 70 | // config 71 | std::string m_fx2_config_file; 72 | uint32_t m_debug; 73 | uint16_t m_vid_unconfigured; 74 | uint16_t m_pid_unconfigured; 75 | uint16_t m_vid_configured; 76 | uint16_t m_pid_configured; 77 | 78 | // internal 79 | bool SPC_is_idle(bool wait=true); 80 | bool SPC_is_data_ready(bool wait=true); 81 | uint8_t SPC_status(void); 82 | bool SPC_wait_for_status(uint8_t status, bool wait); 83 | bool SPC_cmd(uint8_t cmd, int arg1 = -1, int arg2 = -1, int arg3 = -1); 84 | bool SPC_cmd(uint8_t cmd, uint8_t *args, int nargs); 85 | bool SPC_cmd_idle(uint8_t cmd, int arg1 = -1, int arg2 = -1, int arg3 = -1); 86 | bool SPC_cmd_read(uint8_t *data, int len, uint8_t cmd, int arg1 = -1, int arg2 = -1, int arg3 = -1); 87 | bool SPC_cmd_addr24(uint8_t cmd, uint8_t aid, uint32_t addr, int len); 88 | bool SPC_read_data_b0(uint8_t *data, int len); 89 | bool SPC_cmd_write(const uint8_t *data, int len, uint8_t cmd, int arg1 = -1, int arg2 = -1, int arg3 = -1); 90 | bool SPC_read_data_b4(uint32_t address, uint32_t *data, int len); 91 | bool SPC_cmd_load_row(uint8_t array_id, const uint8_t *data, int len); 92 | 93 | bool NV_WOL_read(AppData *appdata); 94 | bool NV_WOL_write(const AppData *appdata); 95 | bool _NV_WOL_write(const uint8_t *data, int len); 96 | 97 | bool NV_device_config_read(AppData *appdata); 98 | bool NV_device_config_write(const AppData *appdata); 99 | bool _NV_device_config_write(const uint8_t *data, int len); 100 | 101 | bool NV_flash_read(AppData *appdata, bool trim); 102 | bool NV_flash_read_row(v_uint8_t &vdata, uint8_t array_num, uint32_t address); 103 | bool NV_flash_write(const AppData *appdata); 104 | bool NV_flash_write_row(const uint8_t *data, int len, uint8_t array_num, uint32_t address, int even); 105 | int NV_flash_row_length(const AppData *appdata) const; 106 | 107 | bool NV_protection_read(AppData *appdata); 108 | bool NV_protection_write(const AppData *appdata); 109 | 110 | bool NV_eeprom_read(AppData *appdata, bool trim); 111 | bool NV_eeprom_write(const AppData *appdata); 112 | 113 | bool NV_erase_flash(void); 114 | bool NV_erase_sector(uint8_t array_id, uint8_t sector); 115 | 116 | bool NV_flash_checksum(AppData *appdata); 117 | bool NV_checksum_all(uint32_t *checksum); 118 | bool NV_checksum_rows(uint8_t array_id, uint16_t start_row, uint16_t nrows, uint32_t *checksum); 119 | 120 | bool NV_read_multi_bytes(uint8_t array_id, uint32_t address, uint8_t *data, int len); 121 | bool NV_write_row(uint8_t array_id, uint16_t row_num, int die_temp, const uint8_t *data, int len, bool erase_first=true); 122 | bool NV_protect(uint8_t array_id, const uint8_t *data, int len); 123 | bool NV_read_b4(uint8_t array_id, uint32_t *value); 124 | bool NV_write_b4(uint8_t array_id, uint32_t value); 125 | 126 | 127 | bool configure_usb_programmer(void); 128 | bool switch_to_swd(void); 129 | bool send_receive(void); 130 | bool send_c1d4_recv_ok(uint8_t cmd, uint32_t data); 131 | bool jtag_to_swd(void); 132 | bool acquire_target_device(void); 133 | bool release_target_device(void); 134 | 135 | bool ap_register_read(uint32_t address, uint32_t *value, bool dummy_preread=true); 136 | bool ap_register_read(uint32_t address, uint8_t *data, bool dummy_preread=true); 137 | bool ap_register_write(uint32_t address, uint32_t value); 138 | 139 | void set_debug(uint32_t flags) { m_debug = flags; } 140 | // bool verify_checksum(uint16_t reference_checksum); 141 | 142 | void program_geom(int code_len, int *num_arrays, int *row_remainder); 143 | bool read_config(std::string config_dir, std::string config_filename); 144 | 145 | public: 146 | Programmer(); 147 | ~Programmer(); 148 | 149 | int open(std::string config_dir, std::string config_filename, DeviceData *devdata); 150 | void close(); 151 | 152 | bool enter_programming_mode(void); 153 | void exit_programming_mode(void); 154 | 155 | bool configure_target_device(void); // TEMP public !/ 156 | 157 | bool NV_read_checksum(int code_len, uint32_t *checksum); 158 | 159 | bool read_device(AppData *appdata, uint32_t flags); 160 | bool write_device(const AppData *appdata); 161 | bool write_hexfile(const char *filename, const AppData *appdata); 162 | uint32_t verify_device(const AppData *appdata, uint32_t flags); 163 | void dump_flash_data(const AppData *appdata, bool shortform, const char *filename=NULL); 164 | bool erase_flash(void); 165 | void reset_cpu(void); 166 | void usb_clear_stall(void); 167 | 168 | std::string verify_status_string(uint32_t verify_status); 169 | 170 | public: 171 | // misc 172 | int get_die_temperature(void); 173 | uint32_t get_jtag_id(void); 174 | 175 | void usb_print_info(void); 176 | void dostuff(void); 177 | }; 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /src/programmer/fx2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include "fx2.h" 20 | #include "usb.h" 21 | 22 | 23 | #define FX2_RW_RAM 0xA0 24 | #define FX2_RW_EEPROM 0xA2 25 | 26 | 27 | // EZ-USB TRM 001-13670 Appendix C 28 | #define FX2_REG_CPUCS 0xE600 29 | #define FX2_REG_IC_REVISION 0xE60A 30 | 31 | 32 | // command 160 (0xA0) Firmware Load writes to the programmer (or usb interface). First argument is an address 33 | // see for example EZ-USB TRM 001-13670 pg 40 34 | // or https://github.com/makestuff/libfx2loader/blob/master/ram.c 35 | 36 | 37 | int fx2_cmd_rw_ram(libusb_device_handle *dev_handle, uint16_t addr, const char *hex_data_str) 38 | { 39 | uint8_t bmRequestType = 0x40; // VENDOR 0x40 | EP_OUT 0x00 40 | uint8_t bRequest = FX2_RW_RAM; 41 | uint16_t wIndex = 0; 42 | 43 | // wValue = addr 44 | 45 | return control_transfer_out_hex(dev_handle, bmRequestType, bRequest, addr, wIndex, hex_data_str); 46 | } 47 | 48 | 49 | int fx2_cmd_rw_ram(libusb_device_handle *dev_handle, const Block *block) 50 | { 51 | uint8_t bmRequestType = 0x40; // VENDOR 0x40 | EP_OUT 0x00 52 | uint8_t bRequest = FX2_RW_RAM; 53 | uint16_t wIndex = 0; 54 | 55 | return control_transfer_out(dev_handle, bmRequestType, bRequest, block->base_address, wIndex, block->data.data(), block->length()); 56 | } 57 | 58 | 59 | int fx2_cmd_8051_enable(libusb_device_handle *dev_handle, bool enable) 60 | { 61 | //return fx2_cmd_rw_ram(dev_handle, FX2_REG_CPUCS, "00") 62 | uint8_t bmRequestType = 0x40; // VENDOR 0x40 | EP_OUT 0x00 63 | uint8_t bRequest = FX2_RW_RAM; 64 | uint16_t wIndex = 0; 65 | // wValue = addr 66 | uint8_t data = 0x01; 67 | 68 | if (enable) data = 0x00; // CPUCS register bit 0 - 8051RESet. 1=hold in reset, 0=run 69 | return control_transfer_out(dev_handle, bmRequestType, bRequest, FX2_REG_CPUCS, wIndex, &data, 1); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/programmer/fx2.h: -------------------------------------------------------------------------------- 1 | #ifndef _FX2_H 2 | #define _FX2_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include "HexData.h" 26 | 27 | 28 | int fx2_cmd_rw_ram(libusb_device_handle *dev_handle, uint16_t addr, const char *hex_data_str); 29 | int fx2_cmd_rw_ram(libusb_device_handle *dev_handle, const Block *block); 30 | 31 | int fx2_cmd_8051_enable(libusb_device_handle *dev_handle, bool enable); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/programmer/prog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "usb.h" 28 | #include "utils.h" 29 | #include "Programmer.h" 30 | #include "AppData.h" 31 | #include "DeviceData.h" 32 | #include "version.h" 33 | 34 | 35 | // FIXME: put into a siteconfig.h file (and other defaults ?) 36 | #define DEFAULT_CONFIG_DIR "config" 37 | #define DEFAULT_CONFIG_FILE "config.ini" 38 | #define DEFAULT_DEVICE_FILE "devices.dat" 39 | 40 | 41 | struct config_s 42 | { 43 | std::string config_dir; 44 | std::string config_filename; 45 | std::string device_filename; 46 | 47 | std::string device_name; 48 | 49 | DeviceData *devdata; 50 | Programmer *programmer; 51 | 52 | // from config file: 53 | // ... 54 | config_s() : devdata(0), programmer(0) {}; 55 | }; 56 | 57 | typedef int (*cmd_func)(struct config_s *config, int argc, char **argv); 58 | 59 | int cmd_program(struct config_s *config, int argc, char **argv); 60 | int cmd_verify(struct config_s *config, int argc, char **argv); 61 | int cmd_enter_programming(struct config_s *config, int argc, char **argv); 62 | int cmd_reset(struct config_s *config, int argc, char **argv); 63 | int cmd_jtag_id(struct config_s *config, int argc, char **argv); 64 | int cmd_usb_clear(struct config_s *config, int argc, char **argv); 65 | int cmd_upload(struct config_s *config, int argc, char **argv); 66 | int cmd_help(struct config_s *config, int argc, char **argv); 67 | int cmd_erase(struct config_s *config, int argc, char **argv); 68 | 69 | //int parse_commands(struct config_s *config, int argc, char **argv); 70 | 71 | 72 | struct cmds_s { 73 | const char *cmd; 74 | const char *args_desc; 75 | const char *cmd_desc; 76 | int n_mand_args; 77 | cmd_func func; 78 | bool do_connect; // convenience - do programmer open/close for command 79 | bool enter_prog_mode; 80 | bool device_specific; 81 | } Cmds[] = { 82 | {"program", "filename", "program device", 1, cmd_program, false, true, true}, 83 | {"upload", "filename", "read device and save in file", 1, cmd_upload, true, true, true}, 84 | {"verify", "filename", "verify device", 1, cmd_verify, false, true, true}, 85 | {"reset", "", "reset device", 0, cmd_reset, true, true, false}, 86 | {"erase", "", "erase device", 0, cmd_erase, true, true, false}, 87 | {"id", "", "get jtag id", 0, cmd_jtag_id, true, true, false /* hmmm */ }, 88 | {"usb_clear", "", "clear USB error on device", 0, cmd_usb_clear, true, false, false}, 89 | {"help", "", "display help", 0, cmd_help, false, false, false} 90 | }; 91 | 92 | int NCmds = sizeof(Cmds)/sizeof(struct cmds_s); 93 | char *Progname = NULL; 94 | 95 | 96 | 97 | //void usage(const char *progname) 98 | void usage(void) 99 | { 100 | fprintf(stderr, "PSoC Programmer, v%s\n" 101 | "Copyright (C) 2014 Kim Lester, http://www.dfusion.com.au/\n\n" 102 | "Usage: %s CMD\n where CMD is:\n", VERSION_STR, Progname); 103 | int i; 104 | for (i=0; icmd, cmd->args_desc, cmd->cmd_desc); 108 | } 109 | 110 | exit(1); 111 | } 112 | 113 | 114 | bool read_device_config(struct config_s *config) 115 | { 116 | if (config->device_name.length() == 0) 117 | { 118 | fprintf(stderr,"Device Name not specified\n"); 119 | return false; 120 | } 121 | 122 | config->devdata = new DeviceData; 123 | 124 | std::string device_filepath = config->config_dir + std::string("/") + config->device_filename; 125 | 126 | fprintf(stderr, "devdata: filepath:%s, device_name:%s\n", 127 | device_filepath.c_str(), config->device_name.c_str()); 128 | 129 | config->devdata->read_file(device_filepath, config->device_name); 130 | //config->devdata->dump(); 131 | 132 | if (!config->devdata->validate()) 133 | { 134 | fprintf(stderr, "Device %s (File: %s) failed basic validity checks\n", 135 | config->device_name.c_str(), device_filepath.c_str()); 136 | config->devdata->dump(); 137 | return false; 138 | } 139 | 140 | return true; 141 | } 142 | 143 | 144 | Programmer *programmer_open(const struct config_s *config) 145 | { 146 | Programmer *programmer = new Programmer; 147 | 148 | // std::string config_filepath = config->config_dir + std::string("/") + config->config_filename; // FIXME: pathcat 149 | 150 | // fprintf(stderr,"programmer open: config_path:%s\n", config_filepath.c_str()); 151 | if (programmer->open(config->config_dir, config->config_filename, config->devdata) != SUCCESS) 152 | { 153 | fprintf(stderr, "Failed to open device\n"); 154 | return NULL; 155 | } 156 | 157 | programmer->usb_print_info(); 158 | 159 | return programmer; 160 | } 161 | 162 | 163 | void parse_args(int *argc, char ***argv, struct config_s *config) 164 | { 165 | config->config_dir = DEFAULT_CONFIG_DIR; 166 | config->config_filename = DEFAULT_CONFIG_FILE; 167 | config->device_filename = DEFAULT_DEVICE_FILE; 168 | 169 | int ch; 170 | while ((ch = getopt(*argc, *argv, "hC:d:")) != -1) 171 | { 172 | switch (ch) 173 | { 174 | case 'C': 175 | config->config_dir = optarg; 176 | break; 177 | 178 | case 'd': 179 | config->device_name = optarg; 180 | break; 181 | 182 | case 'h': 183 | default: 184 | usage(); 185 | break; 186 | } 187 | } 188 | 189 | *argc -= optind; 190 | *argv += optind; 191 | } 192 | 193 | 194 | int parse_commands(struct config_s *config, int argc, char **argv) 195 | { 196 | const char *cmd_str = argv[0]; 197 | argc--; 198 | 199 | int i; 200 | for (i=0; icmd) != 0) 204 | continue; 205 | 206 | if (argc < cmd->n_mand_args) 207 | break; 208 | 209 | // found command 210 | 211 | if (cmd->device_specific && !read_device_config(config)) 212 | { 213 | fprintf(stderr, "Failed to read device config\n"); 214 | return -1; 215 | } 216 | 217 | if (cmd->do_connect) 218 | { 219 | // FIMXE: messy. maybe create a class. 220 | config->programmer = programmer_open(config); 221 | 222 | if (config->programmer == NULL) return -1; 223 | 224 | if (cmd->enter_prog_mode) 225 | config->programmer->enter_programming_mode(); // every time !? 226 | 227 | int rc = cmd->func(config, argc, ++argv); 228 | 229 | config->programmer->close(); 230 | return rc; 231 | } 232 | else 233 | { 234 | return cmd->func(config, argc, ++argv); 235 | } 236 | } 237 | 238 | usage(); 239 | return -1; // never reaches here 240 | } 241 | 242 | 243 | // CMDS 244 | 245 | int cmd_help(struct config_s *config, int nargs, char **argv) 246 | { 247 | usage(); 248 | return -1; // never reached 249 | } 250 | 251 | 252 | int cmd_program(struct config_s *config, int nargs, char **argv) 253 | { 254 | // read file (check it exists and is ok before connecting to programmer) 255 | 256 | const char *filename = argv[0]; 257 | fprintf(stderr, "program %s\n", filename); 258 | 259 | AppData appdata; 260 | bool rc = appdata.read_hex_file(filename); 261 | 262 | // FIXME: really should verify file signature here - make it a function to read and verify 263 | 264 | if (!rc) 265 | { 266 | fprintf(stderr,"failed to read file [%s]\n", filename); 267 | return -1; 268 | } 269 | 270 | // open programmer 271 | 272 | if (!config->programmer) 273 | config->programmer = programmer_open(config); 274 | 275 | if (config->programmer == NULL) return -1; 276 | 277 | config->programmer->enter_programming_mode(); // Seem to need to be in programming mode to get idcode 278 | 279 | uint32_t idcode = config->programmer->get_jtag_id(); 280 | fprintf(stderr,"Silicon ID: 0x%04x\n", idcode); 281 | // TODO: check it matches file version 282 | 283 | if (appdata.device_id != idcode) 284 | { 285 | fprintf(stderr,"Error. device ids mismatch (file: 0x%08x, device: 0x%08x).\n", appdata.device_id, idcode); 286 | 287 | if (idcode == 0) 288 | fprintf(stderr,"Failed to obtain device id\n"); 289 | else 290 | fprintf(stderr, "Program was compiled for a different type of device."); 291 | 292 | config->programmer->close(); 293 | return -1; 294 | } 295 | 296 | if (!config->programmer->write_device(&appdata)) 297 | { 298 | fprintf(stderr, "* WRITE FAILED!\n"); 299 | config->programmer->close(); 300 | return -1; 301 | } 302 | 303 | config->programmer->close(); 304 | return 0; 305 | } 306 | 307 | 308 | 309 | int cmd_upload(struct config_s *config, int nargs, char **argv) 310 | { 311 | const char *filename = argv[0]; 312 | 313 | AppData appdata; 314 | 315 | config->programmer->enter_programming_mode(); 316 | // uint32_t idcode = programmer->get_jtag_id(); 317 | // fprintf(stderr,"Silicon ID: 0x%04x\n", idcode); 318 | int flags = RD_TRIM_ALL; // FIXME from config 319 | 320 | bool rc = config->programmer->read_device(&appdata, flags); 321 | 322 | appdata.write_hex_file(filename); 323 | 324 | return rc; 325 | } 326 | 327 | 328 | int cmd_verify(struct config_s *config, int nargs, char **argv) 329 | { 330 | assert(config && config->programmer); 331 | 332 | assert(0 && "TO DO"); 333 | 334 | return 0; 335 | } 336 | 337 | 338 | int cmd_enter_programming(struct config_s *config, int nargs, char **argv) 339 | { 340 | assert(config && config->programmer); 341 | 342 | config->programmer->enter_programming_mode(); 343 | return 0; 344 | } 345 | 346 | 347 | int cmd_reset(struct config_s *config, int nargs, char **argv) 348 | { 349 | fprintf(stderr,"config=%p cp=%p\n", config, config->programmer); 350 | assert(config && config->programmer); 351 | 352 | config->programmer->reset_cpu(); 353 | return 0; 354 | } 355 | 356 | 357 | int cmd_erase(struct config_s *config, int nargs, char **argv) 358 | { 359 | assert(config && config->programmer); 360 | 361 | config->programmer->erase_flash(); 362 | return 0; 363 | } 364 | 365 | 366 | int cmd_jtag_id(struct config_s *config, int nargs, char **argv) 367 | { 368 | assert(config && config->programmer); 369 | 370 | uint32_t idcode = config->programmer->get_jtag_id(); 371 | fprintf(stderr,"Silicon ID: 04%04x\n", idcode); 372 | return 0; 373 | } 374 | 375 | 376 | int cmd_usb_clear(struct config_s *config, int nargs, char **argv) 377 | { 378 | assert(config && config->programmer); 379 | 380 | config->programmer->usb_clear_stall(); 381 | return 0; 382 | } 383 | 384 | 385 | // ===== 386 | 387 | int main(int argc, char **argv) 388 | { 389 | int rc = 0; 390 | // const char *progname = argv[0]; 391 | Progname = argv[0]; 392 | 393 | struct config_s config; 394 | 395 | parse_args(&argc, &argv, &config); 396 | 397 | if (argc < 1) usage(); 398 | 399 | if (!usb_init()) 400 | { 401 | fprintf(stderr, "Failed to initialise usb interface"); 402 | return -1; 403 | } 404 | 405 | //libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG); 406 | //list_matching_devices(VID_CYPRESS, PID_ANY); 407 | 408 | //memset(&config, 0, sizeof(config)); 409 | 410 | // FIXME default and cmdline override (also should it be strdup?): 411 | 412 | // std::string config_filepath = config.config_dir + std::string("/") + config.config_filename; // FIXME: pathcat 413 | // INIReader reader(config_filepath); // FIXME: I read file multiple times. Should read it once (but later when structure sorted out) 414 | 415 | // parse main commandline arguments 416 | // string default_device_name = reader.Get(...); // FIXME 417 | 418 | // FIXME: if config_file or device_file start with / don't prepend config_dir, Also need pathcat... 419 | //if (!read_device_config(&config)) { fprintf(stderr, "Failed to read device config\n"); exit(1); } 420 | 421 | // process commands 422 | rc = parse_commands(&config, argc, argv); 423 | 424 | usb_finalise(); 425 | 426 | return rc; 427 | } 428 | -------------------------------------------------------------------------------- /src/programmer/usb.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "usb.h" 25 | #include "utils.h" 26 | 27 | 28 | //#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN) 29 | //#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT) 30 | 31 | #define DEBUG_CONTROL 0x01 32 | #define DEBUG_BULK 0x02 33 | 34 | static uint32_t usb_debug = 0; 35 | 36 | 37 | bool usb_init(void) 38 | { 39 | int rc = libusb_init(NULL); 40 | if (rc < 0) 41 | { 42 | fprintf(stderr, "Failed to initialise usb interface"); 43 | 44 | // finalise 45 | libusb_exit(NULL); 46 | return false; 47 | } 48 | return true; 49 | } 50 | 51 | void usb_finalise(void) 52 | { 53 | libusb_exit(NULL); 54 | } 55 | 56 | 57 | libusb_device_handle *open_device(int vid, int pid, int config, int interface, int alternate) 58 | { 59 | fprintf(stderr,"Config:%d, Interface:%d, Alternate:%d\n", config, interface, alternate); 60 | 61 | //struct libusb_device_descriptor desc; 62 | int rc; 63 | 64 | libusb_device_handle *dev_handle; 65 | 66 | // not supposed to use this conv. func: 67 | dev_handle = libusb_open_device_with_vid_pid(NULL, vid, pid); 68 | if (dev_handle == NULL) 69 | { 70 | fprintf(stderr,"libusb: open device failed\n"); // , rc, libusb_strerror(rc)); 71 | return NULL; 72 | } 73 | 74 | #if 0 75 | int was_attached = 0; 76 | if (libusb_kernel_driver_active(dev_handle, interface)) 77 | { 78 | rc = libusb_detach_kernel_driver(dev_handle, interface); 79 | if (rc < 0) 80 | { 81 | fprintf(stderr,"libusb: detach kernel driver failed: %d %s\n", rc, libusb_strerror(rc)); 82 | libusb_close(dev_handle); 83 | return rc; 84 | } 85 | was_attached = 1; 86 | } 87 | #else 88 | libusb_set_auto_detach_kernel_driver(dev_handle, 1); 89 | #endif 90 | 91 | //get_string_descriptors(dev_handle); 92 | 93 | #if 1 94 | rc = libusb_set_configuration(dev_handle, config); // config==bConfiguraitonValue 95 | if (rc < 0) 96 | { 97 | fprintf(stderr,"libusb: set configuraton %d failed: %d %s\n", config, rc, libusb_strerror((enum libusb_error)rc)); 98 | libusb_close(dev_handle); 99 | return NULL; 100 | } 101 | #endif 102 | 103 | rc = libusb_claim_interface(dev_handle, interface); 104 | if (rc < 0) 105 | { 106 | fprintf(stderr,"libusb: claim interface %d failed: %d %s\n", interface, rc, libusb_strerror((enum libusb_error)rc)); 107 | #if 0 108 | libusb_attach_kernel_driver(dev_handle, interface); 109 | #endif 110 | libusb_close(dev_handle); 111 | return NULL; 112 | } 113 | 114 | #if 1 115 | rc = libusb_set_interface_alt_setting(dev_handle, interface, alternate); 116 | if (rc < 0) 117 | { 118 | fprintf(stderr,"libusb: set alternate interface %d.%d failed: %d %s\n", interface, alternate, rc, libusb_strerror((enum libusb_error)rc)); 119 | libusb_release_interface(dev_handle, interface); 120 | libusb_close(dev_handle); 121 | return NULL; 122 | } 123 | #endif 124 | 125 | //unsigned char reply_data[2048]; 126 | //memset(reply_data,0,2048); 127 | //rc = libusb_get_string_descriptor(dev_handle, 0x02, 0x0409, reply_data, 38); 128 | //fprintf(stderr, "1A string desc: %d, %s\n", rc, reply_data); 129 | 130 | return dev_handle; 131 | } 132 | 133 | 134 | void close_device(libusb_device_handle *dev_handle, int interface) 135 | { 136 | if (dev_handle == NULL) 137 | return; 138 | 139 | int rc; 140 | 141 | rc = libusb_release_interface(dev_handle, interface); 142 | if (rc < 0) 143 | { 144 | fprintf(stderr,"libusb: release interface %d failed: %d %s\n", interface, rc, libusb_strerror((enum libusb_error)rc)); 145 | } 146 | 147 | #if 0 148 | if (was_attached) 149 | rc = libusb_attach_kernel_driver(dev_handle, interface); 150 | if (rc < 0) 151 | fprintf(stderr,"libusb: attach kernel driver failed: %d %s\n", rc, libusb_strerror((enum libusb_error)rc)); 152 | #endif 153 | 154 | libusb_close(dev_handle); 155 | } 156 | 157 | 158 | // Data transfer routines 159 | // ====================== 160 | 161 | int control_transfer_out_hex(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, 162 | uint16_t wValue, uint16_t wIndex, const char *hex_str) 163 | { 164 | // returns ???? 165 | 166 | uint8_t data[2048]; // FIXME Hack 167 | 168 | if (!hex_str) 169 | { 170 | fprintf(stderr, "control_transfer_160_hex: null string\n"); 171 | return -2; 172 | } 173 | 174 | int len = hex_to_bin(hex_str, data, 2048); 175 | if (len < 0) 176 | { 177 | //fprintf(stderr, "Failed convert hex data: %d %s\n", len, NULLSTR(hex_str)); 178 | fprintf(stderr, "Failed convert hex data: %d %s\n", len, hex_str); 179 | return len; 180 | } 181 | //fprintf(stderr, "bin -> %d bytes", len); 182 | #if 0 183 | fprintf(stderr, "H:%s\nB:", NULLSTR(hex_str)); 184 | int i; 185 | for (i=0; i 0: expect *length bytes. *length==0: take what we're given 249 | int timeout_ms = 100; 250 | int actual = 0; 251 | int rc; 252 | // uint8_t dir; 253 | 254 | // dir = LIBUSB_ENDPOINT_OUT; 255 | 256 | // if (dir == LIBUSB_ENDPOINT_IN) 257 | // epaddr |= 0x80; 258 | 259 | rc = libusb_bulk_transfer(dev_handle, epaddr, data, *length, &actual, timeout_ms); 260 | 261 | if (usb_debug & DEBUG_BULK) 262 | { 263 | // if (dir == LIBUSB_ENDPOINT_OUT) 264 | if (epaddr & 0x80) // in if set 265 | fprintf(stderr, "EP 0x%02x: read %d (of a max %d) bytes. %s\n", epaddr, actual, *length, rc==0?"OK":"FAILED"); 266 | else 267 | fprintf(stderr, "EP 0x%02x: wrote %d/%d bytes. %s\n", epaddr, actual, *length, rc==0?"OK":"FAILED"); 268 | } 269 | 270 | if (rc != 0) 271 | fprintf(stderr, "Error %d %s\n", rc, libusb_strerror((enum libusb_error)rc)); 272 | 273 | *length = actual; 274 | 275 | return rc; 276 | } 277 | 278 | 279 | int send_bulk_data(libusb_device_handle *dev_handle, uint8_t epaddr, uint8_t *data, int length) 280 | { 281 | int rc = bulk_data_transfer(dev_handle, epaddr, data, &length); 282 | return rc; 283 | } 284 | 285 | 286 | int send_bulk_data_hex(libusb_device_handle *dev_handle, uint8_t epaddr, const char *hex_str) 287 | { 288 | uint8_t data[2048]; // FIXME Hack 289 | 290 | if (!hex_str) 291 | { 292 | fprintf(stderr, "send_bulk_hex: null string\n"); 293 | return -2; 294 | } 295 | 296 | int len = hex_to_bin(hex_str, data, 2048); 297 | if (len < 0) 298 | { 299 | fprintf(stderr, "Failed convert hex data: %d %s\n", len, hex_str); 300 | return len; 301 | } 302 | 303 | int rc = bulk_data_transfer(dev_handle, epaddr, data, &len); 304 | return rc; 305 | } 306 | 307 | 308 | int recv_bulk_data(libusb_device_handle *dev_handle, uint8_t epaddr, uint8_t *data, int max_length) 309 | { 310 | int rc = bulk_data_transfer(dev_handle, epaddr, data, &max_length); 311 | if (rc < 0) 312 | return rc; 313 | 314 | return max_length; // length actually received 315 | } 316 | 317 | 318 | int clear_endpoint_stall(libusb_device_handle *dev_handle, uint8_t epaddr) 319 | { 320 | uint32_t timeout = 0; 321 | 322 | int len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_ENDPOINT, 323 | LIBUSB_REQUEST_CLEAR_FEATURE, 0 /* ENDPOINT_HALT wValue */, epaddr /* wIndex */, NULL /* reply_data */, 0, timeout); 324 | if (len < 0) 325 | { 326 | fprintf(stderr, "Failed transfer control data: %d %s\n", len, libusb_strerror((enum libusb_error)len)); 327 | return len; 328 | } 329 | 330 | return 0; 331 | } 332 | 333 | // Support routines 334 | // ================ 335 | 336 | 337 | #if 0 338 | void print_string_descriptors(libusb_device_handle *dev_handle, struct libusb_device_descriptor desc) 339 | { 340 | print_string_descriptor(dev_handle, desc->iManufacturer); 341 | print_string_descriptor(dev_handle, desc->iProduct); 342 | print_string_descriptor(dev_handle, desc->iSerialNumber); 343 | } 344 | #endif 345 | 346 | void print_string_descriptor(libusb_device_handle *dev_handle, int index, const char *label) 347 | { 348 | const int max_len = 256; 349 | unsigned char data[max_len+1]; 350 | 351 | data[0] = 0; 352 | 353 | //fprintf(stderr,"DEBUG: %p, max_len=%d\n", dev_handle, max_len); 354 | if (index == 0) 355 | { 356 | fprintf(stderr,"libusb: get_string_descriptor %s %d failed: Cannot get ascii on index=0\n", (label ? label : "Descriptor"), index); 357 | return; 358 | } 359 | 360 | int len = libusb_get_string_descriptor_ascii(dev_handle, (uint8_t) index, data, max_len); 361 | if (len < 0) 362 | { 363 | fprintf(stderr,"libusb: get_string_descriptor %s %d failed: %d %s\n", (label ? label : "Descriptor"), index, len, libusb_strerror((enum libusb_error)len)); 364 | return; 365 | } 366 | // FIXME: NULL TERM ? 367 | assert(len <= 256); 368 | 369 | data[len] = 0; 370 | fprintf(stderr, "%s: %s\n", (label ? label : "Descriptor"), data); 371 | } 372 | 373 | //void release_device(libusb_device_handle *dev_handle) 374 | //{ 375 | // int rc = libusb_release_interface(dev_handle, 0); 376 | //} 377 | 378 | //void send_data(libusb_device_handle *dev_handle, uint8_t *data, int length) 379 | //{ 380 | // //libusb_bulk_transfer(dev_handle, epaddr, data, length, &actual, 100); 381 | //} 382 | 383 | 384 | 385 | void list_matching_devices(int vid, int pid) 386 | { 387 | // if vid == -1, list all devices, if pid == -1 list all devices for matching vid 388 | 389 | fprintf(stderr, "Listing devices matching VID.PID == %04x.%04x\n", vid, pid); 390 | 391 | libusb_device **devs, *dev; 392 | 393 | int ndev = libusb_get_device_list(NULL, &devs); 394 | 395 | int i = 0; 396 | while ((dev = devs[i++]) != NULL) 397 | { 398 | struct libusb_device_descriptor desc; 399 | 400 | int rc = libusb_get_device_descriptor(dev, &desc); 401 | if (rc < 0) 402 | { 403 | fprintf(stderr, "Failed to get device at index %d: %d %s\n", i, rc, libusb_strerror((enum libusb_error)rc)); 404 | continue; 405 | } 406 | 407 | if (vid == -1 || vid == desc.idVendor) 408 | { 409 | if (pid == -1 || pid == desc.idProduct) 410 | { 411 | //get_device_info(pDesc) 412 | fprintf( stderr, "Found matching device: %04x.%04x\n", vid, pid); 413 | //print_device_info(dev, &desc); 414 | print_device_info(dev); 415 | } 416 | } 417 | } 418 | 419 | libusb_free_device_list(devs, 1); 420 | fprintf(stderr,"-------------------------\n"); 421 | } 422 | 423 | //dev_handle1 = libusb_open_device_with_vid_pid(NULL, 0x04B4, desc.idProduct); //opens the Cypress device. Gets the device handle for all future operations. 424 | 425 | const char * Type_str[] = { "Control", "Isochronous", "Bulk", "Interrupt" }; // CHECK 426 | const char * Dir_str[] = { "Out", "In"}; 427 | 428 | 429 | //void print_device_info(libusb_device *dev, struct libusb_device_descriptor *pDesc) 430 | void print_device_info(libusb_device *dev) 431 | { 432 | struct libusb_device_descriptor desc; 433 | libusb_get_device_descriptor(dev, &desc); 434 | 435 | fprintf(stderr, "Bus Num: %2d, Address: %2d\n", 436 | libusb_get_bus_number(dev), libusb_get_device_address(dev)); 437 | 438 | fprintf(stderr, "VID.PID: %04x.%04x\n", desc.idVendor, desc.idProduct); 439 | 440 | fprintf(stderr, "nConfigs: %d\n", desc.bNumConfigurations); 441 | 442 | int config_index = 0; 443 | for(config_index = 0; config_index< desc.bNumConfigurations; config_index++) 444 | { 445 | struct libusb_config_descriptor *config; 446 | libusb_get_config_descriptor(dev, config_index, &config); 447 | 448 | //fprintf( stderr, "Config: %d\n", config_index); 449 | fprintf( stderr, "Config: %d\n", config->bConfigurationValue); 450 | 451 | fprintf( stderr, " nInterfaces: %d\n", config->bNumInterfaces); 452 | 453 | int i,j,k; 454 | 455 | for(i=0; ibNumInterfaces; i++) 456 | { 457 | const struct libusb_interface *inter; 458 | inter = &config->interface[i]; 459 | fprintf( stderr, " nAlternates: %d\n",inter->num_altsetting); 460 | 461 | for(j=0; jnum_altsetting; j++) 462 | { 463 | const struct libusb_interface_descriptor *interdesc; 464 | interdesc = &inter->altsetting[j]; // interface descriptor 465 | fprintf( stderr, " CIA (%d.%d.%d)\n", config->bConfigurationValue, interdesc->bInterfaceNumber, interdesc->bAlternateSetting); 466 | // fprintf( stderr, " interface Number %d\n", interdesc->bInterfaceNumber); 467 | // fprintf( stderr, " Alternate Setting %d\n", interdesc->bAlternateSetting); 468 | fprintf( stderr, " nEndpoints: %d\n", interdesc->bNumEndpoints); 469 | 470 | for(k=0; kbNumEndpoints; k++) 471 | { 472 | const struct libusb_endpoint_descriptor *epdesc; 473 | epdesc = &interdesc->endpoint[k]; // endpoint descriptor 474 | fprintf( stderr, " EP address: %2x ", epdesc->bEndpointAddress); 475 | 476 | int type = epdesc->bmAttributes & 0x03; 477 | int dir = epdesc->bEndpointAddress & 0x80 ? 1 : 0; 478 | fprintf( stderr, " %s %s endpoint\n", Type_str[type], Dir_str[dir]); 479 | } 480 | } 481 | } 482 | 483 | libusb_free_config_descriptor(config); 484 | } 485 | } 486 | 487 | void print_device_info2(libusb_device_handle *dev_handle) 488 | { 489 | libusb_device *dev = libusb_get_device(dev_handle); 490 | assert(dev); 491 | 492 | fprintf(stderr, "Bus Num: %2d, Address: %2d\n", 493 | libusb_get_bus_number(dev), libusb_get_device_address(dev)); 494 | 495 | struct libusb_device_descriptor desc; 496 | libusb_get_device_descriptor(dev, &desc); 497 | 498 | fprintf(stderr, "VID.PID: %04x.%04x\n", desc.idVendor, desc.idProduct); 499 | // fprintf(stderr, "DEBUG: string index, M:%d, P:%d, S/N:%d\n", desc.iManufacturer, desc.iProduct, desc.iSerialNumber); 500 | #if 0 501 | 502 | // FIXME: HACK 503 | desc.iManufacturer = 1; 504 | desc.iProduct = 2; 505 | desc.iSerialNumber = 3; 506 | #endif 507 | 508 | // print_string_descriptor(dev_handle, 0, "Language"); 509 | print_string_descriptor(dev_handle, desc.iManufacturer, "Manufacturer"); 510 | print_string_descriptor(dev_handle, desc.iProduct, "Product"); 511 | print_string_descriptor(dev_handle, desc.iSerialNumber, "Serial Number"); 512 | 513 | fprintf(stderr, "nConfigs: %d\n", desc.bNumConfigurations); 514 | 515 | int config_index = 0; 516 | for(config_index = 0; config_index< desc.bNumConfigurations; config_index++) 517 | { 518 | struct libusb_config_descriptor *config; 519 | libusb_get_config_descriptor(dev, config_index, &config); 520 | 521 | //fprintf( stderr, "Config: %d\n", config_index); 522 | fprintf( stderr, "Config: %d\n", config->bConfigurationValue); 523 | // print_string_descriptor(dev_handle, config->iConfiguration, "Configuration"); 524 | 525 | fprintf( stderr, " nInterfaces: %d\n", config->bNumInterfaces); 526 | 527 | int i,j,k; 528 | 529 | for(i=0; ibNumInterfaces; i++) 530 | { 531 | const struct libusb_interface *inter; 532 | inter = &config->interface[i]; 533 | fprintf( stderr, " nAlternates: %d\n",inter->num_altsetting); 534 | 535 | for(j=0; jnum_altsetting; j++) 536 | { 537 | const struct libusb_interface_descriptor *interdesc; 538 | interdesc = &inter->altsetting[j]; // interface descriptor 539 | fprintf( stderr, " CIA (%d.%d.%d)\n", config->bConfigurationValue, interdesc->bInterfaceNumber, interdesc->bAlternateSetting); 540 | // print_string_descriptor(dev_handle, interdesc->iInterface, "Interface"); 541 | // fprintf( stderr, " interface Number %d\n", interdesc->bInterfaceNumber); 542 | // fprintf( stderr, " Alternate Setting %d\n", interdesc->bAlternateSetting); 543 | fprintf( stderr, " nEndpoints: %d\n", interdesc->bNumEndpoints); 544 | 545 | for(k=0; kbNumEndpoints; k++) 546 | { 547 | const struct libusb_endpoint_descriptor *epdesc; 548 | epdesc = &interdesc->endpoint[k]; // endpoint descriptor 549 | fprintf( stderr, " EP address: %2x ", epdesc->bEndpointAddress); 550 | 551 | int type = epdesc->bmAttributes & 0x03; 552 | int dir = epdesc->bEndpointAddress & 0x80 ? 1 : 0; 553 | fprintf( stderr, " %s %s endpoint\n", Type_str[type], Dir_str[dir]); 554 | } 555 | } 556 | } 557 | 558 | libusb_free_config_descriptor(config); 559 | } 560 | } 561 | -------------------------------------------------------------------------------- /src/programmer/usb.h: -------------------------------------------------------------------------------- 1 | #ifndef _USB_H 2 | #define _USB_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | bool usb_init(void); 32 | void usb_finalise(void); 33 | 34 | libusb_device_handle *open_device(int vid, int pid, int config, int interface, int alternate); 35 | void close_device(libusb_device_handle *dev_handle, int interface); 36 | 37 | int control_transfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t *reply_length, uint16_t max_length); 38 | int control_transfer_out_hex(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, const char *hex_str); 39 | int control_transfer_out(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, const uint8_t *data, int len); 40 | 41 | int bulk_data_transfer(libusb_device_handle *dev_handle, uint8_t epaddr, uint8_t *data, int *length); 42 | 43 | //void send_data(libusb_device_handle *dev_handle, uint8_t *data, int length); 44 | int send_bulk_data(libusb_device_handle *dev_handle, uint8_t epaddr, uint8_t *data, int length); 45 | int send_bulk_data_hex(libusb_device_handle *dev_handle, uint8_t epaddr, const char *hex_data_str); 46 | int recv_bulk_data(libusb_device_handle *dev_handle, uint8_t epaddr, uint8_t *data, int max_length); 47 | 48 | int clear_endpoint_stall(libusb_device_handle *dev_handle, uint8_t epaddr); 49 | 50 | void list_matching_devices(int vid, int pid); 51 | //void print_device_info(libusb_device *dev, struct libusb_device_descriptor *pDesc); 52 | void print_device_info(libusb_device *dev); 53 | void print_device_info2(libusb_device_handle *dev_handle); 54 | //void find_device(int vid, int pid, struct libusb_device_descriptor *pDesc); 55 | //void print_string_descriptors(libusb_device_handle *dev_handle); 56 | void print_string_descriptor(libusb_device_handle *dev_handle, int index, const char *label); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/programmer/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "utils.h" 26 | 27 | 28 | #if 0 29 | void dump_vector(FILE *fp, const char *msg, const v_uint8_t v) 30 | { 31 | if (msg) fprintf(fp, "%s: ", msg); 32 | 33 | const uint8_t *vp = v.data(); 34 | int i; 35 | for(i=0;i> 8) & 0xFF; 73 | b[1] = data & 0xFF; 74 | } 75 | 76 | 77 | void uint16_to_b2_LE(uint32_t data, uint8_t *b) 78 | { 79 | b[1] = (data >> 8) & 0xFF; 80 | b[0] = data & 0xFF; 81 | } 82 | 83 | 84 | void uint32_to_b4_BE(uint32_t data, uint8_t *b) 85 | { 86 | b[0] = (data >> 24) & 0xFF; 87 | b[1] = (data >> 16) & 0xFF; 88 | b[2] = (data >> 8) & 0xFF; 89 | b[3] = data & 0xFF; 90 | } 91 | 92 | 93 | void uint32_to_b4_LE(uint32_t data, uint8_t *b) 94 | { 95 | b[3] = (data >> 24) & 0xFF; 96 | b[2] = (data >> 16) & 0xFF; 97 | b[1] = (data >> 8) & 0xFF; 98 | b[0] = data & 0xFF; 99 | } 100 | 101 | 102 | uint32_t b4_BE_to_uint32(const uint8_t *b) 103 | { 104 | uint32_t value = (b[0] << 24) | (b[1] << 16) | (b[2]<< 8) | b[3]; 105 | return value; 106 | } 107 | 108 | 109 | uint32_t b4_LE_to_uint32(const uint8_t *b) 110 | { 111 | uint32_t value = (b[3] << 24) | (b[2] << 16) | (b[1]<< 8) | b[0]; 112 | return value; 113 | } 114 | 115 | 116 | int hex_to_bin(const char *hex, uint8_t *bin, int max_bin_len) 117 | { 118 | // doesn't zero bin. If len hex is 0, bin untouched 119 | 120 | if (!hex) 121 | return -1; // or return 0 !? 122 | 123 | int length = strlen(hex); 124 | 125 | if (length > 2*max_bin_len || length % 2 != 0) 126 | return -1; 127 | 128 | uint8_t *dp = bin; 129 | int v = 0; 130 | 131 | int i; 132 | for (i=0; i= '0' && c <= '9') 137 | v |= c - '0'; 138 | else if (c >= 'a' && c <= 'f') 139 | v |= c - 'a' + 10; 140 | else if (c >= 'A' && c <= 'F') 141 | v |= c - 'A' + 10; 142 | else 143 | { 144 | //fprintf(stderr, "Err: [%c,%2x]\n", c, c); 145 | assert(0 && "invalid hex"); 146 | } 147 | 148 | //fprintf(stderr, "i:%d %c\n", i, c); 149 | if ((i & 0x01) == 0) 150 | v <<= 4; 151 | else 152 | { 153 | *(dp++) = v; 154 | v = 0; 155 | } 156 | } 157 | 158 | return length >> 1; 159 | } 160 | 161 | 162 | #if 0 163 | int XXhex_to_bin(const char *hex, uint8_t *bin, int max_bin_len) 164 | { 165 | if (!hex) 166 | return -1; 167 | 168 | int length = strlen(hex); 169 | 170 | if (length > max_bin_len || length % 2 != 0) 171 | return -1; 172 | 173 | int o=0; 174 | 175 | int i; 176 | for (i=0; i= '0' && c <= '9') 186 | v |= c - '0'; 187 | else if (c >= 'A' && c <= 'F') 188 | v |= c - '0' + 10; 189 | else 190 | { 191 | assert(0 && "invalid hex"); 192 | } 193 | 194 | v <<= 4; 195 | } 196 | data[o++] = v; 197 | } 198 | } 199 | #endif 200 | -------------------------------------------------------------------------------- /src/programmer/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H 2 | #define _UTILS_H 3 | 4 | /* 5 | Copyright (C) 2014 Kim Lester 6 | http://www.dfusion.com.au/ 7 | 8 | This Program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This Program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this Program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #define NULLSTR(s) ((s) ? (s) : "") 26 | 27 | // FIXME: I don't actually have dest types so to_Uxx is academic 28 | // FIXME: I have both macros and funcs below 29 | #define B4LE_to_U32(c) (((c)[3]<<24) | ((c)[2] << 16) | ((c)[1] << 8) | (c)[0] ) 30 | #define B4BE_to_U32(c) (((c)[0]<<24) | ((c)[1] << 16) | ((c)[2] << 8) | (c)[3] ) 31 | #define B2LE_to_U32(c) (((c)[1] << 8) | (c)[0] ) 32 | #define B2BE_to_U16(c) (((c)[0] << 8) | (c)[1] ) 33 | 34 | #ifndef MIN 35 | #define MIN(a,b) ((a) <= (b) ? (a) : (b)) 36 | #endif 37 | 38 | #ifndef MAX 39 | #define MAX(a,b) ((a) >= (b) ? (a) : (b)) 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int hex_to_bin(const char *hex, uint8_t *bin, int max_bin_len); 47 | void dump_data(FILE *fp, const uint8_t *data, int len, const char *msg); 48 | bool match(const uint8_t *data, int data_len, const char *hex_data); 49 | 50 | void uint16_to_b2_BE(uint32_t data, uint8_t *b); 51 | void uint16_to_b2_LE(uint32_t data, uint8_t *b); 52 | void uint32_to_b4_BE(uint32_t data, uint8_t *b); 53 | void uint32_to_b4_LE(uint32_t data, uint8_t *b); 54 | 55 | uint32_t b4_BE_to_uint32(const uint8_t *b); 56 | uint32_t b4_LE_to_uint32(const uint8_t *b); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/programmer/version.h: -------------------------------------------------------------------------------- 1 | #ifndef _VERSION_H 2 | #define _VERSION_H 3 | 4 | #define VERSION_STR "0.1" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/support/app_config.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Kim Lester 3 | http://www.dfusion.com.au/ 4 | 5 | This Program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This Program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this Program. If not, see . 17 | */ 18 | 19 | #include 20 | #include "libc.h" 21 | 22 | 23 | #if DEBUG 24 | #include 25 | #include 26 | #include 27 | #include 28 | #endif 29 | 30 | 31 | // Config Table Types 32 | #define CFG_TT_END 0 33 | #define CFG_TT_CF 1 34 | #define CFG_TT_OV 2 35 | #define CFG_TT_DA 3 36 | #define CFG_TT_AC 4 37 | 38 | #define config_base_addr ((const uint8_t *)0x48000000) 39 | 40 | static void cfg_set_regions(const uint8_t *cfg_base_addr) 41 | { 42 | // Note: count is [cc]cc + 1. Zero is not allowed except in END case. 43 | 44 | // table: [ ttcc aaaa aaaa ]* 0000 0000 45 | // tt = type, cc = value|00 46 | // element: tt == 1: constant fill subtable 47 | // ccvv # cccc 48 | // element: tt == 2: offset value subtable 49 | // [ oovv ]+(cc) 50 | // element: tt == 3: data array subtable 51 | // [ vv ]+(cc) 52 | // element: tt == 4: address copy subtable 53 | // ssss ssss 54 | 55 | //uint32_t *tablebase = &config_base_addr[0]; 56 | // WARNING for compactness 32 bit addresses are NOT aligned on relevant memory boundaries. 57 | // easiest way to manage data is 8 bit chunks. (unless I pad case 3 for cc == 1) 58 | 59 | const uint8_t *tbl = cfg_base_addr; 60 | while(1) 61 | { 62 | uint8_t table_type = tbl[0]; 63 | uint32_t count = tbl[1] + 1; // Note + 1. uint32_t to handle count=63336. 64 | 65 | #if DEBUG 66 | printf("Table Type: %d\n", table_type); 67 | #endif 68 | if (table_type == CFG_TT_END) break; 69 | 70 | uint32_t addr = (tbl[5] << 24) | (tbl[4] << 16) | (tbl[3] << 8) | tbl[2]; 71 | uint8_t *ap = (uint8_t *)(intptr_t)addr; 72 | 73 | tbl += 6; 74 | 75 | if (table_type == CFG_TT_CF) 76 | { 77 | // constant fill: ccvv 78 | uint8_t count_hi = tbl[0]; 79 | uint8_t value = tbl[1]; 80 | count += (count_hi << 8); 81 | #if DEBUG 82 | printf(" CF: %p = 0x%02x * %d\n", ap, value, count); 83 | #else 84 | memset(ap, value, count); 85 | #endif 86 | tbl += 2; 87 | } 88 | else if (table_type == CFG_TT_OV) 89 | { 90 | // offset value: [ oovv ]+(count) 91 | uint8_t i; 92 | for(i=0; i 5 | 6 | void cfg_set_regions(const uint8_t *cfg_base_addr); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/tests/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = support 2 | 3 | include ../../Makefile.inc 4 | -------------------------------------------------------------------------------- /src/tests/support/Makefile: -------------------------------------------------------------------------------- 1 | PROGNAMES=test_config_data 2 | 3 | INC = -I ../../support 4 | CFLAGS += -DSRC_TEST_MODE 5 | 6 | all: $(TARGETS) tests 7 | 8 | include ../../Makefile.inc 9 | 10 | config_data.c: 11 | $(COPY) ../../support/$@ . 12 | 13 | test_config_data: config_data.o test_config_data.o 14 | 15 | tests: test_config_data 16 | ./test_config_data test.bin > test1.out 17 | diff test1.out test1.ref 18 | # [ $? -eq 0 ] || echo "ERROR" 19 | # rm test1.out 20 | 21 | 22 | clean:: 23 | $(RM) test1.out 24 | -------------------------------------------------------------------------------- /src/tests/support/config_data.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "config_data.h" 5 | 6 | 7 | #ifdef SRC_TEST_MODE 8 | #include 9 | #endif 10 | 11 | // Config Table Types 12 | #define CFG_TT_UNDEF 0 13 | #define CFG_TT_CF 1 14 | #define CFG_TT_OV 2 15 | #define CFG_TT_DA 3 16 | #define CFG_TT_COPY 4 17 | 18 | 19 | void cfg_set_regions(const uint8_t *cfg_base_addr) 20 | { 21 | // Refer: docs/romdata.txt 22 | 23 | // table: [ ttcc aaaa aaaa ]* 0000 24 | // tt = type, cc = value 25 | // element: tt == 1: constant fill 26 | // ccvv # cccc 27 | // element: tt == 2: offset value 28 | // [ oovv ]+(cc) 29 | // element: tt == 3: data array 30 | // [ vv ]+(cc) 31 | // element: tt == 4: mem to mem copy 32 | // ssss ssss 33 | 34 | // WARNING for compactness 32 bit addresses are NOT aligned on relevant memory boundaries. 35 | // easiest way to manage data is 8 bit chunks. (unless I pad case 3 for cc == 1) 36 | 37 | const uint8_t *tbl = cfg_base_addr; 38 | while(1) 39 | { 40 | uint8_t table_type = tbl[0]; 41 | uint8_t count_low = tbl[1]; 42 | 43 | if (table_type == CFG_TT_UNDEF) break; 44 | 45 | uint32_t addr = (tbl[5] << 24) | (tbl[4] << 16) | (tbl[3] << 8) | tbl[2]; 46 | uint8_t *ap = (uint8_t *)((size_t)addr); 47 | 48 | #ifdef SRC_TEST_MODE 49 | //printf("T: %d, A:%x ", table_type, addr); 50 | printf("T: %d ", table_type); 51 | #endif 52 | tbl += 6; 53 | 54 | if (table_type == CFG_TT_CF) 55 | { 56 | // constant fill: ccvv 57 | uint8_t count_hi = tbl[0]; 58 | uint8_t value = tbl[1]; 59 | uint16_t count = (count_hi << 8) | count_low; 60 | #ifdef SRC_TEST_MODE 61 | printf("CF: %lx = %d * %d\n", (size_t)ap, value, count); 62 | #else 63 | memset(ap, value, count); 64 | #endif 65 | tbl += 2; 66 | } 67 | else if (table_type == CFG_TT_OV) 68 | { 69 | // offset value: [ oovv ]+(count) 70 | uint8_t i; 71 | for(i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "config_data.h" 9 | 10 | 11 | int main(int argc, char **argv) 12 | { 13 | if (argc < 2) 14 | { 15 | fprintf(stderr,"Usage: %s FILENAME\n", argv[0]); 16 | exit(1); 17 | } 18 | 19 | const char *filename = argv[1]; 20 | 21 | FILE *fp = fopen(filename, "r"); 22 | if (fp == NULL) 23 | { 24 | fprintf(stderr,"Failed to open file: %s - %s\n", filename, strerror(errno)); 25 | exit(1); 26 | } 27 | 28 | struct stat st; 29 | 30 | fstat(fileno(fp), &st); 31 | 32 | uint8_t *buf = (uint8_t *)calloc(st.st_size, 1); 33 | 34 | fread(buf, st.st_size, 1, fp); 35 | 36 | cfg_set_regions(buf); 37 | } 38 | -------------------------------------------------------------------------------- /src/tools/Makefile: -------------------------------------------------------------------------------- 1 | PROGNAMES=hex2bin mergehex hexinfo 2 | SCRIPTNAMES= freehex2other.py gen_config.py 3 | 4 | INC = -I ../libhex -I ../programmer 5 | LIBS = -L ../libhex -lhex 6 | 7 | include ../Makefile.inc 8 | 9 | mergehex: mergehex.cpp ../programmer/AppData.cpp ../programmer/utils.c 10 | $(CXX) $(INC) -o $@ $^ $(LIBS) 11 | 12 | hexinfo: hexinfo.cpp ../programmer/AppData.cpp ../programmer/utils.c 13 | $(CXX) $(INC) -o $@ $^ $(LIBS) 14 | 15 | hex2bin: hex2bin.cpp 16 | $(CXX) $(INC) -o $@ $^ $(LIBS) 17 | -------------------------------------------------------------------------------- /src/tools/freehex2other.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (C) 2014 Kim Lester 4 | # http://www.dfusion.com.au/ 5 | # 6 | # This Program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This Program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this Program. If not, see . 18 | 19 | 20 | import sys 21 | import argparse 22 | import binascii 23 | 24 | # Input format "free format hex": 25 | # - ASCII file 26 | # - Ignores whitespace between pairs of hex digits 27 | # - Ignores rest of line after a # (comment character) 28 | 29 | # TODO as needed: 30 | # intelhex could have a base address arg, or read it from an input #define 31 | 32 | Output_formats = ("hex", "intelhex", "binary") 33 | 34 | 35 | def parse_command_line(): 36 | parser = argparse.ArgumentParser(description='Convert ASCII hex bytes to other formats') 37 | parser.add_argument('-f', required=True, nargs=1, dest='output_format', help='output format: %s' % (",".join(Output_formats))) 38 | parser.add_argument('-i', nargs=1, dest="infile", help="input file. Default stdin") 39 | parser.add_argument('-o', nargs=1, dest="outfile", help="output file. Default stdout") 40 | 41 | return (parser, parser.parse_args()) 42 | 43 | 44 | def read_file(infile): 45 | # infile is an array or null need infile[0] 46 | ba = bytearray() 47 | fin = None 48 | 49 | if infile is None: 50 | fin = sys.stdin 51 | else: 52 | fin = open(infile[0], 'r') 53 | 54 | linenum = 1 55 | for line in fin.readlines(): 56 | line = line.split('#', 1)[0] # throw away any comment 57 | line = line.strip() 58 | # Note: fromhex() ignores whitespace between pairs of hex chars 59 | try: 60 | ba.extend(bytearray.fromhex(line)) 61 | except (ValueError): 62 | print("Failed to parse input line %d :" % (linenum) ,line, file=sys.stderr) 63 | sys.exit(1) 64 | linenum += 1 65 | 66 | if fin != sys.stdin: 67 | fin.close() 68 | return ba 69 | 70 | 71 | def output(outfile, ba): 72 | # FIXME: check if file already exists 73 | # Python 3 cares about 'b' even under Unix 74 | # Note: cannot output binary to stdout 75 | 76 | outfunc = None 77 | outmode = '' 78 | 79 | if format == "hex": 80 | outfunc = b2h 81 | elif format == "intelhex": 82 | outfunc = b2ih 83 | elif format == "binary": 84 | outfunc = b2b 85 | outmode = 'b' 86 | 87 | fout = None 88 | 89 | if outfile is None: 90 | fout = sys.stdout 91 | if outmode == 'b': 92 | print("Cannot output binary to stdout", file=sys.stderr) 93 | # FIXME: there are ways to do this... 94 | sys.exit(1) 95 | else: 96 | fout = open(outfile[0], 'w'+outmode) 97 | 98 | if fout is None: 99 | print("Failed to create file %s" % (outfile), file=sys.stderr) 100 | sys.exit(1) 101 | 102 | outfunc(ba, fout) 103 | 104 | if fout != sys.stdout: 105 | fout.close() 106 | 107 | 108 | def b2h(ba, fout): 109 | s = binascii.b2a_hex(ba) # == hexlify() 110 | fout.write(s.decode().upper()) 111 | 112 | 113 | def b2b(ba, fout): 114 | fout.write(ba) 115 | 116 | 117 | def b2ih(ba, fout): 118 | ''' bytes to intel hex ''' 119 | 120 | max_linelen = 32 121 | base_addr = 0 # FIXME: set this !? 122 | # FIXME: does not handle address+offset > 2^16 123 | 124 | offset = 0 125 | while 1: 126 | b = ba[offset:offset+max_linelen] 127 | actual_linelen = len(b) 128 | if actual_linelen == 0: 129 | break 130 | 131 | ihexleader = "%02X%04X00" % (actual_linelen, base_addr+offset) 132 | bindata = binascii.a2b_hex(ihexleader) + b 133 | cksum = ((sum(bindata) ^ 0xFF) + 1) & 0xFF # two's complement of LSB 134 | asciihex = binascii.b2a_hex(bindata).decode('ascii').upper() 135 | print(":%s%02X" % (asciihex,cksum), file=fout) 136 | offset += actual_linelen 137 | 138 | print(":00000001FF", file=fout); 139 | 140 | # --- main --- 141 | 142 | (parser, args) = parse_command_line() 143 | 144 | format = args.output_format[0] 145 | 146 | if format not in Output_formats: 147 | print("Output format must be one of: %s" % (",".join(Output_formats)), file=sys.stderr) 148 | sys.exit(1) 149 | 150 | ba = read_file(args.infile) 151 | output(args.outfile, ba) 152 | -------------------------------------------------------------------------------- /src/tools/gen_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (C) 2014 Kim Lester 4 | # http://www.dfusion.com.au/ 5 | # 6 | # This Program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This Program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this Program. If not, see . 18 | 19 | # ----- 20 | 21 | 22 | # Overview 23 | # 24 | # This utility is used to create configuration data (address and data) values 25 | # to initialise microcontroller configuration registers. 26 | # It creates a list of various data structures. Each structure is designed 27 | # to optimise one common type of data initialisation requirement (eg constant 28 | # fill, data copy etc). The data may be stored anywayre in FLASH but on PSOC 29 | # is typically stored in the so called FLASH "configuration" area. A C function 30 | # is supplied to walk the list, decode and action each entry. 31 | 32 | # Source File Format 33 | # ------------------ 34 | # 35 | # Grammer: 36 | # #include "filename.h" 37 | # #define NAME VALUE 38 | # #label NAME ADDRESS 39 | # 40 | # addr : value * count # Source type 1 41 | # addr : value # Source type 2 42 | # addr : hex bytes.... [ @ width ] # Source type 3 NOTE: dest width not currently supported 43 | # addr : [src_addr] [* count] # Source type 4 Default count 1 44 | 45 | # Future: ?? 46 | # addr : [off:value]+ # Source type 5 47 | # 48 | # Labels: 49 | # * Labels are an additional construct. They are output unchanged in the 50 | # freehex output format. Their purpose is to add metadata to the output file (eg data load address) 51 | # 52 | # * FIXME: True or not: only one label is currently permitted and it must occur before any "addr:" lines. 53 | # * FIXME: Should any coalescence be prevented from crossing label locations so that labels can be used to 54 | # create distinct config data sets (eg with diff load addresses) in a single file. 55 | # 56 | # 57 | # Notes: 58 | # * addr, value, count may be expressed in standard C (well Python) 59 | # format, decimal, hex (0x...) etc. 60 | # 61 | # * normal C include files can be used to pull in #define lines. 62 | # FIXME: This tool does not currently support #define macros or defines with expressions on RHS. 63 | # 64 | # * A count == 0 in the source file is not valid. 65 | # 66 | # * Source Types and Output types more or less match trivially. 67 | # Source Type -> Output Table Type (TT) 68 | # 1 1 CF Constant Fill 69 | # 2 ** 3 or 2. It depends. See below ** 70 | # 3 3 DA Data Array (single value is most compact) 71 | # 4 4 AC Address Copy (memcpy) 72 | # 73 | # * A single byte value could be INPUT using Source Types 1, 2 or 3 74 | # * For a single byte Source Type 3 syntactically reduces to Source Type 2. 75 | # * For a single byte all three source types (1,2,3) reduce to the same 76 | # internal format. Therefore single bytes will always be output in a 77 | # consistent format regardless of source construct. 78 | # 79 | # * A single byte may be OUTPUT using Output Types 1 (CF), 2 (OV), 3(DA) 80 | # The most compact representation for a single byte happens to be DA. 81 | # Thus DA is the canonical format for outputting a single byte. 82 | # 83 | # However a group of single byte values in a config file will often be 84 | # within a small address range. Therefore a run of single byte values 85 | # within an address range of 256 bytes can be efficiently coded using 86 | # output type 2 offset,value (OV). 87 | # Thus Output Type 2 (OV) is automatically generated as needed and 88 | # cannot be explicitly specified in the Source File unless Source Type 5 89 | # is implemented (to support entering small address offsets). 90 | # 91 | # Limits: 92 | # Constant Fill: count <= 65536 93 | # Data Array: <= 256 bytes 94 | # Address Copy: <= 256 bytes 95 | # Offset Value: address offset range <= 255 (count <=256 but offset <= 255) 96 | 97 | 98 | # Output Modes 99 | # ------------ 100 | # * there are two output modes - strictly in source order and optimised 101 | # (within a label group?). The optimisation mode groups multiple 102 | # single value type 2 items into a CFG_TT_OV structure where possible. 103 | # 104 | # * It is possible to write an address twice. A realistic use case is to zero 105 | # a large block (CF) and then sparse write values into it later. 106 | # With output mode preserving source order it is up to the data file creator 107 | # to put the block fill before any sparse fill of individual values. 108 | # * Optimised mode gathers Source Type 2 entries together to compress storage space. 109 | # To permit bulk fills and sparse writes to the same space the general 110 | # rule is bulk fills first then sparse. 111 | # In practice the key rule is probably only: 112 | # In output file put CF (bulk fill) before others. 113 | # An additional refinement might be CF before AC before others too. 114 | # 115 | # To ensure results are determinant between version the following order is 116 | # used when output is optimised (LHS output/executed first): 117 | # 118 | # CF -> AC -> DA(multi) -> OV -> DA(single) 119 | # 120 | # Note that DA multi is like AC so it comes before OV and DA single 121 | 122 | 123 | # Output/Memory Data Structure 124 | # ---------------------------- 125 | # 126 | # The top level entity is a list of data structures. The first byte of a 127 | # structure contains the structure type, the list ends with an element 128 | # type of CFG_TT_END. There are 4 types of initialisation structure: 129 | # Type: 1: constant fill, 2: data fill, 3:offset,value, 4: mem to mem copy 130 | # 131 | # Note: to permit count to handle common values of 256/65536 the stored count value has 1 added to it. 132 | # Therefore a count of 0 is not possible. 133 | 134 | # list structure: 135 | # [ HEADER ELEMENT ]* 0000 136 | # -> 137 | # [ ttcc aaaa aaaa ELEMENT ]* 0000 138 | # tt: type 139 | # cc: count_low - 1 # add 1 to get real count (ie stored 0 -> count=1, 1->2 etc) 140 | # a...a: 32 bit address 141 | # 0000 is the list terminating value of ttcc 142 | # 143 | # 144 | # ELEMENT tt == 1: constant fill (CF) 145 | # ccvv 146 | # cc: count_hi 147 | # vv: value 148 | # 149 | # ELEMENT tt == 2: offset value (OV) 150 | # [ oovv ]+ 151 | # oo: offset 152 | # vv: value 153 | # "oovv" structure repeats cc (count_low) times 154 | # 155 | # ELEMENT tt == 3: data array (DA) 156 | # [ vv ]+ 157 | # vv: value 158 | # "vv" structure repeats cc (count_low) times 159 | # 160 | # ELEMENT tt == 4: address copy (AC) 161 | # ssss ssss 162 | # s...s: 32 bit (source) address 163 | # 164 | # 165 | # Note: 166 | # * For compactness addresses (eg 32 bit addresses) are NOT aligned on usual 167 | # memory boundaries. Note that ARMv7-M can handle unaligned 16/32 bit reads (not 64) IIRC, 168 | # Form ARMv6 and earlier can do byte reads and reconstruct any 16/32 bit values. 169 | 170 | # TODO 171 | # ---- 172 | # add option for preserve/optimise order 173 | # optional: source type 5 174 | # optional: add other output formats. However can just pipe output to freehex2other.py 175 | # optional: add command line argument for endianness 176 | # optional: add command line argument for debug 177 | # optional: implement dest width in source type 3 178 | 179 | 180 | import collections 181 | import re 182 | import sys 183 | import argparse 184 | 185 | 186 | Debug = 0 187 | 188 | 189 | CFG_TT_UNDEF = -1 190 | CFG_TT_END = 0 191 | CFG_TT_CF = 1 192 | CFG_TT_OV = 2 193 | CFG_TT_DA = 3 194 | CFG_TT_AC = 4 195 | CFG_TT_LABEL = -1 # special type (put in configItem to maintain sequencing only) 196 | 197 | 198 | ConfigItem = collections.namedtuple('ConfigItem', 'type addr value count') 199 | # For output type OV: ConfigItem value is a dict[off] = value, count = len(dict) 200 | # For output type AC: ConfigItem value is the source address 201 | 202 | re_define = re.compile(r"#define\s+(?P\w+)\s+(?P.*)") 203 | 204 | #Output_formats = ("hex", "intelhex", "binary") 205 | 206 | 207 | def parse_command_line(): 208 | parser = argparse.ArgumentParser(description='Compile config data into freehex file format') 209 | # parser.add_argument('-f', required=True, nargs=1, dest='output_format', help='output format: %s' % (",".join(Output_formats))) 210 | # Note I don't currently see any point in supporting read from stdin 211 | # Leave as -i though rather than positional for consistency and so natural 212 | # cmdline order is infile then outfile 213 | parser.add_argument('-i', required=True, nargs=1, dest="infile", help="input file") 214 | parser.add_argument('-o', nargs=1, dest="outfile", help="output file. Default stdout") 215 | 216 | return (parser, parser.parse_args()) 217 | 218 | 219 | def read_symtab(symtab, filename): 220 | linenum = 0 221 | with open(filename) as f: 222 | for line in f.readlines(): 223 | linenum += 1 224 | 225 | m = re_define.match(line) 226 | if m is not None: 227 | # print('DEF:', m.group('name'), m.group('value'), file=sys.stderr) 228 | symtab[m.group('name')] = m.group('value') 229 | 230 | if Debug: 231 | for k,v in symtab.items(): 232 | print('d:', k, v, file=sys.stderr) 233 | 234 | 235 | def get_uint(symtab, valuestr, context=None): 236 | ''' get integer value of valuestr performing any symtab substitutions ''' 237 | # context is optional list: (linenum origline) 238 | 239 | orig_valuestr = valuestr # for error handling only 240 | 241 | # repeatedly convert #define to their values 242 | while valuestr in symtab: 243 | # print("Converting %s to %s" % (valuestr, symtab[valuestr]), file=sys.stderr) 244 | valuestr = symtab[valuestr] 245 | 246 | # FIXME: HACkish. The #defines being used have numbers ending in 'u' like 0x12345u 247 | if valuestr[-1:] == 'u': 248 | valuestr = valuestr[:-1] 249 | 250 | # should be an integer by now (in some base) 251 | try: 252 | value=int(valuestr, 0) 253 | except (ValueError): 254 | context_msg = "" 255 | if context is not None: 256 | context_msg = " at line %d.\nOriginal line: %sFailed expression after substitution was: %s" % (context[0], context[1], valuestr) 257 | print("Failed to convert variable '%s' to an integer%s" % (orig_valuestr, context_msg), file=sys.stderr) 258 | # not great style to exit here but it's a simple program 259 | sys.exit(1); 260 | 261 | return value 262 | 263 | 264 | def parse(configfile): 265 | config = [] 266 | symtab = {} 267 | 268 | # re_blank = re.compile("^$") 269 | re_expr = re.compile(r"(?P\w+):(?P\w+|\[\w+\])(?P\*)?(?P.*)") 270 | re_brackets = re.compile(r"\[(?P\w+)\]") 271 | # re_include = re.compile(r"#include\s+\"(?P\w+)\"|<(?\w+)>") 272 | re_include = re.compile(r"#include\s+\"(?P[^\"]+)\"") 273 | re_label = re.compile(r"#label\s+(?P