From 14e7cf69fe253dc09f7990769166776c84936f7f Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 10 Aug 2023 19:36:50 +0200 Subject: [PATCH] init --- .clang-format | 42 ++ .gitignore | 4 + LICENSE | 20 + README.md | 0 data/flangers.hex | 1025 ++++++++++++++++++++++++++++++++++ data/flangers.hex.bin.target | Bin 0 -> 4096 bytes src/Makefile | 45 ++ src/fvhex2bin.c | 194 +++++++ src/kk_ihex.h | 191 +++++++ src/kk_ihex_read.c | 181 ++++++ src/kk_ihex_read.h | 117 ++++ 11 files changed, 1819 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 data/flangers.hex create mode 100644 data/flangers.hex.bin.target create mode 100644 src/Makefile create mode 100644 src/fvhex2bin.c create mode 100644 src/kk_ihex.h create mode 100644 src/kk_ihex_read.c create mode 100644 src/kk_ihex_read.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..0fa41a7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,42 @@ +BasedOnStyle: LLVM +ReflowComments: false + +MacroBlockBegin: "^BEGIN_OPERATOR" +MacroBlockEnd: "^END_OPERATOR" + +Language: Cpp +DerivePointerAlignment: true +SortIncludes: Never +PointerAlignment: Left +AlignAfterOpenBracket: AlwaysBreak +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +BinPackArguments: false +BinPackParameters: false +ExperimentalAutoDetectBinPacking: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true +ColumnLimit: 100 +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +PenaltyBreakBeforeFirstCallParameter: 0 +PenaltyReturnTypeOnItsOwnLine: 1000000 +PenaltyBreakAssignment: 1000000 +PenaltyExcessCharacter: 10 +IndentCaseLabels: true +IndentWidth: 4 +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +SpaceAfterTemplateKeyword: false +AccessModifierOffset: -4 +AllowShortBlocksOnASingleLine: Always +IndentPPDirectives: BeforeHash +IndentExternBlock: Indent +Cpp11BracedListStyle: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c8472f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.d +src/fvhex2bin +src/libfvhex2bin.a diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..246c860 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013-2017 Kimmo Kulovesi + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/data/flangers.hex b/data/flangers.hex new file mode 100644 index 0000000..fb58e69 --- /dev/null +++ b/data/flangers.hex @@ -0,0 +1,1025 @@ +:04000000802000114B +:0400040004E00612FC +:0400080000180224B6 +:04000C0000000026CA +:0400100009E30204FA +:0400140000000006E2 +:0400180020130404A9 +:04001C000000024A94 +:040020002013028423 +:0400240000000002D6 +:0400280006000714B3 +:04002C000000073495 +:0400300000000426A2 +:04003400400006E0A2 +:04003800000004467A +:04003C00C0000444B8 +:040040000000046652 +:04004400C0A404440C +:0400480000000406AA +:04004C004000042448 +:040050004000046404 +:04005400400002C6A0 +:04005800000002E6BC +:04005C00000000118F +:04006000000000118B +:040064000000001187 +:040068000000001183 +:04006C00000000117F +:04007000000000117B +:040074000000001177 +:040078000000001173 +:04007C00000000116F +:04008000000000116B +:040084000000001167 +:040088000000001163 +:04008C00000000115F +:04009000000000115B +:040094000000001157 +:040098000000001153 +:04009C00000000114F +:0400A000000000114B +:0400A4000000001147 +:0400A8000000001143 +:0400AC00000000113F +:0400B000000000113B +:0400B4000000001137 +:0400B8000000001133 +:0400BC00000000112F +:0400C000000000112B +:0400C4000000001127 +:0400C8000000001123 +:0400CC00000000111F +:0400D000000000111B +:0400D4000000001117 +:0400D8000000001113 +:0400DC00000000110F +:0400E000000000110B +:0400E4000000001107 +:0400E8000000001103 +:0400EC0000000011FF +:0400F00000000011FB +:0400F40000000011F7 +:0400F80000000011F3 +:0400FC0000000011EF +:0401000000000011EA +:0401040000000011E6 +:0401080000000011E2 +:04010C0000000011DE +:0401100000000011DA +:0401140000000011D6 +:0401180000000011D2 +:04011C0000000011CE +:0401200000000011CA +:0401240000000011C6 +:0401280000000011C2 +:04012C0000000011BE +:0401300000000011BA +:0401340000000011B6 +:0401380000000011B2 +:04013C0000000011AE +:0401400000000011AA +:0401440000000011A6 +:0401480000000011A2 +:04014C00000000119E +:04015000000000119A +:040154000000001196 +:040158000000001192 +:04015C00000000118E +:04016000000000118A +:040164000000001186 +:040168000000001182 +:04016C00000000117E +:04017000000000117A +:040174000000001176 +:040178000000001172 +:04017C00000000116E +:04018000000000116A +:040184000000001166 +:040188000000001162 +:04018C00000000115E +:04019000000000115A +:040194000000001156 +:040198000000001152 +:04019C00000000114E +:0401A000000000114A +:0401A4000000001146 +:0401A8000000001142 +:0401AC00000000113E +:0401B000000000113A +:0401B4000000001136 +:0401B8000000001132 +:0401BC00000000112E +:0401C000000000112A +:0401C4000000001126 +:0401C8000000001122 +:0401CC00000000111E +:0401D000000000111A +:0401D4000000001116 +:0401D8000000001112 +:0401DC00000000110E +:0401E000000000110A +:0401E4000000001106 +:0401E8000000001102 +:0401EC0000000011FE +:0401F00000000011FA +:0401F40000000011F6 +:0401F80000000011F2 +:0401FC0000000011EE +:040200000000272DA6 +:0402040000000446AC +:04020800400002446C +:04020C004000046644 +:040210000000046A7C +:04021400000004865C +:040218008020001131 +:04021C00229004B276 +:0402200000120224A2 +:040224000000006670 +:04022800053C02048B +:04022C000000004688 +:040230004000042462 +:040234000000024A7A +:0402380040000284FC +:04023C0000000002BC +:04024000062004D4BC +:04024400002004F49E +:04024800000004A608 +:04024C00400004A0CA +:04025000000004C6E0 +:04025400C00004C41E +:04025800000004E6B8 +:04025C00400004A4B6 +:04026000400004E472 +:04026400000005068B +:0402680080200011E1 +:04026C0001B00612C5 +:04027000001802244C +:040274000000002660 +:04027800037D0204FC +:04027C000000000678 +:0402800028610404E9 +:040284000000024A2A +:0402880028610504E0 +:04028C0000000982E3 +:0402900006001074E0 +:0402940000001094C2 +:040298000000052637 +:04029C0040001060AE +:0402A000000005460F +:0402A400100005043D +:0402A80014C026A0B8 +:0402AC00C000176314 +:0402B00014C04CA08A +:0402B400C00026C39D +:0402B80014C091E0FD +:0402BC00C0004CC36F +:0402C00014C1054020 +:0402C400C0009203E1 +:0402C8004000056687 +:0402CC00400AD420F0 +:0402D0000000044ADC +:0402D400EB42E340D6 +:0402D80014C10563E5 +:0402DC007F42E36218 +:0402E0004000056471 +:0402E400400611605F +:0402E8000000044AC4 +:0402EC00EB4861007A +:0402F00014C611839C +:0402F4007F486122BC +:0402F8000000058677 +:0402FC00C0000544F5 +:04030000000005A64E +:04030400400005248C +:04030800000005C626 +:04030C00400005A404 +:04031000400005C4E0 +:04031400000005C61A +:040318001013058435 +:04031C000000048A4F +:04032000400005C4D0 +:04032400000005C60A +:04032800400005C4C8 +:04032C00000002C605 +:04033000400005C4C0 +:04033400000002E6DD +:04033800C0A404A4B5 +:04033C000000042693 +:04034000C0A405242C +:0403440000000406AB +:0403480000000011A0 +:04034C00000000119C +:040350000000001198 +:040354000000001194 +:040358000000001190 +:04035C00000000118C +:040360000000001188 +:040364000000001184 +:040368000000001180 +:04036C00000000117C +:040370000000001178 +:040374000000001174 +:040378000000001170 +:04037C00000000116C +:040380000000001168 +:040384000000001164 +:040388000000001160 +:04038C00000000115C +:040390000000001158 +:040394000000001154 +:040398000000001150 +:04039C00000000114C +:0403A0000000001148 +:0403A4000000001144 +:0403A8000000001140 +:0403AC00000000113C +:0403B0000000001138 +:0403B4000000001134 +:0403B8000000001130 +:0403BC00000000112C +:0403C0000000001128 +:0403C4000000001124 +:0403C8000000001120 +:0403CC00000000111C +:0403D0000000001118 +:0403D4000000001114 +:0403D8000000001110 +:0403DC00000000110C +:0403E0000000001108 +:0403E4000000001104 +:0403E8000000001100 +:0403EC0000000011FC +:0403F00000000011F8 +:0403F40000000011F4 +:0403F80000000011F0 +:0403FC0000000011EC +:040400000000272DA4 +:0404040000000446AA +:04040800400002446A +:04040C004000046642 +:040410000000046A7A +:04041400000004865A +:0404180080600011EF +:04041C00000004A632 +:040420000000800D4B +:04042400000004C60A +:04042800001404A414 +:04042C000000020AC0 +:04043000400004C4C0 +:04043400FFEC04C60F +:040438000000020AB4 +:04043C00400004A4D4 +:04044000000004A60E +:04044400400004A4CC +:040448001000400D53 +:04044C00000004E6C2 +:04045000400004E480 +:040454000000022A78 +:040458000000050695 +:04045C0080200011EB +:040460004000001246 +:040464000000000E86 +:0404680040000284CA +:04046C00000000028A +:04047000C240001472 +:04047400FD7105040D +:0404780000000086FA +:04047C000640001422 +:040480000040003404 +:0404840029AF054552 +:04048800C000054863 +:04048C000000052641 +:040490000000000E5A +:040494007FFF000FD7 +:040498000011000D42 +:04049C000000030653 +:0404A0004000000117 +:0404A40000000566E9 +:0404A80040000524E7 +:0404AC0040000564A3 +:0404B00000000586BD +:0404B4008020001193 +:0404B800229004B2D8 +:0404BC000012022404 +:0404C00000000066D2 +:0404C400053C0204ED +:0404C80000000046EA +:0404CC00286104247B +:0404D0000000024ADC +:0404D4002861058412 +:0404D80000020022FC +:0404DC00062204D41C +:0404E000002204F4FE +:0404E400000005A669 +:0404E800400204C00A +:0404EC00000005C641 +:0404F000C00005C47F +:0404F400000005E619 +:0404F8003F5C04C49D +:0404FC000000024AB0 +:04050000C0117FCDDA +:0405040000000606E7 +:04050800400005A406 +:04050C0000000426C1 +:04051000400005A4FE +:04051400400005E4BA +:0405180000000626B3 +:04051C00802000112A +:0405200001B006120E +:040524000018022495 +:0405280000000026A9 +:04052C00037D020445 +:0405300000000006C1 +:0405340032D60404B3 +:040538000000024A73 +:04053C0032D6062489 +:04054000000209A20A +:040544000602107427 +:040548000002109409 +:04054C00000006465F +:0405500040021080D5 +:040554000000066637 +:04055800C000066475 +:04055C00000006860F +:04056000100006245D +:0405640014C226C0D7 +:04056800C002178333 +:04056C0014C24CC0A9 +:04057000C00226E3BC +:0405740014C292001B +:04057800C0024CE38E +:04057C0014C305603F +:04058000C002922300 +:04058400400006A687 +:04058800400CD4400F +:04058C000000044A1D +:04059000EB44E360F5 +:0405940014C3058304 +:040598007F44E38237 +:04059C00400006A471 +:0405A000400811807E +:0405A4000000044A05 +:0405A800EB4A612099 +:0405AC0014C811A3BB +:0405B0007F4A6142DB +:0405B400000006C677 +:0405B800C0A4064491 +:0405BC000000040631 +:0405C00040000644AD +:0405C4000000060A23 +:0405C800000006E643 +:0405CC004000068461 +:0405D0000000060A17 +:0405D400400006E4F9 +:0405D800000006E633 +:0405DC00101306C42E +:0405E0000000048A89 +:0405E400400006E4E9 +:0405E800000006E623 +:0405EC00400006E4E1 +:0405F000000002C63F +:0405F400400006E4D9 +:0405F800000002E617 +:0405FC0000000011EA +:0406000040000204B0 +:040604002666332D06 +:0406080000000446A4 +:04060C0080600011F9 +:04061000000004667C +:040614000000800D55 +:040618000000048654 +:04061C00001404645E +:040620000000044A88 +:04062400400004840A +:04062800FFEC048659 +:04062C000000044A7C +:04063000400004641E +:040634000000046658 +:040638004000046416 +:04063C001000400D5D +:04064000000004A60C +:04064400400004A4CA +:040648000000022A82 +:04064C00000004C6E0 +:0406500080200011F5 +:040654004000001250 +:040658000000000E90 +:04065C00286104E429 +:040660000000024A4A +:040664002861028483 +:04066800000000028C +:04066C00C240001474 +:04067000FD7104C450 +:0406740000000086FC +:040678000640001424 +:04067C000040003406 +:0406800029AF052574 +:04068400C000052885 +:040688000000050663 +:04068C000000000E5C +:040690007FFF000FD9 +:040694000011000D44 +:040698000000030655 +:04069C004000000119 +:0406A000000005460B +:0406A400400004848A +:0406A8002000400DE1 +:0406AC0000000566DF +:0406B00040000504FD +:0406B40040000544B9 +:0406B80000000586B3 +:0406BC008020001189 +:0406C00001B006126D +:0406C40000180224F4 +:0406C8000000002608 +:0406CC00037D0204A4 +:0406D0000000000620 +:0406D40032D6040412 +:0406D8000000024AD2 +:0406DC0032D6058489 +:0406E00000020022F2 +:0406E40006020714EF +:0406E80000020734D1 +:0406EC00000005A65F +:0406F00040020700BD +:0406F400000005C637 +:0406F800C00005C475 +:0406FC00000005E60F +:040700008020001144 +:04070400229004B289 +:0407080000120224B5 +:04070C000000006683 +:04071000053C02049E +:04071400000000469B +:04071800286104242C +:04071C000000024A8D +:0407200028610584C3 +:0407240000020E02BF +:0407280006221294FF +:04072C00002212B4E1 +:0407300000000606B9 +:04073400400212A0CD +:040738000000062691 +:04073C00C0A405A4AC +:0407400000000406AB +:04074400C0000624C7 +:040748000000064661 +:04074C00200005A4E0 +:040750000000066639 +:04075400200005E498 +:0407580040000664F3 +:04075C00000006662D +:04076000200006046B +:040764000000068605 +:040768002000064423 +:04076C0040000684BF +:0407700000000686F9 +:040774003F5C05647D +:040778000000024A31 +:04077C00C0117FCD5C +:04078000000006A6C9 +:04078400E000066427 +:0407880020000684C3 +:04078C000000046AFB +:0407900020000664DB +:04079400000006C695 +:04079800400006C453 +:04079C00000006AAA9 +:0407A000000006E669 +:0407A4004000060407 +:0407A8000000042623 +:0407AC004000050400 +:0407B000000004E65B +:0407B400400006E417 +:0407B800000002C675 +:0407BC00400006E40F +:0407C000000002E64D +:0407C4000000001120 +:0407C800000000111C +:0407CC000000001118 +:0407D0000000001114 +:0407D4000000001110 +:0407D800000000110C +:0407DC000000001108 +:0407E0000000001104 +:0407E4000000001100 +:0407E80000000011FC +:0407EC0000000011F8 +:0407F00000000011F4 +:0407F40000000011F0 +:0407F80000000011EC +:0407FC0000000011E8 +:0408000040000204AE +:040804002666332D04 +:0408080000000446A2 +:04080C0080600011F7 +:04081000000004667A +:040814000000800D53 +:040818000000048652 +:04081C00001404645C +:040820000000044A86 +:040824004000048408 +:04082800FFEC048657 +:04082C000000044A7A +:04083000400004641C +:040834000000046656 +:040838004000046414 +:04083C001000400D5B +:04084000000004A60A +:04084400400004A4C8 +:040848000000022A80 +:04084C00000004C6DE +:0408500080200011F3 +:04085400400000124E +:040858000000000E8E +:04085C0040000284D2 +:040860000000000292 +:04086400C24000147A +:04086800FD7104C456 +:04086C000000008602 +:04087000064000142A +:04087400004000340C +:0408780029AF05059A +:04087C00C0000508AB +:04088000000004E68A +:040884000000000E62 +:040888007FFF000FDF +:04088C000011000D4A +:04089000000003065B +:04089400400000011F +:040898000000052631 +:04089C00400004E430 +:0408A00040000524EB +:0408A4000000054605 +:0408A800802000119B +:0408AC00229004B2E0 +:0408B000001202240C +:0408B40000000066DA +:0408B800053C0204F5 +:0408BC0000000046F2 +:0408C0002861042483 +:0408C4000000024AE4 +:0408C800286105445A +:0408CC000002002204 +:0408D000062204D424 +:0408D400002204F406 +:0408D80000000566B1 +:0408DC00400204C012 +:0408E0000000058689 +:0408E4004000048448 +:0408E8002000400D9F +:0408EC00000005A65D +:0408F000400005645B +:0408F40000000426D6 +:0408F800802000114B +:0408FC0001B006122F +:0409000000180224B5 +:0409040000000026C9 +:04090800037D020465 +:04090C0000000006E1 +:0409100032D60404D3 +:040914000000024A93 +:0409180032D605448A +:04091C00000209A22A +:040920000602107447 +:040924000002109429 +:04092800000005C600 +:04092C0040021080F5 +:04093000000005E6D8 +:04093400C00005E416 +:0409380000000606AF +:04093C00C00005846E +:040940000000062687 +:04094400C0A405C482 +:0409480000000406A1 +:04094C00200005C4BE +:040950000000064657 +:040954002000060475 +:040958004000064411 +:04095C00000006464B +:04096000200005640A +:040964000000066623 +:040968002000062441 +:04096C0040000664DD +:040970000000066617 +:04097400E000064455 +:0409780020000664F1 +:04097C000000046A09 +:040980002000064409 +:0409840000000686E3 +:040988003A3D05A44B +:04098C000000024A1B +:04099000C0117FCD46 +:04099400000006A6B3 +:040998004000068491 +:04099C00000006AAA7 +:0409A000000006C687 +:0409A40040000244C9 +:0409A8001AE14A2DD9 +:0409AC00000006E65B +:0409B0000000072616 +:0409B4001CCC06E46D +:0409B800000007260E +:0409BC003FEF06E41F +:0409C0000AC010ADAC +:0409C4000000030626 +:0409C80040000001EA +:0409CC0040000706DA +:0409D0000000072AF2 +:0409D400200006C435 +:0409D8000002178280 +:0409DC0040000704CC +:0409E0000000070606 +:0409E400400006C405 +:0409E80040000704C0 +:0409EC00400002C6FF +:0409F000000002E61B +:0409F40000000011EE +:0409F80000000011EA +:0409FC0000000011E6 +:040A0000400002446C +:040A04004000044664 +:040A08000000044A9C +:040A0C00000004667C +:040A100080600011F1 +:040A14000000048654 +:040A18000000800D4D +:040A1C00000004A62C +:040A20000014048436 +:040A24000000020AC2 +:040A2800400004A4E2 +:040A2C00FFEC04A631 +:040A30000000020AB6 +:040A340040000484F6 +:040A38000000048630 +:040A3C0040000484EE +:040A40001000400D55 +:040A4400000004C6E4 +:040A4800400004C4A2 +:040A4C000000022A7A +:040A5000000004E6B8 +:040A540080200011ED +:040A58004000001248 +:040A5C000000000E88 +:040A600020130284D9 +:040A6400000000028C +:040A6800C240001474 +:040A6C00FD7104E430 +:040A700000000086FC +:040A74000640001424 +:040A78000040003406 +:040A7C0029AF052574 +:040A8000C000052885 +:040A84000000050663 +:040A88000000000E5C +:040A8C007FFF000FD9 +:040A90000011000D44 +:040A94000000030655 +:040A98004000000119 +:040A9C00000005460B +:040AA0004000050409 +:040AA40040000544C5 +:040AA80000000566DF +:040AAC0040000244C0 +:040AB0002333398D26 +:040AB40000000586B3 +:040AB800201305649E +:040ABC000002002212 +:040AC0000000000E24 +:040AC4007FFF000FA1 +:040AC8000000058A9B +:040ACC0013F3120D01 +:040AD0000000030619 +:040AD40040000001DD +:040AD800000005A66F +:040ADC000000000E08 +:040AE0007FFF000F85 +:040AE4000000058A7F +:040AE80008FA10ED0B +:040AEC0000000306FD +:040AF00040000001C1 +:040AF400000005C633 +:040AF8003F5C04A4B7 +:040AFC000000024AAA +:040B0000C0117FCDD4 +:040B0400000005E602 +:040B08008020001138 +:040B0C00229004B27D +:040B100000120224A9 +:040B14000000006677 +:040B1800053C020492 +:040B1C00000000468F +:040B20002861042420 +:040B24000000024A81 +:040B2800286105A497 +:040B2C00000740621C +:040B3000062744F45C +:040B3400002745143D +:040B380000000606AD +:040B3C004007450029 +:040B40000000062685 +:040B4400C0000624C3 +:040B4800000006465D +:040B4C00400006045B +:040B50004000064417 +:040B54000000066631 +:040B580080200011E8 +:040B5C0001B00612CC +:040B60000018022453 +:040B64000000002667 +:040B6800037D020403 +:040B6C00000000067F +:040B700032D6040471 +:040B74000000024A31 +:040B780032D605A4C8 +:040B7C00000749E243 +:040B80000607509480 +:040B8400000750B462 +:040B880000000686DD +:040B8C00400750C00E +:040B9000000006A6B5 +:040B9400C0A406846F +:040B9800000004064F +:040B9C00C00006A4EB +:040BA000000006C685 +:040BA4004000068483 +:040BA800000005EA5A +:040BAC00000006E659 +:040BB000400006C437 +:040BB400000005EA4E +:040BB800400006E40F +:040BBC00000006E649 +:040BC0004000066487 +:040BC4000000070620 +:040BC8004000028463 +:040BCC0040000704DA +:040BD0000000070614 +:040BD400400006E4F3 +:040BD80040000704CE +:040BDC000000070608 +:040BE000400005C408 +:040BE40040000704C2 +:040BE80000000706FC +:040BEC0040000704BA +:040BF00040000704B6 +:040BF400400002C6F5 +:040BF800000002E611 +:040BFC0040000604AB +:040C0000802000113F +:040C04004523001272 +:040C0800148C020442 +:040C0C00000000865E +:040C1000C2400014CA +:040C14004000042672 +:040C18007FEFC00D9D +:040C1C0000000009CB +:040C20000000044686 +:040C24004000044444 +:040C28000000024A7C +:040C2C00000004665A +:040C30004000046418 +:040C34000000048632 +:040C38008020001107 +:040C3C006000001242 +:040C40000000000EA2 +:040C4400390A040461 +:040C48000000022A7C +:040C4C0040000284DE +:040C5000000000029E +:040C5400C260001466 +:040C5800F47B0484A1 +:040C5C00000000C6CE +:040C60000660001416 +:040C640000600034F8 +:040C6800308D04C502 +:040C6C00C00004C8F8 +:040C7000000004A6D6 +:040C7400D8F604A406 +:040C7800000004066E +:040C7C0040000284AE +:040C8000400004A488 +:040C8400400002C664 +:040C8800000002E680 +:040C8C000000001153 +:040C9000000000114F +:040C9400000000114B +:040C98000000001147 +:040C9C000000001143 +:040CA000000000113F +:040CA400000000113B +:040CA8000000001137 +:040CAC000000001133 +:040CB000000000112F +:040CB400000000112B +:040CB8000000001127 +:040CBC000000001123 +:040CC000000000111F +:040CC400000000111B +:040CC8000000001117 +:040CCC000000001113 +:040CD000000000110F +:040CD400000000110B +:040CD8000000001107 +:040CDC000000001103 +:040CE00000000011FF +:040CE40000000011FB +:040CE80000000011F7 +:040CEC0000000011F3 +:040CF00000000011EF +:040CF40000000011EB +:040CF80000000011E7 +:040CFC0000000011E3 +:040D000000000011DE +:040D040000000011DA +:040D080000000011D6 +:040D0C0000000011D2 +:040D100000000011CE +:040D140000000011CA +:040D180000000011C6 +:040D1C0000000011C2 +:040D200000000011BE +:040D240000000011BA +:040D280000000011B6 +:040D2C0000000011B2 +:040D300000000011AE +:040D340000000011AA +:040D380000000011A6 +:040D3C0000000011A2 +:040D4000000000119E +:040D4400000000119A +:040D48000000001196 +:040D4C000000001192 +:040D5000000000118E +:040D5400000000118A +:040D58000000001186 +:040D5C000000001182 +:040D6000000000117E +:040D6400000000117A +:040D68000000001176 +:040D6C000000001172 +:040D7000000000116E +:040D7400000000116A +:040D78000000001166 +:040D7C000000001162 +:040D8000000000115E +:040D8400000000115A +:040D88000000001156 +:040D8C000000001152 +:040D9000000000114E +:040D9400000000114A +:040D98000000001146 +:040D9C000000001142 +:040DA000000000113E +:040DA400000000113A +:040DA8000000001136 +:040DAC000000001132 +:040DB000000000112E +:040DB400000000112A +:040DB8000000001126 +:040DBC000000001122 +:040DC000000000111E +:040DC400000000111A +:040DC8000000001116 +:040DCC000000001112 +:040DD000000000110E +:040DD400000000110A +:040DD8000000001106 +:040DDC000000001102 +:040DE00000000011FE +:040DE40000000011FA +:040DE80000000011F6 +:040DEC0000000011F2 +:040DF00000000011EE +:040DF40000000011EA +:040DF80000000011E6 +:040DFC0000000011E2 +:040E0000802000113D +:040E04000700017270 +:040E080000050224BB +:040E0C0000000026BC +:040E10000E200204AA +:040E140000000006D4 +:040E1800390A04048B +:040E1C000000024A86 +:040E20002013028415 +:040E240000000002C8 +:040E2800060001942B +:040E2C00000001B40D +:040E30000000042694 +:040E34004000016019 +:040E3800000004466C +:040E3C00C0A4044406 +:040E400000000406A4 +:040E44004000042442 +:040E480040000284E0 +:040E4C00400002C69A +:040E5000000002E6B6 +:040E54000000001189 +:040E58000000001185 +:040E5C000000001181 +:040E6000000000117D +:040E64000000001179 +:040E68000000001175 +:040E6C000000001171 +:040E7000000000116D +:040E74000000001169 +:040E78000000001165 +:040E7C000000001161 +:040E8000000000115D +:040E84000000001159 +:040E88000000001155 +:040E8C000000001151 +:040E9000000000114D +:040E94000000001149 +:040E98000000001145 +:040E9C000000001141 +:040EA000000000113D +:040EA4000000001139 +:040EA8000000001135 +:040EAC000000001131 +:040EB000000000112D +:040EB4000000001129 +:040EB8000000001125 +:040EBC000000001121 +:040EC000000000111D +:040EC4000000001119 +:040EC8000000001115 +:040ECC000000001111 +:040ED000000000110D +:040ED4000000001109 +:040ED8000000001105 +:040EDC000000001101 +:040EE00000000011FD +:040EE40000000011F9 +:040EE80000000011F5 +:040EEC0000000011F1 +:040EF00000000011ED +:040EF40000000011E9 +:040EF80000000011E5 +:040EFC0000000011E1 +:040F000000000011DC +:040F040000000011D8 +:040F080000000011D4 +:040F0C0000000011D0 +:040F100000000011CC +:040F140000000011C8 +:040F180000000011C4 +:040F1C0000000011C0 +:040F200000000011BC +:040F240000000011B8 +:040F280000000011B4 +:040F2C0000000011B0 +:040F300000000011AC +:040F340000000011A8 +:040F380000000011A4 +:040F3C0000000011A0 +:040F4000000000119C +:040F44000000001198 +:040F48000000001194 +:040F4C000000001190 +:040F5000000000118C +:040F54000000001188 +:040F58000000001184 +:040F5C000000001180 +:040F6000000000117C +:040F64000000001178 +:040F68000000001174 +:040F6C000000001170 +:040F7000000000116C +:040F74000000001168 +:040F78000000001164 +:040F7C000000001160 +:040F8000000000115C +:040F84000000001158 +:040F88000000001154 +:040F8C000000001150 +:040F9000000000114C +:040F94000000001148 +:040F98000000001144 +:040F9C000000001140 +:040FA000000000113C +:040FA4000000001138 +:040FA8000000001134 +:040FAC000000001130 +:040FB000000000112C +:040FB4000000001128 +:040FB8000000001124 +:040FBC000000001120 +:040FC000000000111C +:040FC4000000001118 +:040FC8000000001114 +:040FCC000000001110 +:040FD000000000110C +:040FD4000000001108 +:040FD8000000001104 +:040FDC000000001100 +:040FE00000000011FC +:040FE40000000011F8 +:040FE80000000011F4 +:040FEC0000000011F0 +:040FF00000000011EC +:040FF40000000011E8 +:040FF80000000011E4 +:040FFC0000000011E0 +:00000001FF diff --git a/data/flangers.hex.bin.target b/data/flangers.hex.bin.target new file mode 100644 index 0000000000000000000000000000000000000000..dc0c6e434149e7b813c1fa397d09dfee51a32a6f GIT binary patch literal 4096 zcmeH~&x;&I6vy9Is%x@~i8Hee5%Dlg#?BfDNRmrLNfBm;IP4*RKn}CX(1+X%-b8ju znmz;r8ukweI?O>3Mf?NG$=Kwew-7w8?$C!s$-&@3koc+T-psCSNDveQITYVluU`Fn z-*3I1S#L;9Z<@NiqFN#n&2K3Un#Q6ARkyLI68g$WB^0Tg6w#3tvk7*b=r$O;!4!=Z z-J*%8SvHn`>Q(eTt+f!W-r(1B_B|d>$ zWg7a9H1tE}3>mu#W=`}N%;^tk6Oq99_2#~s>1^MJh0c~%3!N>k23lnPijnI3BGnD% zL{_Rjuv3*lhc3G5?t$@+3(0#J$WaU=)ZD5_;*k>h(?ZTY~`*!c2*|PXAuASMs zfWL1|jdk#!U6nAaU0pl7+GO3-Nzev|#I(Q+9MHzzt}X@%bFOXo3sgRaah0R_0ppPy z__^B1bF1|y@Za;g)kBf>17Iehzpq-baQo;N`i1RtFvK^giuG|h_JpycGNKrs_SZNKZqD(B^Yr2$RllnFM5(@kKfhW&pm$E zv_#E+Y80APUbCiSRdpSVotQqDR>ic!QRJLDbTu5UfYDYsx*<-jY=yUio>MmtTQNiX z(jCkG-TUpW9{#Iq?X4^L2X=pr_3(FB8{zHRXKUTnGpw7rfobD6#DHdjmSZR01}DB> zT{L52&~VW&P-P|Nf@a}GNAZbc#C6sS&f}8v6wdp8Z!0>1^R%?RFUHp|IUiyV$OoM3 z%;(IOoWsY&=V@tGCG4d}Q|^7 zK6^gH+eTx%-gb}`Z#&32_XJ)Hn1B&F7_+8nOf}_oU^Lvc8N>Gbc}m9G1nI?!$@O%C<^4Na$r!H^Q}*M&S`O315zpK{*W4wFlT|70X1M)+W2&eFDYw4 zhCOD?*MNLy4cPwuI4U$SVeiynmv#Rc-hQC1z=Z^{KkMNWr>t1I}B%!C-pkr__OgRO|(Fr2SBiEQcb-*vc|nn8?8` z*s(L-W1oYk)F#$@_h(Z%w;`2tzOJOUa?XK6YI{N+jidh4&+JqS!9DC8d(7SLfs?Y| zFF01o4!$QdI~dPwuYs8kSVQ}BE+3Y9_>t0FCLO_z<$bI@aO6_vIY)qatzEj>B;=5_s@6MdVx!ykY5x!1cEto?)d*Vx4};_bn3rDb3L%L`+uM3@&%92n{NLC Dv1r~2 literal 0 HcmV?d00001 diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..feab14a --- /dev/null +++ b/src/Makefile @@ -0,0 +1,45 @@ +TARGET_EXE=fvhex2bin +TARGET_LIB=lib$(TARGET_EXE).a + +# default config +#SYS_PREFIX?=/opt/local + +# System +#SYS_INC_PATH?=$(SYS_PREFIX)/include +#SYS_LIB_PATH?=$(SYS_PREFIX)/lib + +CFLAGS+=-std=c99 -MMD -MP -Wno-format-extra-args -Wno-deprecated-declarations -fvisibility=hidden +#CFLAGS+=-isystem$(SYS_INC_PATH) +#LDFLAGS+=-DMACOSX_DEPLOYMENT_TARGET=11.00 -framework Foundation -framework IOKit -framework Security +#STATIC_LINK_LIBS=$(SYS_LIB_PATH)/libusb-1.0.a + +SRC_ALL=$(wildcard *.c) +SRC_EXE=$(TARGET_EXE).c +SRC_LIB=$(filter-out $(SRC_EXE), $(SRC_ALL)) + +#OBJ_EXE=$(subst .c,.o,$(SRC_EXE)) +OBJ_LIB=$(subst .c,.o,$(SRC_LIB)) + +DEPENDS=$(subst .c,.d,$(SRC_ALL)) + +ifneq ($(MAKECMDGOALS),clean) + -include $(DEPENDS) +endif + +.PHONY: all clean uninstall install +.DEFAULT_GOAL := all + +all: $(TARGET_EXE) + +lib: $(TARGET_LIB) + +$(TARGET_EXE): $(SRC_EXE) $(TARGET_LIB) + $(CXX) $(LDFLAGS) $(TARGET_LIB) $(STATIC_LINK_LIBS) $(SRC_EXE) -o $@ + +$(TARGET_LIB): $(OBJ_LIB) + $(AR) -cr $@ $^ + +clean: + rm $(OBJ_LIB) $(TARGET_LIB) $(TARGET_EXE) $(DEPENDS) + + diff --git a/src/fvhex2bin.c b/src/fvhex2bin.c new file mode 100644 index 0000000..ac263cf --- /dev/null +++ b/src/fvhex2bin.c @@ -0,0 +1,194 @@ +/* + * ihex2bin.c: Read Intel HEX format, write binary data. + * + * By default reads from stdin and writes to stdout. The command-line + * options `-i` and `-o` can be used to specify the input and output + * file, respectively. Specifying an output file allows sparse writes. + * + * NOTE: Many Intel HEX files produced by compilers/etc have data + * beginning at an address greater than zero, potentially causing very + * unnecessarily large files to be created. The command-line option + * `-a` can be used to specify the start address of the output file, + * i.e., the value will be subtracted from the IHEX addresses (the + * result must not be negative). + * + * Alternatively, the command-line option `-A` sets the address offset + * to the first address that would be written (i.e., first byte of + * data written will be at address 0). + * + * Copyright (c) 2013-2019 Kimmo Kulovesi, https://arkku.com + * Provided with absolutely no warranty, use at your own risk only. + * Distribute freely, mark modified copies as such. + */ + +#include "kk_ihex_read.h" +#include +#include +#include +#include +#include + +#define AUTODETECT_ADDRESS (~0UL) + +static FILE *outfile; +static unsigned long line_number = 1L; +static unsigned long file_position = 0L; +static unsigned long address_offset = 0UL; +static bool debug_enabled = 0; + +int main(int argc, char *argv[]) +{ + struct ihex_state ihex; + FILE *infile = stdin; + ihex_count_t count; + char buf[256]; + + outfile = stdout; + + while (--argc) { + char *arg = *(++argv); + if (arg[0] == '-' && arg[1] && arg[2] == '\0') { + switch (arg[1]) { + case 'a': + if (--argc == 0) { + goto invalid_argument; + } + ++argv; + errno = 0; + address_offset = strtoul(*argv, &arg, 0); + if (errno || arg == *argv) { + errno = errno ? errno : EINVAL; + goto argument_error; + } + break; + case 'A': + address_offset = AUTODETECT_ADDRESS; + break; + case 'i': + if (--argc == 0) { + goto invalid_argument; + } + ++argv; + if (!(infile = fopen(*argv, "r"))) { + goto argument_error; + } + break; + case 'o': + if (--argc == 0) { + goto invalid_argument; + } + ++argv; + if (!(outfile = fopen(*argv, "wb"))) { + goto argument_error; + } + break; + case 'v': + debug_enabled = 1; + break; + case 'h': + case '?': + arg = NULL; + goto usage; + default: + goto invalid_argument; + } + continue; + } + invalid_argument: + (void)fprintf(stderr, "Invalid argument: %s\n", arg); + usage: + (void)fprintf(stderr, "kk_ihex " KK_IHEX_VERSION " - Copyright (c) 2013-2015 Kimmo Kulovesi\n"); + (void)fprintf( + stderr, + "Usage: ihex2bin ([-a ]|[-A])" + " [-o ] [-i ] [-v]\n"); + return arg ? EXIT_FAILURE : EXIT_SUCCESS; + argument_error: + perror(*argv); + return EXIT_FAILURE; + } + + ihex_read_at_address( + &ihex, + (address_offset != AUTODETECT_ADDRESS) ? (ihex_address_t)address_offset : 0); + while (fgets(buf, sizeof(buf), infile)) { + count = (ihex_count_t)strlen(buf); + ihex_read_bytes(&ihex, buf, count); + line_number += (count && buf[count - 1] == '\n'); + } + ihex_end_read(&ihex); + + if (infile != stdin) { + (void)fclose(infile); + } + + return EXIT_SUCCESS; +} + +ihex_bool_t ihex_data_read(struct ihex_state *ihex, ihex_record_type_t type, ihex_bool_t error) +{ + if (error) { + (void)fprintf(stderr, "Checksum error on line %lu\n", line_number); + exit(EXIT_FAILURE); + } + if ((error = (ihex->length < ihex->line_length))) { + (void)fprintf(stderr, "Line length error on line %lu\n", line_number); + exit(EXIT_FAILURE); + } + if (!outfile) { + (void)fprintf(stderr, "Excess data after end of file record\n"); + exit(EXIT_FAILURE); + } + if (type == IHEX_DATA_RECORD) { + unsigned long address = (unsigned long)IHEX_LINEAR_ADDRESS(ihex); + if (address < address_offset) { + if (address_offset == AUTODETECT_ADDRESS) { + // autodetect initial address + address_offset = address; + if (debug_enabled) { + (void)fprintf(stderr, "Address offset: 0x%lx\n", address_offset); + } + } else { + (void)fprintf(stderr, "Address underflow on line %lu\n", line_number); + exit(EXIT_FAILURE); + } + } + address -= address_offset; + if (address != file_position) { + if (debug_enabled) { + (void)fprintf( + stderr, + "Seeking from 0x%lx to 0x%lx on line %lu\n", + file_position, + address, + line_number); + } + if (outfile == stdout || fseek(outfile, (long)address, SEEK_SET)) { + if (file_position < address) { + // "seek" forward in stdout by writing NUL bytes + do { + (void)fputc('\0', outfile); + } while (++file_position < address); + } else { + perror("fseek"); + exit(EXIT_FAILURE); + } + } + file_position = address; + } + if (!fwrite(ihex->data, ihex->length, 1, outfile)) { + perror("fwrite"); + exit(EXIT_FAILURE); + } + file_position += ihex->length; + } else if (type == IHEX_END_OF_FILE_RECORD) { + if (debug_enabled) { + (void)fprintf(stderr, "%lu bytes written\n", file_position); + } + if (outfile != stdout) { + (void)fclose(outfile); + } + outfile = NULL; + } + return true; +} diff --git a/src/kk_ihex.h b/src/kk_ihex.h new file mode 100644 index 0000000..ad744fe --- /dev/null +++ b/src/kk_ihex.h @@ -0,0 +1,191 @@ +/* + * kk_ihex.h: A simple library for reading and writing the Intel HEX + * or IHEX format. Intended mainly for embedded systems, and thus + * somewhat optimised for size at the expense of error handling and + * generality. + * + * USAGE + * ----- + * + * The library has been split into read and write parts, which use a + * common data structure (`struct ihex_state`), but each can be used + * independently. Include the header `kk_ihex_read.h` for reading, and/or + * the header `kk_ihex_write.h` for writing (and link with their respective + * object files). Both can be used simultaneously - this header defines + * the shared data structures and definitions. + * + * + * READING INTEL HEX DATA + * ---------------------- + * + * To read data in the Intel HEX format, you must perform the actual reading + * of bytes using other means (e.g., stdio). The bytes read must then be + * passed to `ihex_read_byte` and/or `ihex_read_bytes`. The reading functions + * will then call `ihex_data_read`, at which stage the `struct ihex_state` + * structure will contain the data along with its address. See the header + * `kk_ihex_read.h` for details and example implementation of `ihex_data_read`. + * + * The sequence to read data in IHEX format is: + * struct ihex_state ihex; + * ihex_begin_read(&ihex); + * ihex_read_bytes(&ihex, my_input_bytes, length_of_my_input_bytes); + * ihex_end_read(&ihex); + * + * + * WRITING BINARY DATA AS INTEL HEX + * -------------------------------- + * + * In order to write out data, the `ihex_write_at_address` or + * `ihex_write_at_segment` functions are used to set the data location, + * and then the binary bytes are written with `ihex_write_byte` and/or + * `ihex_write_bytes`. The writing functions will then call the function + * `ihex_flush_buffer` whenever the internal write buffer needs to be + * cleared - it is up to the caller to provide an implementation of + * `ihex_flush_buffer` to do the actual writing. See the header + * `kk_ihex_write.h` for details and an example implementation. + * + * See the declaration further down for an example implementation. + * + * The sequence to write data in IHEX format is: + * struct ihex_state ihex; + * ihex_init(&ihex); + * ihex_write_at_address(&ihex, 0); + * ihex_write_bytes(&ihex, my_data, length_of_my_data); + * ihex_end_write(&ihex); + * + * For outputs larger than 64KiB, 32-bit linear addresses are output. Normally + * the initial linear extended address record of zero is NOT written - it can + * be forced by setting `ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW` before + * writing the first byte. + * + * Gaps in the data may be created by calling `ihex_write_at_address` with the + * new starting address without calling `ihex_end_write` in between. + * + * + * The same `struct ihex_state` may be used either for reading or writing, + * but NOT both at the same time. Furthermore, a global output buffer is + * used for writing, i.e., multiple threads must not write simultaneously + * (but multiple writes may be interleaved). + * + * + * CONSERVING MEMORY + * ----------------- + * + * For memory-critical use, you can save additional memory by defining + * `IHEX_LINE_MAX_LENGTH` as something less than 255. Note, however, that + * this limit affects both reading and writing, so the resulting library + * will be unable to read lines with more than this number of data bytes. + * That said, I haven't encountered any IHEX files with more than 32 + * data bytes per line. For write only there is no reason to define the + * maximum as greater than the line length you'll actually be writing, + * e.g., 32 or 16. + * + * If the write functionality is only occasionally used, you can provide + * your own buffer for the duration by defining `IHEX_EXTERNAL_WRITE_BUFFER` + * and providing a `char *ihex_write_buffer` which points to valid storage + * for at least `IHEX_WRITE_BUFFER_LENGTH` characters from before the first + * call to any IHEX write function to until after the last. + * + * If you are doing both reading and writing, you can define the maximum + * output length separately as `IHEX_MAX_OUTPUT_LINE_LENGTH` - this will + * decrease the write buffer size, but `struct ihex_state` will still + * use the larger `IHEX_LINE_MAX_LENGTH` for its data storage. + * + * You can also save a few additional bytes by disabling support for + * segmented addresses, by defining `IHEX_DISABLE_SEGMENTS`. Both the + * read and write modules need to be build with the same option, as the + * resulting data structures will not be compatible otherwise. To be honest, + * this is a fairly pointless optimisation. + * + * + * Copyright (c) 2013-2019 Kimmo Kulovesi, https://arkku.com/ + * Provided with absolutely no warranty, use at your own risk only. + * Use and distribute freely, mark modified copies as such. + */ + +#ifndef KK_IHEX_H +#define KK_IHEX_H + +#define KK_IHEX_VERSION "2019-08-07" + +#include + +#ifdef IHEX_USE_STDBOOL +#include +typedef bool ihex_bool_t; +#else +typedef uint_fast8_t ihex_bool_t; +#endif + +typedef uint_least32_t ihex_address_t; +typedef uint_least16_t ihex_segment_t; +typedef int ihex_count_t; + +// Maximum number of data bytes per line (applies to both reading and +// writing!); specify 255 to support reading all possible lengths. Less +// can be used to limit memory footprint on embedded systems, e.g., +// most programs with IHEX output use 32. +#ifndef IHEX_LINE_MAX_LENGTH +#define IHEX_LINE_MAX_LENGTH 255 +#endif + +enum ihex_flags { + IHEX_FLAG_ADDRESS_OVERFLOW = 0x80 // 16-bit address overflow +}; +typedef uint8_t ihex_flags_t; + +typedef struct ihex_state { + ihex_address_t address; +#ifndef IHEX_DISABLE_SEGMENTS + ihex_segment_t segment; +#endif + ihex_flags_t flags; + uint8_t line_length; + uint8_t length; + uint8_t data[IHEX_LINE_MAX_LENGTH + 1]; +} kk_ihex_t; + +enum ihex_record_type { + IHEX_DATA_RECORD, + IHEX_END_OF_FILE_RECORD, + IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD, + IHEX_START_SEGMENT_ADDRESS_RECORD, + IHEX_EXTENDED_LINEAR_ADDRESS_RECORD, + IHEX_START_LINEAR_ADDRESS_RECORD +}; +typedef uint8_t ihex_record_type_t; + +#ifndef IHEX_DISABLE_SEGMENTS + +// Resolve segmented address (if any). It is the author's recommendation that +// segmented addressing not be used (and indeed the write function of this +// library uses linear 32-bit addressing unless manually overridden). +// +#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address + (((ihex_address_t)((ihex)->segment)) << 4)) +// +// Note that segmented addressing with the above macro is not strictly adherent +// to the IHEX specification, which mandates that the lowest 16 bits of the +// address and the index of the data byte must be added modulo 64K (i.e., +// at 16 bits precision with wraparound) and the segment address only added +// afterwards. +// +// To implement fully correct segmented addressing, compute the address +// of _each byte_ with its index in `data` as follows: +// +#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((((ihex)->address + (byte_index)) & 0xFFFFU) + (((ihex_address_t)((ihex)->segment)) << 4)) + +#else // IHEX_DISABLE_SEGMENTS: + +#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address) +#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((ihex)->address + (byte_index)) + +#endif + +// The newline string (appended to every output line, e.g., "\r\n") +#ifndef IHEX_NEWLINE_STRING +#define IHEX_NEWLINE_STRING "\n" +#endif + +// See kk_ihex_read.h and kk_ihex_write.h for function declarations! + +#endif // !KK_IHEX_H diff --git a/src/kk_ihex_read.c b/src/kk_ihex_read.c new file mode 100644 index 0000000..bea44be --- /dev/null +++ b/src/kk_ihex_read.c @@ -0,0 +1,181 @@ +/* + * kk_ihex_read.c: A simple library for reading the Intel HEX (IHEX) format. + * + * See the header `kk_ihex.h` for instructions. + * + * Copyright (c) 2013-2019 Kimmo Kulovesi, https://arkku.com/ + * Provided with absolutely no warranty, use at your own risk only. + * Use and distribute freely, mark modified copies as such. + */ + +#include "kk_ihex_read.h" + +#define IHEX_START ':' + +#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U) + +enum ihex_read_state { + READ_WAIT_FOR_START = 0, + READ_COUNT_HIGH = 1, + READ_COUNT_LOW, + READ_ADDRESS_MSB_HIGH, + READ_ADDRESS_MSB_LOW, + READ_ADDRESS_LSB_HIGH, + READ_ADDRESS_LSB_LOW, + READ_RECORD_TYPE_HIGH, + READ_RECORD_TYPE_LOW, + READ_DATA_HIGH, + READ_DATA_LOW +}; + +#define IHEX_READ_RECORD_TYPE_MASK 0x07 +#define IHEX_READ_STATE_MASK 0x78 +#define IHEX_READ_STATE_OFFSET 3 + +void +ihex_begin_read (struct ihex_state * const ihex) { + ihex->address = 0; +#ifndef IHEX_DISABLE_SEGMENTS + ihex->segment = 0; +#endif + ihex->flags = 0; + ihex->line_length = 0; + ihex->length = 0; +} + +void +ihex_read_at_address (struct ihex_state * const ihex, ihex_address_t address) { + ihex_begin_read(ihex); + ihex->address = address; +} + +#ifndef IHEX_DISABLE_SEGMENTS +void +ihex_read_at_segment (struct ihex_state * const ihex, ihex_segment_t segment) { + ihex_begin_read(ihex); + ihex->segment = segment; +} +#endif + +void +ihex_end_read (struct ihex_state * const ihex) { + uint_fast8_t type = ihex->flags & IHEX_READ_RECORD_TYPE_MASK; + uint_fast8_t sum; + if ((sum = ihex->length) == 0 && type == IHEX_DATA_RECORD) { + return; + } + { + // compute and validate checksum + const uint8_t * const eptr = ihex->data + sum; + const uint8_t *r = ihex->data; + sum += type + (ihex->address & 0xFFU) + ((ihex->address >> 8) & 0xFFU); + while (r != eptr) { + sum += *r++; + } + sum = (~sum + 1U) ^ *eptr; // *eptr is the received checksum + } + if (ihex_data_read(ihex, type, (uint8_t) sum)) { + if (type == IHEX_EXTENDED_LINEAR_ADDRESS_RECORD) { + ihex->address &= 0xFFFFU; + ihex->address |= (((ihex_address_t) ihex->data[0]) << 24) | + (((ihex_address_t) ihex->data[1]) << 16); +#ifndef IHEX_DISABLE_SEGMENTS + } else if (type == IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD) { + ihex->segment = (ihex_segment_t) ((ihex->data[0] << 8) | ihex->data[1]); +#endif + } + } + ihex->length = 0; + ihex->flags = 0; +} + +void +ihex_read_byte (struct ihex_state * const ihex, const char byte) { + uint_fast8_t b = (uint_fast8_t) byte; + uint_fast8_t len = ihex->length; + uint_fast8_t state = (ihex->flags & IHEX_READ_STATE_MASK); + ihex->flags ^= state; // turn off the old state + state >>= IHEX_READ_STATE_OFFSET; + + if (b >= '0' && b <= '9') { + b -= '0'; + } else if (b >= 'A' && b <= 'F') { + b -= 'A' - 10; + } else if (b >= 'a' && b <= 'f') { + b -= 'a' - 10; + } else if (b == IHEX_START) { + // sync to a new record at any state + state = READ_COUNT_HIGH; + goto end_read; + } else { + // ignore unknown characters (e.g., extra whitespace) + goto save_read_state; + } + + if (!(++state & 1)) { + // high nybble, store temporarily at end of data: + b <<= 4; + ihex->data[len] = b; + } else { + // low nybble, combine with stored high nybble: + b = (ihex->data[len] |= b); + // We already know the lowest bit of `state`, dropping it may produce + // smaller code, hence the `>> 1` in switch and its cases. + switch (state >> 1) { + default: + // remain in initial state while waiting for : + return; + case (READ_COUNT_LOW >> 1): + // data length + ihex->line_length = b; +#if IHEX_LINE_MAX_LENGTH < 255 + if (b > IHEX_LINE_MAX_LENGTH) { + ihex_end_read(ihex); + return; + } +#endif + break; + case (READ_ADDRESS_MSB_LOW >> 1): + // high byte of 16-bit address + ihex->address &= ADDRESS_HIGH_MASK; // clear the 16-bit address + ihex->address |= ((ihex_address_t) b) << 8U; + break; + case (READ_ADDRESS_LSB_LOW >> 1): + // low byte of 16-bit address + ihex->address |= (ihex_address_t) b; + break; + case (READ_RECORD_TYPE_LOW >> 1): + // record type + if (b & ~IHEX_READ_RECORD_TYPE_MASK) { + // skip unknown record types silently + return; + } + ihex->flags = (ihex->flags & ~IHEX_READ_RECORD_TYPE_MASK) | b; + break; + case (READ_DATA_LOW >> 1): + if (len < ihex->line_length) { + // data byte + ihex->length = len + 1; + state = READ_DATA_HIGH; + goto save_read_state; + } + // end of line (last "data" byte is checksum) + state = READ_WAIT_FOR_START; + end_read: + ihex_end_read(ihex); + } + } +save_read_state: + ihex->flags |= state << IHEX_READ_STATE_OFFSET; +} + +void +ihex_read_bytes (struct ihex_state * restrict ihex, + const char * restrict data, + ihex_count_t count) { + while (count > 0) { + ihex_read_byte(ihex, *data++); + --count; + } +} + diff --git a/src/kk_ihex_read.h b/src/kk_ihex_read.h new file mode 100644 index 0000000..1b776fd --- /dev/null +++ b/src/kk_ihex_read.h @@ -0,0 +1,117 @@ +/* + * kk_ihex_read.h: A simple library for reading Intel HEX data. See + * the accompanying kk_ihex_write.h for IHEX write support. + * + * + * READING INTEL HEX DATA + * ---------------------- + * + * To read data in the Intel HEX format, you must perform the actual reading + * of bytes using other means (e.g., stdio). The bytes read must then be + * passed to `ihex_read_byte` and/or `ihex_read_bytes`. The reading functions + * will then call `ihex_data_read`, at which stage the `struct ihex_state` + * structure will contain the data along with its address. See below for + * details and example implementation of `ihex_data_read`. + * + * The sequence to read data in IHEX format is: + * struct ihex_state ihex; + * ihex_begin_read(&ihex); + * ihex_read_bytes(&ihex, my_input_bytes, length_of_my_input_bytes); + * ihex_end_read(&ihex); + * + * + * CONSERVING MEMORY + * ----------------- + * + * For memory-critical use, you can save additional memory by defining + * `IHEX_LINE_MAX_LENGTH` as something less than 255. Note, however, that + * this limit affects both reading and writing, so the resulting library + * will be unable to read lines with more than this number of data bytes. + * That said, I haven't encountered any IHEX files with more than 32 + * data bytes per line. + * + * + * Copyright (c) 2013-2019 Kimmo Kulovesi, https://arkku.com/ + * Provided with absolutely no warranty, use at your own risk only. + * Use and distribute freely, mark modified copies as such. + */ + +#ifndef KK_IHEX_READ_H +#define KK_IHEX_READ_H + +#ifdef __cplusplus +#ifndef restrict +#define restrict +#endif +extern "C" { +#endif + +#include "kk_ihex.h" + +// Begin reading at address 0 +void ihex_begin_read(struct ihex_state *ihex); + +// Begin reading at `address` (the lowest 16 bits of which will be ignored); +// this is required only if the high bytes of the 32-bit starting address +// are not specified in the input data and they are non-zero +void ihex_read_at_address(struct ihex_state *ihex, + ihex_address_t address); + +// Read a single character +void ihex_read_byte(struct ihex_state *ihex, char chr); + +// Read `count` bytes from `data` +void ihex_read_bytes(struct ihex_state * restrict ihex, + const char * restrict data, + ihex_count_t count); + +// End reading (may call `ihex_data_read` if there is data waiting) +void ihex_end_read(struct ihex_state *ihex); + +// Called when a complete line has been read, the record type of which is +// passed as `type`. The `ihex` structure will have its fields `data`, +// `line_length`, `address`, and `segment` set appropriately. In case +// of reading an `IHEX_EXTENDED_LINEAR_ADDRESS_RECORD` or an +// `IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD` the record's data is not +// yet parsed - it will be parsed into the `address` or `segment` field +// only if `ihex_data_read` returns `true`. This allows manual handling +// of extended addresses by parsing the `ihex->data` bytes. +// +// Possible error cases include checksum mismatch (which is indicated +// as an argument), and excessive line length (in case this has been +// compiled with `IHEX_LINE_MAX_LENGTH` less than 255) which is indicated +// by `line_length` greater than `length`. Unknown record types and +// other erroneous data is usually silently ignored by this minimalistic +// parser. (It is recommended to compute a hash over the complete data +// once received and verify that against the source.) +// +// Example implementation: +// +// ihex_bool_t ihex_data_read(struct ihex_state *ihex, +// ihex_record_type_t type, +// ihex_bool_t error) { +// error = error || (ihex->length < ihex->line_length); +// if (type == IHEX_DATA_RECORD && !error) { +// (void) fseek(outfile, IHEX_LINEAR_ADDRESS(ihex), SEEK_SET); +// (void) fwrite(ihex->data, 1, ihex->length, outfile); +// } else if (type == IHEX_END_OF_FILE_RECORD) { +// (void) fclose(outfile); +// } +// return !error; +// } +// +extern ihex_bool_t ihex_data_read(struct ihex_state *ihex, + ihex_record_type_t type, + ihex_bool_t checksum_mismatch); + +// Begin reading at `segment`; this is required only if the initial segment +// is not specified in the input data and it is non-zero. +// +#ifndef IHEX_DISABLE_SEGMENTS +void ihex_read_at_segment(struct ihex_state *ihex, ihex_segment_t segment); +#endif + +#ifdef __cplusplus +} +#endif +#endif // !KK_IHEX_READ_H