added OTA for M3 tags

This commit is contained in:
Jelmer
2023-09-04 01:18:33 +02:00
parent 8055de91f3
commit efb5a3cb55
28 changed files with 10704 additions and 9 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,719 @@
:1000000000600020B5090000DD090000DF090000E4
:10001000E1090000E3090000E5090000000000001C
:10002000000000000000000000000000E7090000E0
:10003000E909000000000000EB090000ED090000E4
:10004000EF090000EF090000C90E0000EF090000F1
:10005000EF090000EF090000EF090000EF090000C0
:10006000EF090000EF090000EF090000B5020000F1
:10007000EF090000EF090000EF090000EF090000A0
:10008000EF090000450F0000EF090000EF09000034
:10009000EF090000EF090000EF090000EF09000080
:1000A000EF090000EF090000EF090000EF09000070
:1000B000EF090000EF090000000000000000000050
:1000C000EF090000EF090000EF090000EF09000050
:1000D000EF090000EF090000EF0900000000000038
:1000E0000000000000000000000000000000000010
:1000F0000000000000000000000000000000000000
:1001000000000000000000000000000000000000EF
:1001100000000000000000000000000000000000DF
:1001200000000000000000000000000000000000CF
:1001300000000000000000000000000000000000BF
:1001400000000000000000000000000000000000AF
:10015000000000000000000000000000000000009F
:10016000000000000000000000000000000000008F
:10017000000000000000000000000000000000007F
:10018000000000000000000000000000000000006F
:10019000000000000000000000000000000000005F
:1001A000000000000000000000000000000000004F
:1001B000000000000000000000000000000000003F
:1001C000000000000000000000000000000000002F
:1001D000000000000000000000000000000000001F
:1001E000000000000000000000000000000000000F
:1001F00000000000000000000000000000000000FF
:1002000010B5054C237833B9044B13B10448AFF350
:1002100000800123237010BD780000200000000042
:100220003C2C000008B5034B1BB103490348AFF356
:10023000008008BD000000007C0000203C2C000075
:10024000154B002B08BF134B9D46A3F5803A0021A8
:100250008B460F461348144A121A01F0B5FB0F4B98
:10026000002B00D098470E4B002B00D09847002061
:10027000002104000D000D48002802D00C48AFF307
:10028000008001F075FB2000290000F071FE01F0F4
:100290005BFB00BF000008000060002000000000C1
:1002A0000000000078000020540200200000000040
:1002B0000000000073B5134CD4F84061012E1FD12B
:1002C0000023C4F84031104BD4F80455186801F0ED
:1002D00093F90E4901F09CFA4FF08E4101F0E4F9D8
:1002E00001F05CF80A4B002200F0FAFE01F0AEF8D3
:1002F0002844C4F84005D4F840310193019B66605E
:1003000002B070BD00B000400000002000007A4440
:100310000000E03F70B506460825002433064CBFB8
:10032000012100210F2000F07DFE0E20012176002A
:1003300000F078FE64000D20F6B2E4B200F084FE16
:1003400008B144F0010400210E20013D00F06AFED6
:1003500015F0FF05E2D1204670BD10B5002104461E
:100360000C2000F05FFE2046FFF7D4FF01210C2097
:10037000BDE8104000F056BE70B506460C460C2095
:100380000021154600F04EFE5A20FFF7C3FF002063
:10039000FFF7C0FF300AFFF7BDFFF0B2FFF7BAFF6B
:1003A0000020FFF7B7FF2544AC4205D00020FFF73F
:1003B000B1FF04F8010BF7E701210C20BDE8704004
:1003C00000F030BE0C2008B5002100F02BFE052007
:1003D000FFF7A0FF0020FFF79DFFC307FAD401211C
:1003E0000C2000F01FFE012008BD70B506460C462B
:1003F0000C200021154600F015FE0320FFF78AFFB0
:10040000C6F30740FFF786FFC6F30720FFF782FF1A
:10041000F0B2FFF77FFF2544AC4205D00020FFF784
:1004200079FF04F8010BF7E701210C20BDE87040CB
:1004300000F0F8BD2DE9F341AB20FFF78EFF082255
:1004400069460020FFF798FF9DF80030532B0FD12D
:100450009DF80130462B0BD19DF80230442B07D17B
:100460009DF80330502B03D19DF80730FF2B34D07B
:100470006D4801F0CDFB00210C2000F0D3FD902051
:10048000FFF748FF0020FFF745FF0020FFF742FF7E
:100490000020FFF73FFF0020FFF73CFFC22809D1F3
:1004A000624B202200201A70FFF734FF052803D08A
:1004B00012280ED0002404E05D4B4FF480321A6005
:1004C000012401210C2000F0ADFD204602B0BDE862
:1004D000F081574B4FF40022F1E79DF805100129F8
:1004E00006D09DF80420534801F01EFB0024ECE7E1
:1004F0009DF80640FF2C08BFFE240025E8B201301D
:1005000008226946C000FFF737FF9DF80030002B36
:1005100040F083809DF80230012B7ED19DF803309E
:10052000082B7AD9444CBDF8040024222146FFF759
:1005300023FF237803F00302012A204604D03F481A
:1005400001F066FB3E4845E05A0701D43D48F7E715
:10055000A37813F0060F01D03B48F1E765786B1ED6
:10056000DBB2FD2B01D93948EAE7304BE2791D7047
:10057000130601D53648E3E77AB32D4B4FF400114B
:1005800019602B4B196854104900E2B2002CFAD1C3
:100590001960304A304992F800C091F800E01C27F9
:1005A0002346A046C4196478661EF6B2FD2E24D8F0
:1005B000C65D0F2E2ED0102E1CD00C2E1DD1A542A4
:1005C0001BD0B8F1000F01D081F800E00BB182F828
:1005D00000C0224801F01CFB88E7A2791AB1144B35
:1005E0004FF40051CCE7627912B1114B2021C7E7DB
:1005F0001B48A5E7A6464FF001080237242FD1D1AA
:10060000B8F1000F01D081F800E00BB182F800C012
:1006100001245AE7A4460123EFE70135EBB29C42DF
:10062000BFF46CAF8EE700BF8C290000980000205B
:1006300094000020A32900009B000020BF29000097
:10064000602A0000CF290000E8290000FC290000F2
:10065000182A0000990000209A000020452A000076
:100660002D2A00002DE9F04105460F4616468EB3AF
:100670005FFA85F8C8F58074A4B2B4424FF0060062
:1006800028BF3446FFF769FE00210C2000F0CAFCA9
:100690000220FFF73FFEC5F30740FFF73BFEC5F31F
:1006A0000720FFF737FE4046FFF734FE07EB04084C
:1006B000474504D017F8010BFFF72CFEF8E701219E
:1006C0000C2000F0AFFCFFF77DFE20B12544341B69
:1006D000A6B2CCE70120BDE8F08100001FB50C22D6
:1006E00001A94FF44030FFF780FE074B029A9A426F
:1006F00007D10398054BC31A5842584105B05DF81D
:1007000004FB0020FAE700BFBAABBAABEFBEADDE28
:100710001FB50C2201A94FF44030FFF766FE019887
:1007200005B05DF804FB00001A4B022230B5C3F897
:100730000425D3F80024002AFBD0C3F80805D3F819
:100740000024002AFBD00022C3F80425114B1A46CE
:10075000D3F80044002CFBD00124C3F80445D2F8A0
:100760000034002BFBD00B4A0B1F01F6FC74401A1F
:10077000114653F8045FC550D2F80054002DFBD049
:10078000A342F6D10023C2F80435D1F80034002B7F
:10079000FBD030BD00E001401FB504A9002341F8A3
:1007A0000C3D0C224FF44030CDE90233FFF75AFFE5
:1007B00005B05DF804FB08B50121102000F032FC03
:1007C0000121112000F02EFC0121122000F02AFC52
:1007D0000121102000F0FEFB0121112000F0FAFBA6
:1007E0000121122000F0F6FB02211C2000F0F2FB98
:1007F00002211D2000F0EEFB03210A2000F0EAFB9D
:1008000003210B2000F0E6FB00210D2000F0E2FBAD
:1008100001210E2000F0DEFB01210F2000F0DAFBA9
:1008200001210C2000F0FEFB01210C20BDE8084056
:1008300000F0D0BB80B400AF72B6074A4FF48043DB
:1008400093601B6883F3088844F204031B6862B654
:10085000BD4680BC184700BF00ED00E010B5002188
:10086000044600F0DFFB032000F05EFB2046012180
:10087000BDE8104000F0D6BBF8B5FFF749FF0F24E4
:1008800005461220FFF7EAFF013C462000F04CFB32
:1008900014F0FF04F5D1A5F50053B3F5283F0BD9AB
:1008A00014241020FFF7DAFF013C642000F03CFB29
:1008B00014F0FF04F5D1F8BD29461848184F01F08F
:1008C00033F94FF4805001F077F806464FF4805228
:1008D00020463146FFF789FD04F580403146FFF799
:1008E00023FF2146384601F01FF904F580541220F9
:1008F000FFF7B4FFA542E9D80A4801F089F90021C1
:10090000112000F08FFB4FF4FA7000F00DFB012175
:100910001120BDE8F84000F085BB00BF8F2A000021
:10092000B32A0000C92A00007047000008B54FF440
:10093000E1310E4800F084F94FF4967000F0F4FABB
:100940000B4801F065F9FFF736FFFFF773FDFFF77E
:10095000C5FE38B1FFF790FFFFF71EFFBDE8084066
:10096000FFF768BF1120FFF779FFF7E7DC010020F0
:10097000E22A000010B50348144600F005F82046AE
:1009800010BD00BFDC0100202DE9F04106460D46F8
:1009900001EB02080C464445A4EB050707D0336879
:1009A00014F8011B1B68304698470028F3D13846DD
:1009B000BDE8F0810649074A074B9B1A03DD043B5B
:1009C000C858D050FBDC00F039F8FFF739FC0000C4
:1009D000482C00000000002078000020FEE7FEE721
:1009E000FEE7FEE7FEE7FEE7FEE7FEE7FEE7FEE7DF
:1009F000074B1B78062B09D1064B1B68C3F3031367
:100A0000033B032B02D8044AD05C70470020704798
:100A1000E00F00F0E80F00F0F02A0000054B186826
:100A2000421C04BF044B187820F00800831F584272
:100A30005841704730010010E00F00F008B56C4BD2
:100A40001B685A1C04BF6B4B1B78062B05D16A4BE5
:100A50006A4A1B68C3F304231360FFF7C9FF10B190
:100A6000674B684A1A60FFF7D9FF28B1664B674A9F
:100A70001B68C3F342331360FFF7BAFF20B1644A27
:100A8000D36823F08073D360FFF7C8FF40B14FF005
:100A900080430022C3F80C21C3F81021C3F8382585
:100AA000FFF7A6FF10B15B4B03221A60FFF7A0FF10
:100AB00040B1594B05221A6001229A6700229A60C0
:100AC0003F225A604A4B1A68501C0BBF494B534B8C
:100AD0001A781B6802BF08331B68C3F30313062A86
:100AE0004ED1033B032B03D84D4AD35C002B49D096
:100AF0004FF080524B4BD2F80414C3F82015D2F8B3
:100B00000814C3F82415D2F80C14C3F82815D2F829
:100B10001014C3F82C15D2F81414C3F83015D2F8F9
:100B20001814C3F83415D2F81C14C3F84015D2F8C1
:100B30002014C3F84415D2F82414C3F84815D2F889
:100B40002814C3F84C15D2F82C14C3F85015D2F859
:100B50003014C3F85415D2F83414C3F86015D2F821
:100B60003814C3F86415D2F83C14C3F86815D2F8E9
:100B70004014C3F86C15D2F84424C3F8702501E082
:100B80000E2AB5D01A4B1B68591C04BF194B1B7891
:100B9000062B05D1244B254A1B6803F04F03136035
:100BA000FFF73CFF48B14FF08043D3F80024D20751
:100BB00044BF6FF00102C3F800240D4B1B68062BE5
:100BC00009D1164B1B68033B022B81BF184A1368DF
:100BD00043F480631360064B1B680E2B01BF134A5E
:100BE000136843F00F031360124B134A1A6008BDD9
:100BF00030010010E00F00F02403001040350140E8
:100C000074C007400DF0ADBA440200103C0500402E
:100C1000F0ED00E0A0050040105600403401001047
:100C2000EC2A000000C0004058020010E40E004012
:100C30003C170040040000200090D00301207047C2
:100C400003681322DB69184770470369C3F81C1552
:100C50000369D3F81C21002AFBD00022C3F81C2111
:100C60000120704710B490F95C30144C59090122EE
:100C7000203103F01F0302FA03F344F82130036923
:100C800010BC0421C3F8081303695A600369DA60D1
:100C900003690022C3F8002502694FF0FF33C2F850
:100CA0000C350269C2F814350269C2F808350269C8
:100CB0001430C2F8103500F0EDB900BF00E100E0DB
:100CC000143000F0F9B9143000F0FCB9143000F021
:100CD000E5B90000036990F85E2010B5C3F80C2553
:100CE000036990F85D20C3F8142590F8612003692A
:100CF000012A01BF90F85F40C3F81045036990F8DE
:100D0000604006BFC3F8084503690022B1F5966F3D
:100D1000C3F86C2569D9B1F5166F69D9B1F5965F3D
:100D200069D9B1F5165F68D9B1F5615F67D9B1F5D9
:100D3000964F66D9B1F5E14F65D9B1F5164F64D933
:100D4000B1F5614F64D9B1F5963F64D9B1F5E13F92
:100D500063D9B1F5613F63D9364B994263D9B1F597
:100D6000E12F63D9B1F5612F94BF4FF070634FF05D
:100D700080530269C2F8243503690422C3F80025B0
:100D800001690023C1F808310169C1F81C3101690A
:100D900001230B6001698B600169C1F8042390F99C
:100DA0005C20510902F01F0293406031224A42F850
:100DB000213090F95C30002BBDBF03F00F0302F629
:100DC000FC32D2189B18B5BF60236022137683F8DB
:100DD000002390F95C300122590903F01F0302FA45
:100DE00003F3154A42F8213010BD4FF49E23C0E7AB
:100DF0004FF41D23BDE7114BBBE7114BB9E7114B76
:100E0000B7E7114BB5E7114BB3E74FF41D03B0E75C
:100E10004FF46B03ADE70E4BABE74FF0EB73A8E776
:100E20004FF06C73A5E74FF08063A2E74FF0E863E3
:100E30009FE700BF90D0030000E100E000B0130086
:100E40000050270000F03A0000A04E0000C07500DE
:100E500000903A012DE9F0411E4600254FF47A73C7
:100E6000C0E901530D4B044640F8143B1746884631
:100E700000F0FCF80A4AC4F8108084F85C7052F85C
:100E8000263084F85D309DF8183052F8233084F80D
:100E90005E3084F861502046BDE8F081FC2A0000F5
:100EA000242B000010B50369D3F8082104464AB189
:100EB000D3F818151430C9B200F0E1F82369002204
:100EC000C3F8082110BD00000148FFF7EBBF00BFC9
:100ED000DC01002007B51923009302221A230349DD
:100EE0000348FFF7B7FF03B05DF804FB00200040A4
:100EF000DC0100200A4B19680A4B30B5D3F8040511
:100F00000C060D0A44EA00024FF47A712B46A2FB4C
:100F1000014501FB0355E00B40EA454030BD00BFF1
:100F2000400200200010014038B5044648B1FFF7E8
:100F3000E1FF054600F01AF8FFF7DCFF401BA04276
:100F4000F8D338BD074B0022C3F8042182B0D3F890
:100F50000431054A0193019B13680133DBB213602E
:100F600002B07047001001404002002070477047F7
:100F700008B500F011F8FFF7FAFF0120FFF7D4FFE2
:100F8000FFF7D4FC034CFFF7CFFC002CFBD0AFF3F2
:100F90000080F8E7000000000D4BE02283F81123E9
:100FA0004FF40032C3F880211A604FF080430021D3
:100FB0000122C3F818159A6003F58833C3F80815A1
:100FC0000221C3F80413C3F844131A60704700BF2A
:100FD00000E100E01F280FD8114B53F820300329FF
:100FE0000AD8DFE801F002160A1003F5E0734FF0AB
:100FF000A042002142F82310704703F5E0734FF040
:10100000A0420C21F6E703F5E0734FF0A042042163
:10101000F0E703F5E0734FF0A0420321EAE700BFD9
:10102000242B00001F280CD8064B53F82020012346
:1010300093404FF0A04211B9C2F80C357047C2F886
:1010400008357047242B00001F289FBF4FF0A04396
:10105000054AD3F8103552F820009ABF23FA00F061
:1010600000F0010000207047242B000008B540224A
:10107000002100F0A9FC0022C0E9102208BD026C8A
:1010800010B5531C446C03F03F039C421CBF8154B9
:10109000036410BD0023C0E910337047D0E910236A
:1010A00093421FBFC25C013303F03F03436414BF8C
:1010B00010464FF0FF307047D0E91030181A48BF83
:1010C00040307047D0E91023934214BFC05C4FF00A
:1010D000FF30704781F0004102E000BF83F0004321
:1010E00030B54FEA41044FEA430594EA050F08BFC3
:1010F00090EA020F1FBF54EA000C55EA020C7FEA87
:10110000645C7FEA655C00F0E2804FEA5454D4EB03
:101110005555B8BF6D420CDD2C4480EA020281EACD
:10112000030382EA000083EA010180EA020281EA05
:101130000303362D88BF30BD11F0004F4FEA013157
:101140004FF4801C4CEA113102D0404261EB410166
:1011500013F0004F4FEA03334CEA133302D05242EC
:1011600063EB430394EA050F00F0A780A4F10104A8
:10117000D5F1200E0DDB02FA0EFC22FA05F28018E2
:1011800041F1000103FA0EF2801843FA05F35941C8
:101190000EE0A5F120050EF1200E012A03FA0EFC47
:1011A00028BF4CF0020C43FA05F3C01851EBE37171
:1011B00001F0004507D54FF0000EDCF1000C7EEB8E
:1011C00000006EEB0101B1F5801F1BD3B1F5001FCC
:1011D0000CD349085FEA30004FEA3C0C04F10104EB
:1011E0004FEA445212F5800F80F09A80BCF1004F14
:1011F00008BF5FEA500C50F1000041EB045141EA96
:10120000050130BD5FEA4C0C404141EB010111F496
:10121000801FA4F10104E9D191F0000F04BF014641
:101220000020B1FA81F308BF2033A3F10B03B3F11F
:1012300020020CDA0C3208DD02F1140CC2F10C02AF
:1012400001FA0CF021FA02F10CE002F11402D8BF0D
:10125000C2F1200C01FA02F120FA0CFCDCBF41EAD9
:101260000C019040E41AA2BF01EB0451294330BDA8
:101270006FEA04041F3C1CDA0C340EDC04F1140485
:10128000C4F1200220FA04F001FA02F340EA03005C
:1012900021FA04F345EA030130BDC4F10C04C4F1A2
:1012A000200220FA02F001FA04F340EA0300294682
:1012B00030BD21FA04F0294630BD94F0000F83F4CC
:1012C000801306BF81F480110134013D4EE77FEAAF
:1012D000645C18BF7FEA655C29D094EA050F08BFFB
:1012E00090EA020F05D054EA000C04BF19461046DC
:1012F00030BD91EA030F1EBF0021002030BD5FEA20
:10130000545C05D14000494128BF41F0004130BD47
:1013100014F580043CBF01F5801130BD01F000459B
:1013200045F0FE4141F470014FF0000030BD7FEA0E
:10133000645C1ABF194610467FEA655C1CBF0B4609
:10134000024650EA013406BF52EA033591EA030F20
:1013500041F4002130BD00BF90F0000F04BF002118
:10136000704730B54FF4806404F132044FF000054B
:101370004FF0000150E700BF90F0000F04BF0021C4
:10138000704730B54FF4806404F1320410F000452A
:1013900048BF40424FF000013EE700BF42004FEA25
:1013A000E2014FEA31014FEA02701FBF12F07F43A2
:1013B00093F07F4F81F06051704732F07F4208BF59
:1013C000704793F07F4F04BF41F40021704730B560
:1013D0004FF4607401F0004521F000411CE700BFAC
:1013E00050EA010208BF704730B54FF000050AE02F
:1013F00050EA010208BF704730B511F0004502D530
:10140000404261EB41014FF4806404F132045FEA31
:10141000915C3FF4D8AE4FF003025FEADC0C18BFDA
:1014200003325FEADC0C18BF033202EBDC02C2F1CC
:10143000200300FA03FC20FA02F001FA03FE40EA5E
:101440000E0021FA02F11444BDE600BF4A0011D299
:1014500012F5001211D20DD56FF47873B3EB62520E
:101460000ED44FEAC12343F0004343EA505323FA1A
:1014700002F070474FF00000704750EA013002D18F
:101480004FF0FF3070474FF00000704780F0004091
:1014900002E000BF81F0004142001FBF5FEA41034C
:1014A00092EA030F7FEA226C7FEA236C6AD04FEA4C
:1014B0001262D2EB1363C1BFD21841404840414091
:1014C000B8BF5B42192B88BF704710F0004F40F443
:1014D000000020F07F4018BF404211F0004F41F45F
:1014E000000121F07F4118BF494292EA030F3FD02B
:1014F000A2F1010241FA03FC10EB0C00C3F120033E
:1015000001FA03F100F0004302D5494260EB4000CC
:10151000B0F5000F13D3B0F1807F06D340084FEA37
:10152000310102F10102FE2A51D2B1F1004F40EB2C
:10153000C25008BF20F0010040EA03007047490094
:1015400040EB000010F4000FA2F10102EDD1B0FA5F
:1015500080FCACF1080CB2EB0C0200FA0CF0AABF54
:1015600000EBC25052421843BCBFD04018437047F2
:1015700092F0000F81F4000106BF80F400000132F8
:10158000013BB5E74FEA41037FEA226C18BF7FEACF
:10159000236C21D092EA030F04D092F0000F08BF11
:1015A0000846704790EA010F1CBF0020704712F0F8
:1015B0007F4F04D1400028BF40F00040704712F137
:1015C00000723CBF00F50000704700F0004343F09C
:1015D000FE4040F4000070477FEA226216BF0846D2
:1015E0007FEA23630146420206BF5FEA412390EA95
:1015F000010F40F4800070474FF0000304E000BF8B
:1016000010F0004348BF40425FEA000C08BF70473B
:1016100043F0964301464FF000001CE050EA0102FF
:1016200008BF70474FF000030AE000BF50EA010214
:1016300008BF704711F0004302D5404261EB410101
:101640005FEA010C02BF84460146002043F0B64326
:1016500008BFA3F18053A3F50003BCFA8CF2083A4B
:10166000A3EBC25310DB01FA02FC634400FA02FC54
:10167000C2F12002BCF1004F20FA02F243EB02005B
:1016800008BF20F00100704702F1200201FA02FCBD
:10169000C2F1200250EA4C0021FA02F243EB0200B0
:1016A00008BF20EADC7070474FF0FF0C1CEAD052F4
:1016B0001EBF1CEAD15392EA0C0F93EA0C0F6FD0B5
:1016C0001A4480EA010C400218BF5FEA41211ED093
:1016D0004FF0006343EA501043EA5111A0FB01317F
:1016E0000CF00040B1F5000F3EBF490041EAD37154
:1016F0005B0040EA010062F17F02FD2A1DD8B3F1D0
:10170000004F40EBC25008BF20F00100704790F03E
:10171000000F0CF0004C08BF49024CEA502040EA90
:1017200051207F3AC2BFD2F1FF0340EAC250704756
:1017300040F400004FF00003013A5DDC12F1190F94
:10174000DCBF00F000407047C2F10002410021FA06
:1017500002F1C2F1200200FA02FC5FEA310040F11E
:10176000000053EA4C0308BF20EADC70704792F097
:10177000000F00F0004C02BF400010F4000F013ACF
:10178000F9D040EA0C0093F0000F01F0004C02BFCA
:10179000490011F4000F013BF9D041EA0C018FE739
:1017A0000CEAD15392EA0C0F18BF93EA0C0F0AD03F
:1017B00030F0004C18BF31F0004CD8D180EA010065
:1017C00000F00040704790F0000F17BF90F0004FFE
:1017D000084691F0000F91F0004F14D092EA0C0FE0
:1017E00001D142020FD193EA0C0F03D14B0218BF73
:1017F000084608D180EA010000F0004040F0FE40B9
:1018000040F40000704740F0FE4040F44000704754
:101810004FF0FF0C1CEAD0521EBF1CEAD15392EAD3
:101820000C0F93EA0C0F69D0A2EB030280EA010CC3
:1018300049024FEA402037D04FF0805343EA11115C
:1018400043EA10130CF000408B4238BF5B0042F1BA
:101850007D024FF4000C8B4224BF5B1A40EA0C005F
:10186000B3EB510F24BFA3EB510340EA5C00B3EB91
:10187000910F24BFA3EB910340EA9C00B3EBD10F7F
:1018800024BFA3EBD10340EADC001B0118BF5FEAD1
:101890001C1CE0D1FD2A3FF650AF8B4240EBC250FA
:1018A00008BF20F0010070470CF0004C4CEA5020BB
:1018B0007F32C2BFD2F1FF0340EAC250704740F40A
:1018C00000004FF00003013A37E792F0000F00F0FC
:1018D000004C02BF400010F4000F013AF9D040EA7A
:1018E0000C0093F0000F01F0004C02BF490011F40E
:1018F000000F013BF9D041EA0C0195E70CEAD15306
:1019000092EA0C0F08D142027FF47DAF93EA0C0FEC
:101910007FF470AF084676E793EA0C0F04D14B02D0
:101920003FF44CAF08466EE730F0004C18BF31F082
:10193000004CCAD130F000427FF45CAF31F000437C
:101940007FF43CAF5FE700BF08B5074B044613B117
:101950000021AFF30080054B1868836A03B19847F4
:10196000204601F005F800BF00000000A42B000095
:1019700070B50D4E0D4CA41BA4100025A54209D135
:101980000B4E0C4C00F0F6FFA41BA4100025A54242
:1019900005D170BD56F8253098470135EEE756F869
:1019A000253098470135F2E76C0000206C000020DC
:1019B0006C00002074000020024B0146186800F003
:1019C00059B800BF0800002002440346934200D1EA
:1019D000704703F8011BF9E738B50546002945D0E3
:1019E00051F8043C0C1F002BB8BFE41800F0C6FBF4
:1019F0001F4A1368104633B9636014602846BDE877
:101A0000384000F0BCBBA3420CD921686218934255
:101A100004BF1A685B68636004BF521822600460E8
:101A2000ECE713465A680AB1A242FAD91968581865
:101A3000A0420BD120680144581882421960DDD1C0
:101A4000106852685A6001441960D7E702D90C2324
:101A50002B60D3E7206821188A4204BF11685268BE
:101A6000626004BF091821605C60C7E738BD00BF31
:101A70004402002070B5CD1C25F0030508350C2D5F
:101A800038BF0C25002D064601DBA94203D90C23E3
:101A90003360002070BD00F071FB214A14682146BC
:101AA00091B9204C23681BB9304600F0B9F820608A
:101AB0002946304600F0B4F8431C24D10C2333608F
:101AC000304600F05CFBE4E70B685B1B18D40B2B83
:101AD0000FD90B60CD50CC18304600F050FB04F10C
:101AE0000B00231D20F00700C31AD3D05A42E25046
:101AF000D0E78C424B6816BF636013600C46EBE77F
:101B00000C464968CCE7C41C24F00304A04205D06D
:101B1000211A304600F084F80130CFD02560DBE791
:101B200044020020480200200FB40A4B13B51C6881
:101B300024B1A36913B9204600F032FA05AB049A28
:101B4000A1680193204600F043FB02B0BDE81040BD
:101B500004B070470800002070B50E46054618B165
:101B600083690BB900F01CFAAB69AC6813B928465D
:101B700000F016FA234B9C4217D16C68A3891B070F
:101B80001DD52369DBB1013EA36816F8011F013B97
:101B9000A360E9B9002B2EDA22460A21284600F07C
:101BA0004FF8013011D00A2011E0174B9C4201D1AF
:101BB000AC68E3E7154B9C4208BFEC68DEE72146C2
:101BC000284600F08FF80028DDD04FF0FF3070BDC0
:101BD000002B04DAA2699A4206DC0A2904D02368A1
:101BE0005A1C22601970CFE72246284600F028F8D8
:101BF0000130C9D1E9E723680A205A1C2260187015
:101C0000E5E700BFC82B0000E82B0000A82B000070
:101C1000024B01461868FFF79FBF00BF0800002075
:101C200038B5064C002305460846236000F092FEB6
:101C3000431C02D1236803B12B6038BD5002002041
:101C4000F8B50E461446054618B183690BB900F085
:101C5000A7F9214B9C422AD16C68A369A360A38990
:101C60001A072ED5236963B323692068C01A6369F4
:101C7000F6B28342374604DC2146284600F026F9B6
:101C800028BBA368013BA36023685A1C22601E7016
:101C900063690130834204D0A389DB0719D50A2E7A
:101CA00017D12146284600F011F990B10FE00B4BF7
:101CB0009C4201D1AC68D0E7094B9C4208BFEC685C
:101CC000CBE72146284600F00DF80028CCD04FF095
:101CD000FF373846F8BD00BFC82B0000E82B0000D6
:101CE000A82B0000324B70B51D6806460C4625B186
:101CF000AB6913B9284600F053F92E4B9C420FD123
:101D00006C68B4F90C309AB215072CD4D00611D4F3
:101D10000922326043F04003A3814FF0FF303EE0E0
:101D2000254B9C4201D1AC68EBE7244B9C4208BF99
:101D3000EC68E6E7510712D5616B41B104F1440349
:101D4000994202D03046FFF747FE00236363A38920
:101D500023F02403A3810023636023692360A38904
:101D600043F00803A38123694BB9A38903F42073CB
:101D7000B3F5007F03D02146304600F0BFF9A289B9
:101D800012F001030CD00023A36063695B42A361DE
:101D9000236953B9B4F90C3013F08000BAD170BD87
:101DA000920758BF6369A360F2E70020F7E700BF1E
:101DB00008000020C82B0000E82B0000A82B000022
:101DC0008A892DE9F041054610070C4658D44B6826
:101DD000002B05DC0B6C002B02DC0020BDE8F08141
:101DE000E66A002EF9D0002312F480522F68216A8F
:101DF0002B6032D0606DA3895A0705D56368C01A7D
:101E0000636B0BB1236CC01A00230246E66A216A99
:101E10002846B047431CA38906D129681D2948D804
:101E2000294ACA40D60744D500226260D9042269F3
:101E3000226004D5421C01D12B6803B96065616B37
:101E40002F600029C9D004F14403994202D02846EA
:101E5000FFF7C2FD00206063C0E701232846B047BA
:101E6000411CC8D12B68002BC5D01D2B01D0162BCF
:101E700001D12F60B1E7A38943F04003A381ADE70F
:101E80000F69002FA9D093070E6808BF4B690F6038
:101E900018BF0023A6EB07088B60B8F1000F9CDD8C
:101EA00043463A46216AA66A2846B047002806DC1F
:101EB000A38943F04003A3814FF0FF308EE707442E
:101EC000A8EB0008E9E700BF0100402038B50B6926
:101ED00005460C46DBB118B183690BB900F060F818
:101EE0000C4B9C4209D16C68B4F90C307BB1214693
:101EF0002846BDE83840FFF763BF074B9C4201D13D
:101F0000AC68F1E7054B9C4208BFEC68ECE70020A9
:101F100038BD00BFC82B0000E82B0000A82B000034
:101F2000002310B50446C0E9003383608181436615
:101F3000C281C0E904338361194608225C30FFF78F
:101F400043FD054B6362054BA362054BE362054B02
:101F50002462236310BD00BF092700002B27000067
:101F60006327000087270000014900F085B800BF03
:101F7000CD1E000070B54A1E682555430E4605F17A
:101F80007401FFF777FD044640B10021C0E9001657
:101F90000C30A06005F16802FFF716FD204670BD09
:101FA000836910B5044633BBC0E912330365124B95
:101FB000124A1B688262984204BF0123836100F0C9
:101FC0001FF86060204600F01BF8A060204600F07B
:101FD00017F80022E06004216068FFF7A1FF0122EA
:101FE0000921A068FFF79CFF02221221E068FFF799
:101FF00097FF0123A36110BDA42B0000691F0000FF
:10200000F8B51B4B1E68B369074613B93046FFF796
:10201000C7FF4836D6E90134013B03D5336833B1F5
:102020003668F7E7B4F90C506DB16834F4E7042171
:102030003846FFF79FFF30600028F1D10C233B604A
:1020400004462046F8BD0B4B6566C4E90055A56003
:10205000C4E90335C4E905550822294604F15C00AA
:10206000FFF7B2FCC4E90D55C4E91255E9E700BF1A
:10207000A42B00000100FFFF2DE9F84380468946AC
:1020800000F14804002614B93046BDE8F883D4E9CD
:102090000175013F01D52468F5E7AB89012B07D90C
:1020A000B5F90E30013303D029464046C8470643F0
:1020B0006835EEE770B50E46B1F90E10002996B0FE
:1020C00014461D4607DA00232B60B3891A0610D484
:1020D0004FF480630EE06A4600F07CFB0028F2DBE0
:1020E000019A02F47042A2F500535A425A412A6002
:1020F000EEE740230020236016B070BD8B8973B5D6
:102100009D0706460C4607D504F14703236023616B
:102110000123636102B070BD01AB6A46FFF7CAFFDD
:10212000009905463046FFF7A5FC48B9B4F90C30D4
:102130009A05EFD423F0030343F00203A381E3E7FE
:102140000D4BB362A389206043F08003A381009B01
:102150006361019B20615BB1B4F90E10304600F061
:102160004BFB28B1A38923F0030343F00103A381B0
:10217000A3891D43A581CDE7691F00007047704703
:102180009368013B002B10B4936007DA9469A34273
:1021900001DB0A2902D110BCFFF752BD1368581C9D
:1021A00010601970084610BC7047F8B506460F4617
:1021B0001446D518AC4201D1002007E03A4614F885
:1021C000011B3046FFF7DCFF431CF3D1F8BD0000D4
:1021D0002DE9F04F9DB00C4617460393064618B103
:1021E00083690BB9FFF7DCFE7B4B9C4257D17468C7
:1021F000A38918075DD52369002B5AD000230993C2
:1022000020238DF8293030238DF82A304FF0010B30
:10221000B846454615F8013B0BB1252B54D1B8EB18
:10222000070A0BD053463A4621463046FFF7BDFF1A
:10223000013000F0C280099B5344099398F80030A4
:10224000002B00F0BA8000234FF0FF32CDE90523C8
:10225000049307938DF853301A93A846052218F873
:10226000011B5E4800F0ECFA049B78BBD90644BF22
:1022700020228DF853201A0744BF2B228DF85320BB
:102280002A782A2A2AD0079AA84600200A254146F9
:1022900011F8013B303B092B69D960B324E0504B66
:1022A0009C4201D1B468A3E74E4B9C4208BFF4683E
:1022B0009EE721463046FFF715FD00289ED04FF0DF
:1022C000FF301DB0BDE8F08FA846A2E7434A801A50
:1022D0000BFA00F0184304904546BEE7039A111D1F
:1022E00012680391002A01DB079204E0524243F096
:1022F00002030792049398F800302E2B0ED198F821
:1023000001302A2B38D1039B1A1D1B680392002B26
:10231000B8BF4FF0FF3308F102080593324D98F82B
:1023200000100322284600F08BFA40B14023401BE6
:1023300003FA00F0049B034308F10108049398F8A2
:1023400000102A488DF82810062208F1010700F035
:1023500077FA002837D0264B1BBB039B073323F0AB
:10236000070308330393099B4B44099350E705FB8C
:102370000232012088468AE7002308F1010805930C
:1023800019460A25404610F8012B303A092A03D98C
:10239000002BC3D00591C1E705FB01210123804635
:1023A000F0E703AB00932246124B04A93046AFF38B
:1023B0000080B0F1FF3F8146D5D1A3895B063FF590
:1023C0007EAF09987DE703AB00932246094B04A931
:1023D000304600F087F8ECE7C82B0000082C00001E
:1023E000E82B0000A82B00000E2C0000122C00008F
:1023F00000000000AB2100002DE9F04791461F4688
:102400008A680B69DDF820809342B8BF1346C9F88B
:10241000003091F8432006460C4612B10133C9F84A
:1024200000302368990642BFD9F800300233C9F85A
:102430000030256815F0060507D104F1190AE36894
:10244000D9F800209B1AAB4228DC94F8433022686C
:10245000003318BF012392062DD404F143023946FC
:102460003046C047013020D02368E568D9F8002005
:1024700003F00603042B08BFAD1AA36822690CBF42
:1024800025EAE57500259342C4BF9B1AED184FF06D
:1024900000091A344D451AD1002008E001235246A4
:1024A00039463046C047013003D14FF0FF30BDE818
:1024B000F0870135C3E7E1185A1C302081F843004A
:1024C000224494F8451082F843100233C5E70123F3
:1024D000224639463046C0470130E6D009F10109AD
:1024E000D8E700002DE9F04301F1430C0C46097ECA
:1024F00085B06E291746064698460C9A00F0B380C0
:1025000022D8632936D00AD8002900F0B98058298A
:1025100000F0838004F1420584F8421032E064291F
:1025200001D06929F6D120681368050603F104017A
:102530002AD51B681160002B03DA2D225B4284F838
:1025400043206F480A2239E0732900F09D8008D8A3
:102550006F2920D07029DDD1236843F02003236048
:1025600003E0752917D07829D4D1782384F8453031
:10257000644855E01368191D1B68116004F1420599
:1025800084F8423001238CE01B68116010F0400F8A
:1025900018BF1BB2CFE713682568181D1060280606
:1025A00001D51B6802E06806FBD51B8854486F29DB
:1025B00014BF0A220822002184F843106568A56030
:1025C000002DC0F29580216821F004012160002BCC
:1025D0003DD1002D40F08E806546082A0BD123683E
:1025E000DB0708D5236962689A42DEBF302305F80D
:1025F000013C05F1FF35ACEB05032361CDF800800C
:102600003B4603AA21463046FFF7F6FE01304DD186
:102610004FF0FF3005B0BDE8F083394884F845102D
:10262000136821681D1D1B6815600A060BD5CA07B3
:1026300044BF41F0200121601BB9226822F0200232
:1026400022601022B7E74D0648BF9BB2EFE7654610
:10265000B3FBF2F102FB1133C35C05F8013D0B46FD
:102660000029F5D1B9E7136825686169181D106064
:1026700028061B6801D5196002E06A06FBD519809F
:10268000002323616546B9E71368191D11601D68B1
:1026900062680021284600F0D3F808B1401B606052
:1026A00063682361002384F84330A7E723692A463F
:1026B00039463046C0470130AAD023689B0713D45F
:1026C000E068039B9842B8BF1846A3E701234A4637
:1026D00039463046C04701309AD00135E368039A45
:1026E0009B1AAB42F2DCEBE7002504F11909F5E790
:1026F000002BACD1037884F8423004F142056CE73A
:10270000192C00002A2C000010B50C46B1F90E104F
:1027100000F0E6F80028ABBF636DA3891B1823F413
:102720008053ACBF6365A38110BD2DE9F0411F4606
:102730008B89DB0505460C46164605D5022300228B
:10274000B1F90E1000F068F8A389B4F90E1023F463
:102750008053A38132463B462846BDE8F04100F055
:1027600017B810B50C46B1F90E1000F055F8431C1F
:10277000A38915BF606523F4805343F48053A3817C
:1027800018BFA38110BDB1F90E1000F013B80000FE
:1027900038B5074C054608461146002222601A4605
:1027A000FEF7E8F8431C02D1236803B12B6038BD63
:1027B0005002002038B5064C002305460846236029
:1027C00000F0A0F8431C02D1236803B12B6038BD90
:1027D0005002002038B5074C002305460846114634
:1027E000236000F097F8431C02D1236803B12B60EB
:1027F00038BD00BF5002002038B5064C0023054606
:102800000846236000F08EF8431C02D1236803B110
:102810002B6038BD5002002038B5074C05460846ED
:102820001146002222601A4600F084F8431C02D1AF
:10283000236803B12B6038BD500200200000000067
:1028400001F0FF01102A2BDB10F0070F08D010F861
:10285000013B013A8B422DD010F0070F42B3F6D165
:10286000F0B441EA012141EA014122F007047FF07E
:1028700000070023F0E80256083C85EA010586EAD5
:10288000010685FA47F5A3FA87F586FA47F6A5FA11
:1028900087F68EB9EED1F0BC01F0FF0102F007021D
:1028A00032B110F8013B013A83EA010313B1F8D1C8
:1028B0000020704701387047002D06BF35460338A9
:1028C000073815F0010F07D1013015F4807F02BFE2
:1028D000013015F4C03F0130F0BC0138704700BF33
:1028E00038B5074C054608461146002222601A46B4
:1028F00000F028F8431C02D1236803B12B6038BDD7
:1029000050020020024B58221A604FF0FF307047EF
:1029100050020020024B58221A604FF0FF307047DF
:1029200050020020024B58221A600020704700BF5E
:1029300050020020024B58221A604FF0FF307047BF
:1029400050020020024B58221A604FF0FF307047AF
:1029500050020020044A05491368002B08BF0B46AB
:1029600018441060184670474C020020580200209E
:10297000FEE700BFF8B500BFF8BC08BC9E46704734
:10298000F8B500BFF8BC08BC9E467047534644509B
:102990003A20686561646572206E6F7420666F7599
:1029A0006E6400534644503A2076657273696F6EC8
:1029B0002077726F6E673A2025752E25640A0053C2
:1029C0004644503A206E6F20344B2045525A0053F3
:1029D0004644503A206E6F206C61726765207772B2
:1029E0006974652062756600534644503A206164FC
:1029F00064722E6C656E20213D2033005346445096
:102A00003A20344B2045525A206F70636F64652022
:102A1000696E76616C696400534644503A2064657F
:102A20007669636520746F6F20626967005346445E
:102A3000503A2064657669636520736F20736D6119
:102A40006C6C3F2100344B2045525A206F70636FED
:102A500064652064697361677265656D656E740095
:102A6000534644503A206E6F204A454445432074F3
:102A700061626C65206F662065787065637465645B
:102A80002076657273696F6E20666F756E6400469E
:102A90006C617368696E6720256C75206279746556
:102AA000732066726F6D2053504920454550524F38
:102AB0004D0A000D466C617368696E67207061672E
:102AC0006520256C752E2E2E000A416C6C20646FDB
:102AD0006E652C20626F6F74696E67204F45504C95
:102AE00021004F45504C2D424F4F54000000010132
:102AF0000100000000000000000000004B0C00007E
:102B000089090000C10C0000CD0C0000C70C0000BA
:102B1000490C0000410C0000D50C0000650C0000C1
:102B20003D0C000000000000010000000200000059
:102B30000300000004000000050000000600000083
:102B40000700000008000000090000000A00000063
:102B50000B0000000C0000000D0000000E00000043
:102B60000F00000010000000110000001200000023
:102B70001300000014000000150000001600000003
:102B80001700000018000000190000001A000000E3
:102B90001B0000001C0000001D0000001E000000C3
:102BA0001F0000000C0000200000000000000000DA
:102BB0000000000000000000000000000000000015
:102BC0000000000000000000000000000000000005
:102BD00000000000000000000000000000000000F5
:102BE00000000000000000000000000000000000E5
:102BF00000000000000000000000000000000000D5
:102C00000000000000000000232D302B2000686C25
:102C10004C006566674546470030313233343536FF
:102C20003738394142434445460030313233343538
:102C30003637383961626364656600000000000061
:082C400000D6FF7F0100000037
:102C4800F40100000090D0030C00002000000000F8
:102C5800C82B0000E82B0000A82B00000000000093
:102C6800000000000000000000000000000000005C
:102C7800000000000000000000000000000000004C
:102C8800000000000000000000000000000000003C
:102C9800000000000000000000000000000000002C
:102CA80000000000000000000000000025020000F5
:082CB800D50E0000010200002E
:04000003000009B53B
:00000001FF

View File

@@ -0,0 +1,25 @@
import sys
from intelhex import IntelHex
def cut_hex_file(input_hex_file, output_bin_file):
try:
ih = IntelHex(input_hex_file)
# Cut the first 16K (16 * 1024 bytes)
ih = ih[16 * 1024:]
# Write the remaining data to a binary file
ih.tobinfile(output_bin_file)
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python script.py input.hex output.bin")
sys.exit(1)
input_hex_file = sys.argv[1]
output_bin_file = sys.argv[2]
cut_hex_file(input_hex_file, output_bin_file)

View File

@@ -0,0 +1,178 @@
#!/usr/bin/python
# Copyright (c) 2008,2010,2011,2013,2014,2015 Alexander Belchenko
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Merge content of several hex files into one file."""
VERSION = '2.0'
USAGE = '''hexmerge: merge content of hex files.
Usage:
python hexmerge.py [options] FILES...
Options:
-h, --help this help message.
-v, --version version info.
-o, --output=FILENAME output file name (emit output to stdout
if option is not specified)
-r, --range=START:END specify address range for output
(ascii hex value). Both values are inclusive.
Range can be in form 'START:' or ':END'.
--no-start-addr Don't write start addr to output file.
--overlap=METHOD What to do when data in files overlapped.
Supported variants:
* error -- stop and show error message (default)
* ignore -- keep data from first file that
contains data at overlapped address
* replace -- use data from last file that
contains data at overlapped address
Arguments:
FILES list of hex files for merging
(use '-' to read content from stdin)
You can specify address range for each file in the form:
filename:START:END
See description of range option above.
You can omit START or END, so supported variants are:
filename:START: read filename and use data starting from START addr
filename::END read filename and use data till END addr
Use entire file content:
filename
or
filename::
'''
import sys
def main(args=None):
import getopt
output = None
start = None
end = None
write_start_addr = True
overlap = 'error'
if args is None:
args = sys.argv[1:]
try:
opts, args = getopt.gnu_getopt(args, 'hvo:r:',
['help', 'version',
'output=', 'range=',
'no-start-addr', 'overlap=',
])
for o,a in opts:
if o in ('-h', '--help'):
print(USAGE)
return 0
elif o in ('-v', '--version'):
print(VERSION)
return 0
elif o in ('-o', '--output'):
output = a
elif o in ("-r", "--range"):
try:
l = a.split(":")
if l[0] != '':
start = int(l[0], 16)
if l[1] != '':
end = int(l[1], 16)
except (ValueError, IndexError):
raise getopt.GetoptError('Bad range value(s)')
elif o == '--no-start-addr':
write_start_addr = False
elif o == '--overlap':
if a in ('error', 'ignore', 'replace'):
overlap = a
else:
raise getopt.GetoptError('Bad overlap value')
if len(args) == 0:
raise getopt.GetoptError('You should specify file list')
except getopt.GetoptError:
e = sys.exc_info()[1] # current exception
sys.stderr.write(str(e)+"\n")
sys.stderr.write(USAGE+"\n")
return 1
import intelhex
# TODO: move actual merge code into intelhex package as helper function
# and write couple of tests for it.
res = intelhex.IntelHex()
def end_addr_inclusive(addr):
if addr is not None:
return addr + 1
return addr
for f in args:
try:
fname, fstart, fend = intelhex._get_file_and_addr_range(f)
except intelhex._BadFileNotation:
sys.stderr.write('Bad argument: "%s"\n' % f)
sys.stderr.write(USAGE+"\n")
return 1
if fname == '-':
fname = sys.stdin
ih = intelhex.IntelHex(fname)
if (fstart, fend) != (None, None):
ih = ih[fstart:end_addr_inclusive(fend)]
try:
res.merge(ih, overlap)
except intelhex.AddressOverlapError:
e = sys.exc_info()[1] # current exception
sys.stderr.write('Merging: '+fname+"\n")
sys.stderr.write(str(e)+"\n")
return 1
if (start, end) != (None, None):
res = res[start:end_addr_inclusive(end)]
if output is None:
output = sys.stdout
res.write_hex_file(output, write_start_addr)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,14 @@
/* Linker script to configure memory regions. */
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
MEMORY
{
FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 0x30000-0x4000
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x6000
CODE_RAM (rwx) : ORIGIN = 0x800000, LENGTH = 0x6000
}
INCLUDE "nrf_common.ld"

View File

@@ -10,24 +10,32 @@ upload_protocol = stlink
lib_deps =
stevemarple/SoftWire @ ^2.0.9
stevemarple/AsyncDelay @ ^1.1.2
extra_scripts = post:preparefiles.py
[env:Newton_M3_22_BWR]
board_build.ldscript = nrf52811_bootloader.ld
build_flags =
${env.build_flags}
-D BUILD_NEWTON_M3_22_BWR
-Tnrf52811_bootloader.ld
build_src_filter =
+<*>-<uc8179.cpp>+<../hal/Newton_M3_nRF52811/*>
[env:Newton_M3_29_BWR]
board_build.ldscript = nrf52811_bootloader.ld
build_flags =
${env.build_flags}
-D BUILD_NEWTON_M3_29_BWR
-Tnrf52811_bootloader.ld
build_src_filter =
+<*>-<uc8179.cpp>+<../hal/Newton_M3_nRF52811/*>
[env:Newton_M3_75_BWR]
board_build.ldscript = nrf52811_bootloader.ld
build_flags =
${env.build_flags}
-Tnrf52811_bootloader.ld
-D BUILD_NEWTON_M3_75_BWR
build_src_filter =
+<*>-<ssd1619.cpp>+<../hal/Newton_M3_nRF52811/*>

View File

@@ -0,0 +1,24 @@
Import("env")
# Custom HEX from ELF
env.AddPostAction(
"$BUILD_DIR/${PROGNAME}.elf",
env.VerboseAction(" ".join([
"$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
"$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex"
]), "Building $BUILD_DIR/${PROGNAME}.hex")
)
env.AddPostAction(
"$BUILD_DIR/${PROGNAME}.elf",
env.VerboseAction(" ".join([
"python", "make_ota.py", "$BUILD_DIR/${PROGNAME}.hex", "${PIOENV}-ota.bin"
]), "Generating OTA binary ${PIOENV}-ota.bin")
)
env.AddPostAction(
"$BUILD_DIR/${PROGNAME}.elf",
env.VerboseAction(" ".join([
"python", "mergehex.py", "OEPL_bootloader.hex", "$BUILD_DIR/${PROGNAME}.hex", "-o ${PIOENV}-full-flash.hex", "--overlap=replace"
]), "Generating full-flash including bootloader ${PIOENV}-full-flash.hex")
)

View File

@@ -11,6 +11,16 @@
#include "userinterface.h"
#include "wdt.h"
#define FW_LOC 0
#define FW_METADATA_LOC 196608
#define MAGIC1 0xABBAABBA
#define MAGIC2 0xDEADBEEF
struct fwmetadata {
uint32_t fwsize;
uint32_t magic1;
uint32_t magic2;
};
// download-stuff
uint8_t blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0};
static struct blockRequest curBlock = {0}; // used by the block-requester, contains the next request that we'll send
@@ -383,7 +393,7 @@ static void sendXferComplete() {
}
static bool validateBlockData() {
struct blockData *bd = (struct blockData *)blockXferBuffer;
printf("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum);
//printf("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum);
if (bd->size > BLOCK_XFER_BUFFER_SIZE - sizeof(blockData)) {
printf("Impossible data size, we abort here\n");
return false;
@@ -429,15 +439,22 @@ static uint8_t findSlot(const uint8_t *ver) {
return 0xFF;
}
static void eraseUpdateBlock() {
eepromErase(EEPROM_UPDATE_AREA_START, EEPROM_UPDATE_AREA_LEN / EEPROM_ERZ_SECTOR_SZ);
eepromErase(FW_LOC, (FW_METADATA_LOC+EEPROM_ERZ_SECTOR_SZ) / EEPROM_ERZ_SECTOR_SZ);
}
static void eraseImageBlock(const uint8_t c) {
eepromErase(getAddressForSlot(c), EEPROM_IMG_EACH / EEPROM_ERZ_SECTOR_SZ);
}
static void saveUpdateBlockData(uint8_t blockId) {
if (!eepromWrite(EEPROM_UPDATE_AREA_START + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), BLOCK_DATA_SIZE))
if (!eepromWrite(FW_LOC + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), BLOCK_DATA_SIZE))
printf("EEPROM write failed\n");
}
static void saveUpdateMetadata(uint32_t size){
struct fwmetadata metadata;
metadata.magic1 = MAGIC1;
metadata.magic2 = MAGIC2;
metadata.fwsize = size;
eepromWrite(FW_METADATA_LOC, &metadata, sizeof(struct fwmetadata));
}
static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId) {
uint32_t length = EEPROM_IMG_EACH - (sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE));
if (length > 4096)
@@ -550,7 +567,7 @@ static bool getDataBlock(const uint16_t blockSize) {
printf("- COMPLETE\n");
#endif
if (validateBlockData()) {
printf("- Validated\n");
//printf("- Validated\n");
// block download complete, validated
return true;
} else {
@@ -572,6 +589,8 @@ static bool getDataBlock(const uint16_t blockSize) {
return false;
}
uint16_t dataRequestSize = 0;
uint32_t curXferSize = 0;
static bool downloadFWUpdate(const struct AvailDataInfo *avail) {
// check if we already started the transfer of this information & haven't completed it
if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize) {
@@ -582,6 +601,7 @@ static bool downloadFWUpdate(const struct AvailDataInfo *avail) {
memcpy(&(curBlock.ver), &(avail->dataVer), 8);
curBlock.type = avail->dataType;
memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
curXferSize = avail->dataSize;
eraseUpdateBlock();
}
@@ -610,7 +630,7 @@ static bool downloadFWUpdate(const struct AvailDataInfo *avail) {
return true;
}
uint16_t imageSize = 0;
static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) {
// check if we already started the transfer of this information & haven't completed it
if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize) {
@@ -646,7 +666,7 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) {
memcpy(&(curBlock.ver), &(avail->dataVer), 8);
curBlock.type = avail->dataType;
memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
imageSize = curDataInfo.dataSize;
curXferSize = curDataInfo.dataSize;
}
while (curDataInfo.dataSize) {
@@ -680,7 +700,7 @@ static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail) {
memcpy(&eih->version, &curDataInfo.dataVer, 8);
eih->validMarker = EEPROM_IMG_VALID;
eih->id = ++curHighSlotId;
eih->size = imageSize;
eih->size = curXferSize;
eih->dataType = curDataInfo.dataType;
#ifdef DEBUGBLOCKS
@@ -767,8 +787,8 @@ bool processAvailDataInfo(struct AvailDataInfo *avail) {
powerUp(INIT_EEPROM);
wdt60s();
eepromReadStart(EEPROM_UPDATE_AREA_START);
// selfUpdate();
saveUpdateMetadata(curXferSize);
NVIC_SystemReset();
} else {
return false;
}

View File

@@ -0,0 +1,4 @@
Language: Cpp
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 0

3
ARM_Tag_FW/nRF_Bootloader/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.pio
.vscode
core

View File

@@ -0,0 +1,261 @@
#include <Arduino.h>
#include "hal.h"
#include "wdt.h"
int8_t startHFCLK(void) {
if (!isHFCLKstable()) {
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1U;
while (!isHFCLKstable())
;
return 0;
} else {
return -1;
}
}
uint8_t isHFCLKstable(void) {
uint32_t stable = (uint32_t)(CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos) | (CLOCK_HFCLKSTAT_SRC_Xtal << CLOCK_HFCLKSTAT_SRC_Pos);
if (NRF_CLOCK->HFCLKSTAT == stable) {
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
return 1;
} else {
return 0;
}
}
void boardGetOwnMac(uint8_t *mac) {
mac[0] = MAC_ID_1;
mac[1] = MAC_ID_0;
mac[2] = (NRF_UICR->CUSTOMER[0]) & 0xFF;
mac[3] = (NRF_UICR->CUSTOMER[0] >> 8) & 0xFF;
mac[4] = (NRF_UICR->CUSTOMER[0] >> 16) & 0xFF;
mac[5] = (NRF_UICR->CUSTOMER[0] >> 24);
mac[6] = 0;
mac[7] = 0;
uint8_t cksum = 0;
for (uint8_t c = 0; c < 8; c++) {
cksum ^= mac[c];
cksum ^= mac[c] >> 4;
}
mac[0] += cksum & 0x0F;
}
void watchdog_enable(int timeout) {
NRF_WDT->CONFIG = NRF_WDT->CONFIG = (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos) | (WDT_CONFIG_SLEEP_Pause << WDT_CONFIG_SLEEP_Pos);
NRF_WDT->CRV = (32768 * timeout) / 1000;
NRF_WDT->RREN |= WDT_RREN_RR0_Msk;
NRF_WDT->TASKS_START = 1;
NRF_WDT->RR[0] = WDT_RR_RR_Reload;
}
uint32_t sleepMsEntry = 0;
uint32_t loops = 0;
bool interruped = false;
//uint8_t ledcfg[12] = {0b00100010,0x78,0b00100100,5,0x03,0b01000011,1,0xC2,0b1100001,10,10,0};
//uint8_t ledcfg[12] = {0b00010010,0x7D,0,0,0x03,0xE8,0,0,0,0,0,0};
uint8_t ledcfg[12] = {255,0,0,0,0,0,0,0,0,0,0,0};
void setled(uint64_t parta,u_int32_t partb){
ledcfg[0] = parta & 0xFF;
ledcfg[1] = (parta >> 8)& 0xFF;
ledcfg[2] = (parta >> 16)& 0xFF;
ledcfg[3] = (parta >> 24)& 0xFF;
ledcfg[4] = (parta >> 32)& 0xFF;
ledcfg[5] = (parta >> 40)& 0xFF;
ledcfg[6] = (parta >> 48)& 0xFF;
ledcfg[7] = (parta >> 56)& 0xFF;
ledcfg[8] = partb & 0xFF;
ledcfg[9] = (partb >> 8)& 0xFF;
ledcfg[10] = (partb >> 16)& 0xFF;
ledcfg[11] = (partb >> 24)& 0xFF;
}
void resettimer(){
//tell the sleep function to net sleep again
sleepMsEntry = sleepMsEntry - 999999999;
loops = 0;
interruped = true;
}
void flashled(uint8_t color,uint8_t brightnes){
uint8_t colorred = (color >> 5) & 0b00000111;
uint8_t colorgreen = (color >> 2) & 0b00000111;
uint8_t colorblue = color & 0b00000011;
for(uint16_t i = 0;i < brightnes;i++){
digitalWrite(LED_RED, !(colorred >= 7));
digitalWrite(LED_GREEN, !(colorgreen >= 7));
digitalWrite(LED_BLUE, !(colorblue >= 3));
nrf_delay_us(100);
digitalWrite(LED_RED, !(colorred >= 1));
digitalWrite(LED_GREEN, !(colorgreen >= 1));
nrf_delay_us(100);
digitalWrite(LED_RED, !(colorred >= 6));
digitalWrite(LED_GREEN, !(colorgreen >= 6));
digitalWrite(LED_BLUE, !(colorblue >= 1));
nrf_delay_us(100);
digitalWrite(LED_RED, !(colorred >= 2));
digitalWrite(LED_GREEN, !(colorgreen >= 2));
nrf_delay_us(100);
digitalWrite(LED_RED, !(colorred >= 5));
digitalWrite(LED_GREEN, !(colorgreen >= 5));
nrf_delay_us(100);
digitalWrite(LED_RED, !(colorred >= 3));
digitalWrite(LED_GREEN, !(colorgreen >= 3));
digitalWrite(LED_BLUE, !(colorblue >= 2));
nrf_delay_us(100);
digitalWrite(LED_RED, !(colorred >= 4));
digitalWrite(LED_GREEN, !(colorgreen >= 4));
nrf_delay_us(100);
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, HIGH);
}
}
void sleepwithinterrupts(uint32_t sleepinterval){
yield();
sleepMsEntry = millis();
//sometimes we wake up early
while (millis() - sleepMsEntry < sleepinterval){
initRTC0(sleepinterval);
__WFE();
__SEV();
__WFE();
}
}
void ledflashlogic(uint32_t ms){
watchdog_enable(ms + 1000);
uint8_t brightnes = ledcfg[0] >> 4 & 0b00001111;
uint8_t mode = ledcfg[0] & 0b00001111;
//lets not blink for short delays
if(ms < 2000)mode = 15;
//if(mode == 0)sleepwithinterrupts(ms);
if(mode == 1){
uint8_t color = ledcfg[1];
uint32_t ledinerv = (ledcfg[2] << 24 )+ (ledcfg[3] << 16)+ (ledcfg[4] << 8)+ ledcfg[5];
uint32_t sleepinterval = ledinerv;
loops = ms / ledinerv;
if(loops == 0){
loops = 1;
sleepinterval = ms;
}
if(sleepinterval > ms)sleepinterval = ms;
for(uint32_t i = 0;i < loops;i++){
flashled(color,brightnes);
sleepwithinterrupts(sleepinterval);
}
}
else if(mode == 0){
interruped = false;
uint8_t interloopdelayfactor = 100;
u_int8_t loopdelayfactor = 100;
uint8_t c1 = ledcfg[1];
uint8_t c2 = ledcfg[3];
uint8_t c3 = ledcfg[5];
uint8_t loop1delay = (ledcfg[2] >> 4) & 0b00001111;
uint8_t loop2delay = (ledcfg[4] >> 4) & 0b00001111;
uint8_t loop3delay = (ledcfg[6] >> 4) & 0b00001111;
uint8_t loopcnt1 = ledcfg[2] & 0b00001111;
uint8_t loopcnt2 = ledcfg[4] & 0b00001111;
uint8_t loopcnt3 = ledcfg[6] & 0b00001111;
uint8_t ildelay1 = 0;
uint8_t ildelay2 = 0;
uint8_t ildelay3 = 0;
uint8_t grouprepeats = ledcfg[7];
uint32_t fulllooptime1 = loopcnt1 * loop1delay * loopdelayfactor + ildelay1 * interloopdelayfactor;
uint32_t fulllooptime2 = loopcnt2 * loop2delay * loopdelayfactor + ildelay2 * interloopdelayfactor;
uint32_t fulllooptime3 = loopcnt3 * loop3delay * loopdelayfactor + ildelay3 * interloopdelayfactor;
uint32_t looptimesum = fulllooptime1 + fulllooptime2 + fulllooptime3;
int fittingrepeats = (int) ms / looptimesum;
grouprepeats = fittingrepeats;
if(grouprepeats == 0)grouprepeats = 1;
for(int j = 0;j < grouprepeats;j++){
if(!interruped){
for(int i = 0;i < loopcnt1;i++){
flashled(c1,brightnes);
sleepwithinterrupts(loop1delay * loopdelayfactor);
if(interruped)break;
}
sleepwithinterrupts(ildelay1 * interloopdelayfactor);
}
if(!interruped){
for(int i = 0;i < loopcnt2;i++){
flashled(c2,brightnes);
sleepwithinterrupts(loop2delay * loopdelayfactor);
if(interruped)break;
}
sleepwithinterrupts(ildelay2 * interloopdelayfactor);
}
if(!interruped){
for(int i = 0;i < loopcnt3;i++){
flashled(c3,brightnes);
sleepwithinterrupts(loop3delay * loopdelayfactor);
if(interruped)break;
}
sleepwithinterrupts(ildelay3 * interloopdelayfactor);
}
if(interruped)break;
}
}
else sleepwithinterrupts(ms);
}
void sleepForMs(uint32_t ms) {
// Turn everything off for minimal deep sleep current
//radioRxEnable(0);
NRF_CLOCK->TASKS_HFCLKSTOP = 1U;
while ((NRF_CLOCK->HFCLKSTAT & 0x10001) == 0x10001);
Serial.end();
yield();
//led and sleep stuff
ledflashlogic(ms);
//we have to restart the serial
Serial.begin(115200);
Serial.println("wu");
}
#define LF_FREQUENCY 32768UL
#define SECONDS(x) ((uint32_t)((LF_FREQUENCY * (float)((float)x / (float)1000)) + 0.5))
uint32_t wakeUpSeconds = 500;
void initRTC0(uint32_t ms) {
NVIC_DisableIRQ(RTC0_IRQn);
NVIC_ClearPendingIRQ(RTC0_IRQn);
NVIC_SetPriority(RTC0_IRQn, 15);
NRF_RTC0->PRESCALER = 0;
NRF_RTC0->INTENSET = RTC_EVTENSET_COMPARE0_Enabled << RTC_EVTENSET_COMPARE0_Pos;
NRF_RTC0->EVTENSET = RTC_INTENSET_COMPARE0_Enabled << RTC_INTENSET_COMPARE0_Pos;
wakeUpSeconds = ms;
NRF_RTC0->CC[0] = NRF_RTC0->COUNTER + SECONDS(wakeUpSeconds);
NVIC_EnableIRQ(RTC0_IRQn);
NRF_RTC0->TASKS_START = 1;
}
#ifdef __cplusplus
extern "C" {
#endif
void RTC0_IRQHandler(void) {
volatile uint32_t dummy;
if (NRF_RTC0->EVENTS_COMPARE[0] == 1) {
NRF_RTC0->EVENTS_COMPARE[0] = 0;
NRF_RTC0->CC[0] = NRF_RTC0->COUNTER + SECONDS(wakeUpSeconds);
dummy = NRF_RTC0->EVENTS_COMPARE[0];
dummy;
NRF_RTC0->TASKS_STOP = 1;
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,54 @@
#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11
#define eepromByte spiByte
#define eepromPrvSelect() \
do { \
digitalWrite(FLASH_CS, LOW); \
} while (0)
#define eepromPrvDeselect() \
do { \
digitalWrite(FLASH_CS, HIGH); \
} while (0)
#define LED_RED 16
#define LED_GREEN 17
#define LED_BLUE 18
#define BUTTON1 28
#define BUTTON2 29
#define EPD_RST 4
#define EPD_BS 2
#define EPD_CS 6
#define EPD_DC 5
#define EPD_BUSY 3
#define EPD_CLK 19
#define EPD_MOSI 20
#define NFC_I2C_SDA 8
#define NFC_I2C_SCL 9
#define NFC_POWER 10
#define NFC_IRQ 11
#define FLASH_CS 12
#define FLASH_MISO 13
#define FLASH_CLK 14
#define FLASH_MOSI 15
#define EPD_POWER 7
// Can be used as wanted UART RXD and TXD are used for Debug output
#define DBG_RST 21
#define DBG_DL 22
#define DBG_TXD 25
#define DBG_RXD 26
#define DBG_TEST 27
void initRTC0(uint32_t ms);
int8_t startHFCLK(void);
uint8_t isHFCLKstable(void);
void boardGetOwnMac(uint8_t *mac);
void sleepForMs(uint32_t ms);
void setled(uint64_t parta,u_int32_t partb);
void resettimer();

View File

@@ -0,0 +1,32 @@
#ifndef _BOARDHEADER_H_
#define _BOARDHEADER_H_
#include "../../../../tag_types.h"
#include "HAL_Newton_M3.h"
// eeprom map
#define EEPROM_SETTINGS_AREA_START (0x01000UL)
#define EEPROM_SETTINGS_AREA_LEN (0x03000UL)
#define EEPROM_UPDATE_AREA_START (0x04000UL)
#define EEPROM_UPDATE_AREA_LEN (0x10000UL)
#define EEPROM_IMG_START (0x14000UL)
#define EEPROM_IMG_EACH (0x04000UL) // 168*384 / 8 * 2 = 0x3F00
// Mac fixed part
// 7E22CC67B298 (B29)
#define MAC_ID_0 0xB2
#define MAC_ID_1 0x90
// AP mode definitions
#define HAS_EEPROM 1
#define HAS_SCREEN 1
#define AP_EMULATE_TAG 1
// hw types
#define HW_TYPE SOLUM_M3_BWR_29
#define SCREEN_WIDTH 168
#define SCREEN_HEIGHT 384
#endif

View File

@@ -0,0 +1,46 @@
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include <stdbool.h>
#include <stdint.h>
#define EEPROM_WRITE_PAGE_SZ 256 //max write size & alignment
#define EEPROM_ERZ_SECTOR_SZ 4096 //erase size and alignment
//device has 256 sectors, so eepromErase() cannot erase thw whole device...i can live with that
bool eepromInit(void);
void eepromOtpModeEnter(void);
void eepromOtpModeExit(void);
void eepromRead(uint32_t addr, void *dst, uint16_t len) ;
bool eepromWrite(uint32_t addr, const void *src, uint16_t len) ;
bool eepromErase(uint32_t addr, uint16_t numSectors) ;
void eepromDeepPowerDown(void);
uint32_t eepromGetSize(void);
//this is for firmware update use
void eepromReadStart(uint32_t addr) ;
//structures
#define EEPROM_IMG_INPROGRESS (0x7fffffffUL)
#define EEPROM_IMG_VALID (0x494d4721UL)
struct EepromImageHeader { //each image space is 0x17000 bytes, we have space for ten of them
uint64_t version;
uint32_t validMarker;
uint32_t size;
uint8_t dataType;
uint32_t id;
//image data here
//we pre-erase so progress can be calculated by finding the first non-0xff byte
};
#endif

View File

@@ -0,0 +1,10 @@
#ifdef BUILD_NEWTON_M3_29_BWR
#include "../hal/Newton_M3_nRF52811/Newton_M3_nRF52811_29_BWR.h"
#include "../hal/Newton_M3_nRF52811/HAL_Newton_M3.h"
#endif
#ifdef BUILD_NEWTON_M3_75_BWR
#include "../hal/Newton_M3_nRF52811/Newton_M3_nRF52811_75_BWR.h"
#include "../hal/Newton_M3_nRF52811/HAL_Newton_M3.h"
#endif

View File

@@ -0,0 +1,56 @@
#pragma once
#include <Arduino.h>
#define LUTGROUP_NEGATIVE 0
#define LUTGROUP_FASTBLINK 1
#define LUTGROUP_SLOWBLINK 2
#define LUTGROUP_SET 3
#define LUTGROUP_IMPROVE_SHARPNESS 4
#define LUTGROUP_IMPROVE_REDS 5
#define LUTGROUP_UNUSED 6
#define LUTGROUP_UNKNOWN 7
#define LUTGROUP_UNUSED3 8
#define LUTGROUP_UNUSED4 9
#pragma pack(1)
struct vgroup {
uint8_t A : 2;
uint8_t B : 2;
uint8_t C : 2;
uint8_t D : 2;
};
struct lut {
struct vgroup group[7];
};
struct lut10 {
struct vgroup group[10];
} ;
struct group {
uint8_t phaselength[4];
uint8_t repeat;
} ;
struct waveform {
struct lut lut[5];
struct group group[7];
uint8_t gatelevel;
uint8_t sourcelevel[3];
uint8_t dummyline;
uint8_t gatewidth;
} ;
struct waveform10 {
struct lut10 lut[5];
struct group group[10];
uint8_t gatelevel;
uint8_t sourcelevel[3];
uint8_t dummyline;
uint8_t gatewidth;
} ;
#pragma pack(0)

View File

@@ -0,0 +1,30 @@
#pragma once
#include "Arduino.h"
void watchdog_enable(int timeout);
#define wdt10s() \
do \
{ \
watchdog_enable(10000); \
} while (0)
#define wdt30s() \
do \
{ \
watchdog_enable(30000); \
} while (0)
#define wdt60s() \
do \
{ \
watchdog_enable(60000); \
} while (0)
#define wdt120s() \
do \
{ \
watchdog_enable(120000); \
} while (0)

View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@@ -0,0 +1,20 @@
[platformio]
core_dir = $PROJECT_DIR/core
[env]
platform = nordicnrf52@9.6.0
board = nrf52811_dk
framework = arduino
debug_tool = stlink
upload_protocol = stlink
lib_deps =
stevemarple/AsyncDelay @ ^1.1.2
extra_scripts = post:preparefiles.py
[env:nRFBootload]
build_flags =
${env.build_flags}
-D BUILD_NEWTON_M3_29_BWR
build_src_filter =
+<*>-<uc8179.cpp>+<../hal/Newton_M3_nRF52811/*>

View File

@@ -0,0 +1,18 @@
Import("env")
# Custom HEX from ELF
env.AddPostAction(
"$BUILD_DIR/${PROGNAME}.elf",
env.VerboseAction(" ".join([
"$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
"$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex"
]), "Building $BUILD_DIR/${PROGNAME}.hex")
)
env.AddPostAction(
"$BUILD_DIR/${PROGNAME}.elf",
env.VerboseAction(" ".join([
"$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
"$BUILD_DIR/${PROGNAME}.elf", "../Newton_M3_nRF52811/OEPL_bootloader.hex"
]), "Copying bootloader to Newton M3 directory: $BUILD_DIR/${PROGNAME}.hex")
)

View File

@@ -0,0 +1,315 @@
#include <Arduino.h>
#include "eeprom.h"
#include "hal.h"
uint8_t eepromByte(uint8_t data) {
uint8_t temp = 0;
for (uint8_t i = 0; i < 8; i++) {
if (data & 0x80)
digitalWrite(FLASH_MOSI, HIGH);
else
digitalWrite(FLASH_MOSI, LOW);
data = (data << 1);
digitalWrite(FLASH_CLK, HIGH);
temp = (temp << 1);
if (digitalRead(FLASH_MISO))
temp |= 1;
digitalWrite(FLASH_CLK, LOW);
}
return temp;
}
static uint32_t mEepromSize;
static uint8_t mOpcodeErz4K = 0, mOpcodeErz32K = 0, mOpcodeErz64K = 0;
// extern uint8_t * tempBuffer;
uint8_t tempBufferE[320] = {0};
uint32_t eepromGetSize(void) {
return mEepromSize;
}
void eepromReadStart(uint32_t addr) {
eepromPrvSelect();
eepromByte(0x03);
eepromByte(addr >> 16);
eepromByte(addr >> 8);
eepromByte(addr & 0xff);
}
void eepromRead(uint32_t addr, void *dstP, uint16_t len) {
uint8_t *dst = (uint8_t *)dstP;
eepromPrvSelect();
eepromByte(0x03);
eepromByte(addr >> 16);
eepromByte(addr >> 8);
eepromByte(addr & 0xff);
while (len--)
*dst++ = eepromByte(0);
eepromPrvDeselect();
}
static void eepromPrvSimpleCmd(uint8_t cmd) {
eepromPrvSelect();
eepromByte(cmd);
eepromPrvDeselect();
}
static bool eepromPrvBusyWait(void) {
uint8_t val;
eepromPrvSelect();
eepromByte(0x05);
while ((val = eepromByte(0x00)) & 1)
;
eepromPrvDeselect();
return true;
}
static bool eepromWriteLL(uint32_t addr, const void *srcP, uint16_t len) {
const uint8_t *src = (const uint8_t *)srcP;
eepromPrvSimpleCmd(0x06);
eepromPrvSelect();
eepromByte(0x02);
eepromByte(addr >> 16);
eepromByte(addr >> 8);
eepromByte(addr & 0xff);
while (len--)
eepromByte(*src++);
eepromPrvDeselect();
return eepromPrvBusyWait();
}
void eepromDeepPowerDown(void) {
eepromPrvSimpleCmd(0xb9);
}
static void eepromPrvWakeFromPowerdown(void) {
eepromPrvSimpleCmd(0xab);
}
static void eepromPrvSfdpRead(uint16_t ofst, uint8_t *dst, uint8_t len) {
eepromPrvSelect();
eepromByte(0x5a); // cmd
eepromByte(0); // addr
eepromByte(ofst >> 8);
eepromByte(ofst);
eepromByte(0x00); // dummy
while (len--)
*dst++ = eepromByte(0);
eepromPrvDeselect();
}
boolean eepromInit(void) {
uint8_t buf[8];
uint8_t i, nParamHdrs;
eepromPrvWakeFromPowerdown();
// process SFDP
eepromPrvSfdpRead(0, buf, 8);
if (buf[0] != 0x53 || buf[1] != 0x46 || buf[2] != 0x44 || buf[3] != 0x50 || buf[7] != 0xff) {
printf("SFDP: header not found\n");
boolean valid = false;
// try manual ID for chips we know of
eepromPrvSelect();
eepromByte(0x90);
eepromByte(0x00);
eepromByte(0x00);
eepromByte(0x00);
if (eepromByte(0) == 0xc2) { // old macronix chips
valid = true;
mOpcodeErz4K = 0x20;
switch (eepromByte(0)) {
case 0x05: // MX25V512
mEepromSize = 0x00010000ul;
break;
case 0x12: // MX25V4005
mEepromSize = 0x00080000ul;
break;
default:
valid = false;
break;
}
}
eepromPrvDeselect();
return valid;
}
if (buf[5] != 0x01) {
printf("SFDP: version wrong: %u.%d\n", buf[5], buf[4]);
return false;
}
nParamHdrs = buf[6];
if (nParamHdrs == 0xff) // that case is very unlikely and we just do not care
nParamHdrs--;
// now we need to find the JEDEC parameter table header
for (i = 0; i <= nParamHdrs; i++) {
eepromPrvSfdpRead((i * 8) + 8, buf, 8);
if (buf[0] == 0x00 && buf[2] == 0x01 && buf[3] >= 9) {
uint8_t j;
eepromPrvSfdpRead(*(uint16_t *)(buf + 4), tempBufferE, 9 * 4);
if ((tempBufferE[0] & 3) != 1) {
printf("SFDP: no 4K ERZ\n");
break;
}
if (!(tempBufferE[0] & 0x04)) {
printf("SFDP: no large write buf\n");
break;
}
if ((tempBufferE[2] & 0x06)) {
printf("SFDP: addr.len != 3\n");
break;
}
if (!tempBufferE[1] || tempBufferE[1] == 0xff) {
printf("SFDP: 4K ERZ opcode invalid\n");
break;
}
mOpcodeErz4K = tempBufferE[1];
if (tempBufferE[7] & 0x80) {
printf("SFDP: device too big\n");
break;
} else {
uint8_t t;
if ((t = tempBufferE[7]))
mEepromSize = 0x00200000UL;
else if ((t = tempBufferE[6]))
mEepromSize = 0x00002000UL;
else if ((t = tempBufferE[5]))
mEepromSize = 0x00000020UL;
else {
printf("SFDP: device so small?!\n");
break;
}
while (t) {
mEepromSize <<= 1;
t >>= 1;
}
}
// get erase opcodes
for (j = 0x1c; j < 0x24; j += 2) {
uint8_t instr = tempBufferE[j + 1];
if (!instr || instr == 0xff)
continue;
switch (tempBufferE[j]) {
case 0x0c:
if (mOpcodeErz4K != instr) {
printf("4K ERZ opcode disagreement\n");
return false;
}
break;
case 0x0f: // 32K erase
mOpcodeErz32K = instr;
break;
case 0x10: // 64K erase
mOpcodeErz64K = instr;
break;
}
}
/*
printf("EEPROM accepted\n");
printf(" ERZ opcodes: \n");
if (mOpcodeErz4K)
printf(" 4K: %02xh\n", mOpcodeErz4K);
if (mOpcodeErz32K)
printf(" 32K: %02xh\n", mOpcodeErz32K);
if (mOpcodeErz64K)
printf(" 64K: %02xh\n", mOpcodeErz64K);
printf(" Size: 0x%*08lx\n", (uint16_t)&mEepromSize);
*/
return true;
}
}
printf("SFDP: no JEDEC table of expected version found\n");
return false;
}
bool eepromWrite(uint32_t addr, const void *srcP, uint16_t len) {
const uint8_t *src = (const uint8_t *)srcP;
while (len) {
uint16_t lenNow = EEPROM_WRITE_PAGE_SZ - (addr & (EEPROM_WRITE_PAGE_SZ - 1));
if (lenNow > len)
lenNow = len;
if (!eepromWriteLL(addr, src, lenNow))
return false;
addr += lenNow;
src += lenNow;
len -= lenNow;
}
return true;
}
bool eepromErase(uint32_t addr, uint16_t nSec) {
uint8_t now;
if (((uint16_t)addr) & 0x0fff)
return false;
for (; nSec; nSec -= now) {
eepromPrvSimpleCmd(0x06);
eepromPrvSelect();
if (nSec >= 16 && !(uint16_t)addr && mOpcodeErz64K) { // erase 64K
eepromByte(mOpcodeErz64K);
now = 16;
} else if (nSec >= 8 && !(((uint16_t)addr) & 0x7fff) && mOpcodeErz32K) { // erase 32K
eepromByte(mOpcodeErz32K);
now = 8;
} else { // erase 4K
eepromByte(mOpcodeErz4K);
now = 1;
}
eepromByte(addr >> 16);
eepromByte(addr >> 8);
eepromByte(addr);
eepromPrvDeselect();
if (!eepromPrvBusyWait())
return false;
addr += (EEPROM_ERZ_SECTOR_SZ * now);
}
return true;
}
void eepromOtpModeEnter(void) {
eepromPrvSimpleCmd(0xb1);
}
void eepromOtpModeExit(void) {
eepromPrvSimpleCmd(0xc1);
}

View File

@@ -0,0 +1,172 @@
#include <Arduino.h>
#include <AsyncDelay.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "eeprom.h"
#include "hal.h"
#include "wdt.h"
#define UICR_BASE 0x10001000
#define UICR_VTOR_OFFSET 0x14
#define FW_LOC 0
#define FW_METADATA_LOC 196608
#define MAGIC1 0xABBAABBA
#define MAGIC2 0xDEADBEEF
#define BOOTLOADER_SIZE 16384
#define FLASH_SIZE 196608
#define FLASH_PAGE_SIZE 4096
#define APP_ENTRY BOOTLOADER_SIZE
struct fwmetadata {
uint32_t fwsize;
uint32_t magic1;
uint32_t magic2;
};
extern "C" int _write(int file, char *ptr, int len) {
(void)file; /* Not used, avoid warning */
Serial.write(ptr, len);
return len;
}
bool fwFlashPending() {
struct fwmetadata metadata;
eepromRead(FW_METADATA_LOC, &metadata, sizeof(struct fwmetadata));
if (metadata.magic1 == MAGIC1 && metadata.magic2 == MAGIC2) {
return true;
} else {
return false;
}
}
uint32_t fwFlashPendingSize() {
struct fwmetadata metadata;
eepromRead(FW_METADATA_LOC, &metadata, sizeof(struct fwmetadata));
return metadata.fwsize;
}
void writeFlashPage(uint32_t address, uint8_t *source) {
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
}
NRF_NVMC->ERASEPAGE = address;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
}
// write bytes
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
}
for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i += 4) {
uint32_t data_word = *((uint32_t *)&(source[i]));
*((uint32_t *)(address + i)) = data_word;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
}
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
}
}
void removeFwFlashPending() {
struct fwmetadata metadata;
metadata.magic1 = 0;
metadata.magic2 = 0;
metadata.fwsize = 0;
eepromWrite(FW_METADATA_LOC, &metadata, sizeof(struct fwmetadata));
}
void setupPortsInitial() {
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, HIGH);
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
pinMode(BUTTON1, INPUT_PULLUP);
pinMode(BUTTON2, INPUT_PULLUP);
pinMode(NFC_POWER, INPUT_PULLDOWN);
pinMode(NFC_IRQ, INPUT_PULLDOWN);
pinMode(FLASH_MISO, INPUT);
pinMode(FLASH_CLK, OUTPUT);
pinMode(FLASH_MOSI, OUTPUT);
digitalWrite(FLASH_CS, HIGH);
pinMode(FLASH_CS, OUTPUT);
}
typedef void (*app_reset_handler_t)(void);
void jumpToApp(void) {
// Disable interrupts while we configure the vector table
__disable_irq();
SCB->VTOR = APP_ENTRY;
__set_MSP(*(uint32_t *)APP_ENTRY);
app_reset_handler_t app_reset_handler = (app_reset_handler_t) * (uint32_t *)(APP_ENTRY + 4);
__enable_irq();
app_reset_handler();
}
void ledBlink(uint8_t led) {
digitalWrite(led, LOW);
delay(3);
digitalWrite(led, HIGH);
}
void performFWFlash() {
uint32_t filesize = fwFlashPendingSize();
for (uint8_t c = 0; c < 15; c++) {
ledBlink(LED_BLUE);
delay(70);
}
if ((filesize < 8192) || (filesize > (FLASH_SIZE - BOOTLOADER_SIZE))) {
for (uint8_t c = 0; c < 20; c++) {
ledBlink(LED_RED);
delay(100);
}
return;
}
printf("Flashing %lu bytes from SPI EEPROM\n", filesize);
uint8_t *eepromdata = (uint8_t *)malloc(FLASH_PAGE_SIZE);
for (uint32_t offset = 0; offset < filesize; offset += FLASH_PAGE_SIZE) {
eepromRead(FW_LOC + offset, eepromdata, FLASH_PAGE_SIZE);
// dump(eepromdata, FLASH_PAGE_SIZE);
writeFlashPage(APP_ENTRY + offset, eepromdata);
printf("\rFlashing page %lu...", offset);
ledBlink(LED_BLUE);
}
printf("\nAll done, booting OEPL!\n");
digitalWrite(LED_GREEN, LOW);
delay(500);
digitalWrite(LED_GREEN, HIGH);
}
void setup() {
Serial.begin(115200);
delay(300);
printf("OEPL-BOOT\n");
setupPortsInitial();
eepromInit();
if (fwFlashPending()) {
performFWFlash();
removeFwFlashPending();
} else {
ledBlink(LED_GREEN);
}
jumpToApp();
}
void loop() {
}

View File

@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html