No changes between revisions
/Designs/Data_loggers/GPSRL03A/glg.elf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:executable
+*
\ No newline at end of property
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/Designs/Data_loggers/GPSRL03A/glg.hex
0,0 → 1,677
:100000000C9441000C945E000C945E000C945E0015
:100010000C945E000C945E000C945E000C945E00E8
:100020000C945E000C945E000C945E000C9418031B
:100030000C945E000C945E000C945E000C945E00C8
:100040000C945E000C945E000C94B5000C945E0061
:100050000C945E000C9460000C945E000C945E00A6
:100060000C945E000C945E00244750524D430024D3
:100070004750474741002E6C6F6700244750524D50
:10008000430011241FBECFEFD4E0DEBFCDBF11E08F
:10009000A0E0B1E0E8E2FAE202C005900D92AC30D7
:1000A000B107D9F714E0ACE0B1E001C01D92AD3466
:1000B000B107E1F70E9435010C9412150C94000071
:1000C0001F920F920FB60F9211242F933F938F938D
:1000D000209178003091790080917C00203D31059D
:1000E00070F480910F018F3030F080916F0181604A
:1000F00080936F0106C08F5F80930F0102C0109242
:100100000F0181E02C32380770F080910E018F30A2
:1001100030F080916F018E7F80936F0106C08F5FFA
:1001200080930E0102C010920E013093750120934E
:10013000740182E480937C0080917C0030931002F3
:1001400020930F0281E480937C008FED80937A00EE
:100150008F913F912F910F900FBE0F901F90189588
:1001600060E070E081EA96E308951F920F920FB667
:100170000F9211248F939F93EF93FF939091C6005A
:1001800080917801863988F48F5F8093780180911F
:100190007601E82FF0E0EA58FE4F93838F5F8639AF
:1001A00008F080E08093760105C080916F01826045
:1001B00080936F01FF91EF919F918F910F900FBEF0
:1001C0000F901F90189590E052E848E901C090E028
:1001D00080916F0180FD46C0309177018091780158
:1001E000882311F420E013C0E32FF0E0EA58FE4F1B
:1001F0002381E32FEF5FF894809178018150809301
:1002000078017894E63908F0E0E0E0937701809196
:100210006F0181FF14C0F8941092C1001092770111
:1002200010927601109278015093C4004093C1005F
:1002300080916F018D7F80936F017894C8CF2223C6
:1002400039F2992319F4243209F0C2CFE92FF0E0F2
:10025000E35EFE4F20839F5F2A3029F0923508F03D
:10026000B6CFB6CF90E0892F0895A2E0B0E0EBE3DF
:10027000F1E00C94C7148DE085B98EE284B98FE368
:1002800088B917B88EEA8BB982E58AB980E58CBD4A
:1002900081E08DBD83ED90E3909389008093880089
:1002A0008AE08093810082E080936F0082E187BDC5
:1002B00082E484BD81E480937C008FED80937A009A
:1002C00078946DE272E080E00E947F09EE24FF24C2
:1002D00053E0A52E45E0B42E3DE1C32E31E0D32EF0
:1002E0004E010894811C911C28E1222E21E0322E1F
:1002F00090E7692E91E0792E80E0482E81E0582E1B
:100300001092C100299884E680931C0194E68091A4
:100310006F0180FF02C090931C0180911C01882313
:10032000B1F7299A8FEF80931C011FEF80916F0125
:1003300080FD05C080E00E94950F81FF02C01093F0
:100340001C0180911C01882389F791E00EC0A5BC97
:10035000B0921C0180911C018823E1F715BCB0927A
:100360001C0180911C018823E1F7915080F7F894DB
:100370001092C100109277011092760110927801CC
:1003800082E88093C40088E98093C10080916F0166
:100390008D7F80936F01789402C0EE24FF240E9429
:1003A000E300882309F4ACCF2BE730E0ADE1B1E006
:1003B000F9012F5F3F4F9491992329F08C91981761
:1003C00071F41196F5CFEDE1F1E082E09081913288
:1003D00020F331969C32D1F78150C1F77F01E114AF
:1003E000F104E9F2F70180818134C9F6EDE1F1E031
:1003F00089E09081913208F4F0C031969C32C9F7BF
:100400008150B9F77F01309709F4E7C08481958165
:1004100090931E0180931D0182819381909320010E
:1004200080931F018081918190932201809321010B
:1004300066E770E083E291E00E948F1142E16DE196
:1004400071E081E192E00E94D709892B09F0C7C0D1
:1004500040911B0250911C0260911D0270911E027E
:1004600081E192E00E943C05892B09F0B8C092E03E
:100470000EC0A5BCB0921C0180911C018823E1F73D
:1004800015BCB0921C0180911C018823E1F79150AA
:1004900080F785C02FE630E0ADE1B1E0F9012F5FD4
:1004A0003F4F9491992389F08C91981709F0AEC031
:1004B0001196F4CF1196F9012F5F3F4F9491992334
:1004C00021F08C919817B1F357C0042F10E09401DC
:1004D000A8016DE171E081E192E00E940E07892B95
:1004E00009F064C089819A810817190709F05EC074
:1004F0004AE050E068E171E08091740190917501EB
:100500000E94B3114AE050E060E771E080910F0271
:10051000909110020E94B3117F926F923F922F929E
:100520005F924F92DF92CF920E94D411F601019018
:100530000020E9F73197EC19FD099401AF016DE155
:1005400071E081E192E00E940E072DB73EB7285F6F
:100550003F4F0FB6F8943EBF0FBE2DBF892B41F51C
:10056000D6010D900020E9F71197AC19BD098981DA
:100570009A81A817B907E1F480916F0182FF0FC03B
:1005800081E192E00E94A906892B11F096E028C033
:10059000F89480916F018B7F80936F0178940E9413
:1005A000E300482F882309F075CF35C095E018C0C7
:1005B00098E016C0A5BC32E330931C0180911C0169
:1005C0008823E1F715BC82E380931C0180911C0114
:1005D0008823E1F7915070F793CE93E001C094E047
:1005E0001092C100299833E029E135BD20931C0108
:1005F00080911C018823E1F715BC20931C01809198
:100600001C018823E1F7915081F7FFCF28E630E005
:10061000ADE1B1E050CF1092C100299881E192E0A4
:100620000E940007892B11F097E0DACF91E0D2CF3A
:100630001F920F920FB60F9211242F938F939F93B7
:1006400080911C01882319F0815080931C018091B6
:100650000C0190910D01019690930D0180930C0176
:100660008055964448F010920D0110920C01809133
:100670006F01846080936F010E946F119F918F9131
:100680002F910F900FBE0F901F901895FC010097AF
:1006900069F0808191818617970741F480E00E947C
:1006A000950F282F30E02170307002C02CE030E030
:1006B000C9010895A0E0B0E0E0E6F3E00C94CB14AB
:1006C0004B015C01C0911001D0911101CC80DD8003
:1006D000EE80FF80C616D706E806F90609F44EC07C
:1006E0008F8D8823A1F180E2682E712C6C0E7D1E07
:1006F00001E0A7019601B30180E00E94FB0F892B66
:10070000D9F51F8E8C899D89A0E0B0E028853985B8
:100710004A855B85820F931FA41FB51FC816D90693
:10072000EA06FB06A0F41E8D10C08C899D89A0E00E
:10073000B0E0C80ED91EEA1EFB1E01E0A70196011B
:10074000B30180E00E94FB0F1150123070F781144A
:100750009104A104B10491F0BE01605E7F4F01E0FD
:10076000A501940180E00E949C0F892B29F48C82C2
:100770009D82AE82BF8202C080E001C081E0CDB721
:10078000DEB7EEE00C94E714A0E0B0E0EAECF3E0B2
:100790000C94CB14EC014B01E0901001F09011018E
:1007A000F701A084B184C284D384848D813021F088
:1007B000823009F072C05AC08E01000F111F0C0F59
:1007C0001D1F16950795B801672F7727669580E05E
:1007D00090E06A0D7B1D8C1D9D1D0E945A0388238D
:1007E00009F45BC0D801B17051E0652E712C6C2208
:1007F0007D22C0FF0AC0F701EA0FFB1F80A18F70A6
:10080000982D9295907F982B01C0982DAE0DBF1D0D
:10081000FD0190A3E801219681E0F701878FBE01D9
:10082000672F7727669580E090E06A0D7B1D8C1D11
:100830009D1D0E945A03882381F1DE01B17061146D
:10084000710439F034E0969487943A95E1F7982D45
:1008500008C0F701EA0FFB1F90A1907F892D8F70D0
:10086000982BAE0DBF1DFD0190A313C06D2F7727F0
:1008700080E090E06A0D7B1D8C1D9D1D0E945A0337
:10088000882359F0CC0FDD1FD170CE0DDF1D99A24A
:1008900088A281E0F701878F01C080E0CDB7DEB785
:1008A000EEE00C94E714A0E0B0E0E9E5F4E00C948D
:1008B000CE148C01E0901001F0901101823091056E
:1008C00008F467C0E7018E899F890817190708F0A7
:1008D00060C0A884B984CA84DB848C8D813021F007
:1008E000823009F056C040C0E801CC0FDD1FC00FB8
:1008F000D11FD695C795BE01672F7727669580E0F3
:1009000090E06A0D7B1D8C1D9D1D0E945A0388235B
:1009100009F43FC0FE01F170EE0DFF1D90A021967D
:10092000BE01672F7727669580E090E06A0D7B1DFA
:100930008C1D9D1D0E945A03882359F1292D30E0FA
:10094000D170EC0EFD1EF70190A180E0282B392B11
:1009500000FF07C0F90194E0F695E7959A95E1F755
:100960001AC0F901FF7017C0612F772780E090E06F
:100970006A0D7B1D8C1D9D1D0E945A03882349F022
:10098000000F111F1170E00EF11EE701E8A1F9A19F
:1009900002C0E1E0F0E0CF01CDB7DEB7EBE00C94B0
:1009A000EA14A0E0B0E0E7EDF4E00C94CF147C0191
:1009B000C0901001D0901101F601A688B788009769
:1009C00049F4008D118D0230110588F00A151B05C0
:1009D00070F40FC00E9453049C018230910508F40A
:1009E00040C08A159B0508F441C0870102C001E0A0
:1009F00010E0E8012196CA15DB0528F00230110548
:100A000098F1C2E0D0E0CE010E9453049C0100970F
:100A100039F08130910551F1C017D10759F724C041
:100A20001C2F0D2F6FEF7FEFCE010E94C403882390
:100A3000C1F0E114F10431F0BE01C7010E94C4030A
:100A4000882379F0F601108F018F828D938DFFEF4F
:100A50008F3F9F0721F00197F601938F828F9E01B0
:100A600005C021E030E002C020E030E0C901CDB790
:100A7000DEB7EAE00C94EB14A0E0B0E0E2E4F5E0CD
:100A80000C94CB14EC017A018B016C807D80688121
:100A90007981C3010E9446034C01009709F0D6C03A
:100AA0008A8187FDD0C0AA84BB84CC84DD84AE1447
:100AB000BF04C006D10610F481FF02C057016801CF
:100AC0001E821F821886198681E08B83A114B104CF
:100AD000C104D10409F49DC06E857F85611571053F
:100AE00071F480E090E00E94D104BC018130910556
:100AF00009F4A6C09F878E87009709F48AC0F30186
:100B0000858DE82EFF2400E010E0F9E0EE0CFF1CDC
:100B1000001F111FFA95D1F7798B688BEA14FB043B
:100B20000C051D0558F58A8181FF04C0CB010E9488
:100B3000D10403C0CB010E945304BC010097E1F033
:100B40008130910509F47CC0F30186899789681783
:100B5000790708F075C08E819F81A885B9858E0DB3
:100B60009F1DA01FB11F8E839F83A887B987AE18D2
:100B7000BF08C00AD10AD0CF57016801D601C5010C
:100B80000197A109B109E9E0B695A79597958795D1
:100B9000EA95D1F7F82E00911001109111016250E1
:100BA0007040F8018689978902976817790728F0BD
:100BB00020E030E040E050E014C080E090E0F80138
:100BC000258D30E040E050E00E9486149B01AC018E
:100BD000F80180899189A289B389280F391F4A1F9A
:100BE0005B1F2F0D311D411D511D2A8B3B8B4C8BE3
:100BF0005D8BF301858D8F198B838E819F81A885F5
:100C0000B9858A0D9B1DAC1DBD1D8E839F83A88752
:100C1000B9876A8161FF1AC02E813F814885598555
:100C20008A859B85AC85BD8582179307A407B50788
:100C300068F42A873B874C875D8760626A8306C0B9
:100C40008A8180688A8368E0862E912CC401CDB7A2
:100C5000DEB7EEE00C94E714EF92FF920F931F9330
:100C6000CF93DF938C01C0911001D0911101FC0151
:100C7000E280F3800894E11CF11CC7018F70907032
:100C8000892B09F05BC082859385A485B585019683
:100C9000A11DB11D82879387A487B58740855185A3
:100CA0004115510539F48A819B81E816F90608F44B
:100CB00045C049C08D8D90E001979701A4E036951D
:100CC0002795AA95E1F782239323892BB9F5CA01C9
:100CD0000E945304BC0182309105A8F18E899F893E
:100CE0006817790780F5F80171876087C091100156
:100CF000D0911101625070408E899F8902976817C8
:100D0000790728F020E030E040E050E012C080E0B9
:100D100090E02D8D30E040E050E00E9486149B0171
:100D2000AC0188899989AA89BB89280F391F4A1F74
:100D30005B1FF8012287338744875587F801F382C8
:100D4000E28281E001C080E0CDB7DEB7E6E00C943E
:100D5000EF14EF92FF920F931F93CF93DF93EC0169
:100D6000688179818C819D810E9446037C01009776
:100D700009F040C08A8185FF3DC06E897F89888DDA
:100D8000998D0E945A03882391F10A8D1B8DF801D9
:100D90008385806283878A859B85AC85BD85848FAA
:100DA000958FA68FB78F8E859F85938F828F0E9498
:100DB000B000F801668B778B808F918F8A818F7D51
:100DC0008A83E0911001F091110181E0878F60E04A
:100DD00070E080E090E00E945A03882341F040E0F8
:100DE00050E063E080E00E947710892B19F0B8E0B2
:100DF000EB2EF12CC701CDB7DEB7E6E00C94EF1473
:100E0000CF93DF93EC010E94A9069C01009711F497
:100E10001D821C82C901DF91CF910895A0E0B0E04E
:100E2000E4E1F7E00C94C814EC01162F072F7A01C7
:100E30003901AC80BD80F90111821082688179810D
:100E4000C5010E9446034C01009709F03BC18A810D
:100E500087FD35C181FD04C036E0832E912C32C15F
:100E60002A853B854C855D85C701A0E0B0E0820FF7
:100E7000931FA41FB51F82179307A407B50708F493
:100E800021C1812F902F9C016901412C22E0522E1B
:100E900033243394F8C02E813F8148855985DA0187
:100EA000C9019170A070B0700097A105B10509F05B
:100EB000B1C08B8181508B83882349F02A893B897B
:100EC0004C895D892F5F3F4F4F4F5F4F51C02115B8
:100ED00031054105510569F46E857F856115710500
:100EE00089F480E090E00E94D104BC019F878E8746
:100EF00005C0888999890E94D104BC0161157105DA
:100F000009F4C5C06130710509F4D6C0F5018689C0
:100F100097896817790708F0CFC0798B688B0091A3
:100F200010011091110162507040F8018689978973
:100F300002976817790728F020E030E040E050E0A1
:100F400014C080E090E0F801258D30E040E050E0F2
:100F50000E9486149B01AC01F80180899189A289C5
:100F6000B389280F391F4A1F5B1FF501858D8B83BD
:100F70002A8B3B8B4C8B5D8B0F2D069561F16B8122
:100F8000102F601708F4162F012FB60180E00E9481
:100F9000FB0F892B09F090C08B818F5F811B8B83A6
:100FA000812F90E001979C01442737FD4095542FF5
:100FB0008C010F5F1F4F8A899B89AC89BD89820F85
:100FC000931FA41FB51F8A8B9B8BAC8BBD8B102FDF
:100FD0000027110F3EC02E813F81488559858A85A3
:100FE0009B85AC85BD85281739074A075B0790F0BC
:100FF00060E070E080E090E00E945A03882309F4EA
:101000005BC08A899B89AC89BD89F50184839583FE
:10101000A683B7836A897B898C899D890E945A033C
:10102000882309F449C02E813F813170C201821B9F
:10103000930B87018E159F0508F48C01205E3F4FAE
:101040002A0D3B1DA801B601C9010E94A311F5019B
:10105000378EC00ED11EC801A0E0B0E02E813F81C6
:1010600048855985280F391F4A1F5B1F2E833F83F0
:1010700048875987F30180819181800F911F918367
:101080008083E01AF10AE114F10409F004CF2E8103
:101090003F81488559858A859B85AC85BD858217AA
:1010A0009307A407B50720F42A873B874C875D8701
:1010B0008A8180628A8306C08A8180688A8388E008
:1010C000882E912CC401CDB7DEB7E1E10C94E41475
:1010D000A0E0B0E0EEE6F8E00C94C914EC01162FA5
:1010E000072F7A0139018C809D80F90111821082CD
:1010F00068817981C4010E9446035C01009709F070
:10110000F8C08A8187FDF2C080FD04C076E0A72E7A
:10111000B12CEFC02A853B854C855D858E819F81F2
:10112000A885B985281B390B4A0B5B0BC701A0E0CA
:10113000B0E0281739074A075B0708F47901812FC7
:10114000902F9C016901412C62E0562EC7C02E8170
:101150003F8148855985DA01C9019170A070B0704E
:101160000097A105B10509F084C08B8181508B8364
:10117000882349F02A893B894C895D892F5F3F4F3D
:101180004F4F5F4F43C0211531054105510519F4FB
:101190006E857F8505C0888999890E945304BC01AA
:1011A0006230710508F49FC0F40186899789681739
:1011B000790708F098C0798B688B00911001109125
:1011C000110162507040F80186899789029768176B
:1011D000790728F020E030E040E050E014C080E0E3
:1011E00090E0F801258D30E040E050E00E94861448
:1011F0009B01AC01F80180899189A289B389280FEC
:10120000391F4A1F5B1FF401858D8B832A8B3B8B13
:101210004C8B5D8B0F2D069561F16B81102F601744
:1012200008F4162F012FB60180E00E949C0F892B35
:1012300009F059C08B818F5F811B8B83812F90E0D8
:1012400001979C01442737FD4095542F8C010F5F77
:101250001F4F8A899B89AC89BD89820F931FA41F68
:10126000B51F8A8B9B8BAC8BBD8B102F0027110F6A
:101270001BC06A897B898C899D890E945A038823B7
:1012800091F18E819F8191709201281B390B87010A
:101290002E153F0508F489018096880D991DA80137
:1012A000BC01C6010E94A311C00ED11EC801A0E05E
:1012B000B0E02E813F8148855985280F391F4A1F8C
:1012C0005B1F2E833F8348875987F301808191817B
:1012D000800F911F91838083E01AF10AE114F104D9
:1012E00009F035CF06C08A8180688A8348E0A42E41
:1012F000B12CC501CDB7DEB7E0E10C94E514CF9376
:10130000DF93FB01882319F025E030E01DC0A09198
:101310001001B091110170931101609310011097A9
:1013200041F080E292E0ED019C01199221503040A1
:10133000E1F7309739F080E292E0DF01EC011D9295
:101340002197E9F720E030E0C901DF91CF910895BE
:101350000F93CF93DF939B01AC01C0911001D0910B
:101360001101BE01605E7F4F01E080E00E949C0F92
:10137000892BC1F4C25EDD4F88819981CE51D24064
:1013800085559A4A79F443E050E067E071E0CE0178
:101390008A5A9F4F0E9496119C0180E0232B19F0DE
:1013A00081E001C082E0DF91CF910F910895ADE11E
:1013B000B0E0EDEDF9E00C94C7149D8F8C8F3B01EC
:1013C0008090100190901101FC011582148203C0DD
:1013D0000894611C711CF30180818032C9F38F3243
:1013E00019F40894611C711C8114910409F417C14B
:1013F000F42FFF71FB8F142F1E71F401848D88234D
:1014000059F080E00E94950F80FD06C0112309F479
:10141000ABC382FD07C1A8C380E292E0F4019C0146
:10142000119221503040E1F780E00E94B80E80FF19
:1014300003C021E030E08BC3112311F082FDF2C024
:1014400060E070E080E090E00E94A809813021F027
:10145000EE24FF2487011EC082EE91E0880E991EC3
:10146000F40180812EE13EEF820E931E882309F461
:10147000DCC086EE91E0880E991EF401E080F180D8
:10148000028113812AE13EEF820E931EC801B7014B
:101490000E94A809882309F0C8C0F40183A594A577
:1014A0008050924009F0C1C0F40186A997A9BC01FF
:1014B00080E090E0611571058105910569F424E4EF
:1014C00030E0820E931EF4016081718182819381EC
:1014D0002CEB3FEF820E931EF401758B648B20A9D9
:1014E000268F30E040E050E00E9486145B016C01E2
:1014F000F40186A597A5A0E0B0E0E80EF91E0A1F4A
:101500001B1FE086F1860287138785A5858F21A999
:1015100032A93383228383A994A97C0100E010E0DF
:10152000E114F1040105110569F480E490E0880EEE
:10153000991EF401E080F1800281138180EC9FEF1D
:10154000880E991EF40186A597A5A0E0B0E0E81AE0
:10155000F90A0A0B1B0BEA18FB080C091D09A4E089
:1015600036952795AA95E1F7C901A0E0B0E0E81A01
:10157000F90A0A0B1B0B258D30E040E050E0C80152
:10158000B7010E94A5142E5F3F4F4F4F5F4FF401EC
:10159000378B268B283FFFE03F07F0E04F07F0E056
:1015A0005F0710F461E006C0285F3F4F40405040A5
:1015B000E0F562E0F4012085318542855385D6014E
:1015C000C501820F931FA41FB51F84879587A68727
:1015D000B7878281938174E0969587957A95E1F734
:1015E000A0E0B0E0820F931FA41FB51F8A0D9B1DC2
:1015F000AC1DBD1D808B918BA28BB38B648F8FEF45
:101600009FEF938F828F8091120190911301019629
:10161000909313018093120191838083A5C22AE0E5
:1016200030E095C229E030E092C22BE030E08FC27A
:101630002E010894411C511C92E0292E312C4BE0C4
:1016400050E060E270E0C2010E94AC1120E048E08E
:1016500090E038E102C028E04BE0F30111913F0136
:10166000112311F01F3249F4222309F4C7C0392392
:101670003C87113009F044C0C1C0113208F4BEC02B
:101680001F3709F4BBC01E3241F490FDB7C02223BE
:1016900009F4B4C02930F8F2B1C0123209F4AEC076
:1016A0001A3220F11D3208F4A9C01A33F8F01034B0
:1016B00008F4A4C090FD1AC01C3709F49FC0812F04
:1016C0008B55833008F49AC0865E8A3128F44830FE
:1016D00011F4377F01C03F7E812F81568A3130F46B
:1016E0001052483011F4986001C09061241708F03E
:1016F00085C09E7FF201E20FF11D10832F5FADCFF9
:101700006F89788D898D9A8D0E945A03882331F4D0
:1017100090E09C01590128E030E084C02F85388991
:101720002F70307085E0220F331F8A95E1F7F601A4
:10173000E20FF31F80A18823E1F0853EA1F000E2D3
:10174000A02EB12CA20EB31EAC0CBD1CF5018385DE
:10175000082F83FD08C04BE050E0B201C5010E9494
:101760009611009751F0CE010D960E942C06882309
:1017700039F6112309F049C04FC0112319F420E0B4
:1017800030E050C004FF41C0F501E28CF38CFE8ACA
:10179000ED8A0091100110911101B7016250704063
:1017A000F8018689978902976817790728F020E061
:1017B00030E040E050E014C080E090E0F801258D7A
:1017C00030E040E050E00E9486149B01AC01F8013B
:1017D00080899189A289B389280F391F4A1F5B1F0D
:1017E000FC8AEB8A2F8B388F498F5A8F388A2F8645
:1017F00026CF20E030E0AA24BB2414C080E090E093
:101800009C01590124E030E00DC080E090E09C0193
:10181000590123E030E006C080E090E09C015901CE
:1018200022E030E0FB8D4F2F50E0CA018C719070A8
:10183000892B09F441C12115310509F4D6C02230A4
:10184000310509F084C160901001709011010B897D
:101850001C890115110551F11E8B0D8BB8016250C9
:101860007040F3018689978902976817790728F0F5
:1018700020E030E040E050E014C080E090E0F30170
:10188000258D30E040E050E00E9486149B01AC01C1
:10189000F30180899189A289B389280F391F4A1FD2
:1018A0005B1F2F8B388F498F5A8F09C0F3018485B6
:1018B0009585A685B7858F8B988FA98FBA8F188A43
:1018C0001F86BDE0EB2EF12CEC0EFD1E6F89788D8E
:1018D000898D9A8D0E945A03882309F433C1EF85BC
:1018E000F889EF70F070A5E0EE0FFF1FAA95E1F701
:1018F000B0965301AE0EBF1EB097E60DF71D80A146
:10190000882309F44CC1853E09F449C1C7010E94EE
:101910002C068823D9F60115110509F410C18D890B
:101920009E890E94D1048C01009709F408C181307E
:10193000910509F407C160E070E080E090E00E944A
:101940005A03882309F4FEC0A0901001B090110141
:10195000B80162507040F50186899789029768172F
:10196000790720F0CC24DD24760114C080E090E0DB
:10197000F501258D30E040E050E00E9486146B01B7
:101980007C01F50180899189A289B389C80ED91E8D
:10199000EA1EFB1EF301C482D582E682F782E0E2F2
:1019A000AE2EB12CA60CB71C80E092E0F5019C0194
:1019B000119221503040E1F7F301158D10C001E084
:1019C000A7019601B50180E00E94FB0F892B09F069
:1019D000B9C00894C11CD11CE11CF11C1150112389
:1019E00071F781E0F301878FDAC0F2FF03C027E0CF
:1019F00030E0ADC0A114B10409F4A1C0F5018385A4
:101A0000817109F09CC043FF42C0C28CD38C138EFD
:101A1000128E148E158E168E178E81E0F401878F2C
:101A20002480358046805780E0901001F0901101AD
:101A300086011CC0C8010E9453043C0181309105FD
:101A400009F480C060E070E0C8010E94C4038823EC
:101A500009F478C0F701828D938DFFEF8F3F9F07C8
:101A600021F00196F701938F828F830102301105D7
:101A700008F472C0F7018689978908171907D0F210
:101A80006BC00894C108D108F401D18EC08EFB8DC3
:101A9000F3FF22C080E2F50183870E94B000F501C8
:101AA000668B778B808F918F66877787808B918B02
:101AB00081E0F401878F10C02115310509F047C07E
:101AC000A114B10409F441C0F501838584FD3DC032
:101AD00041FF02C080FD33C0F40184819581A6815D
:101AE000B781EC8DFD8D868B978BA08FB18FB38ED8
:101AF000A28E2B8D2283F501828D938DEC8DFD8D31
:101B000097878687F501848D958DA68DB78DEC8D91
:101B1000FD8D82879387A487B587168217821086EA
:101B2000118681E0838395828482F4018081918192
:101B3000EC8DFD8D9183808320E030E008C026E0AD
:101B400030E005C028E030E002C022E030E0C9010A
:101B50006D96E2E10C94E314C201B1010E945A03B4
:101B6000882309F08ECFEECFC0901001D0901101E4
:101B7000F601848595851C8A1B8A1E8A1D8AA0E031
:101B8000B0E08F8B988FA98FBA8F188A1F86DA8A58
:101B9000C98AF3018081882309F04ACD2ACE80E2E8
:101BA000F50111928A95E9F7D501FE0131968BE096
:101BB00001900D928150E1F78C85F5018487FB8DB2
:101BC000F860FB8F64CFFC018AE0809315019FEFE2
:101BD0009EBD0DB407FEFDCF8EB58F3F29F48091D9
:101BE00015018823A9F722C08E3F01F59FEF9EBD06
:101BF0000DB407FEFDCF8EB580839EBD0DB407FEEC
:101C0000FDCF8EB581836250704011F03296EFCFD8
:101C10008FEF8EBD0DB407FEFDCF8EB58FEF8EBD5D
:101C20000DB407FEFDCF8EB581E0089580E00895E4
:101C3000FC0182E3809316018FEF8EBD0DB407FE89
:101C4000FDCF8EB59FEF9EBD0DB407FEFDCF8EB5C7
:101C50008F3F31F0809116018823A9F790E02EC0C4
:101C60006EBD0DB407FEFDCF6D3F11F491E026C0AF
:101C700090E080818EBD0DB407FEFDCF81818EBDC9
:101C80000DB407FEFDCF915011F03296F2CF8FEFD9
:101C90008EBD0DB407FEFDCF8FEF8EBD0DB407FED8
:101CA000FDCF8FEF8EBD0DB407FEFDCF8EB590E05A
:101CB0008F71853009F091E081E09827892F089590
:101CC000282F82E3809316018FEF8EBD0DB407FE9F
:101CD000FDCF8EB59FEF9EBD0DB407FEFDCF8EB537
:101CE0008F3F31F0809116018823A9F78FEF089577
:101CF0002EBD0DB407FEFDCF872F9927AA27BB273E
:101D00008EBD0DB407FEFDCFCB01AA27BB278EBD2C
:101D10000DB407FEFDCFBB27A72F962F852F8EBDB5
:101D20000DB407FEFDCF4EBD0DB407FEFDCF203430
:101D300011F485E905C0283411F487E801C080E07A
:101D40008EBD0DB407FEFDCF2C3431F48FEF8EBD68
:101D50000DB407FEFDCF8EB59AE02FEF2EBD0DB46A
:101D600007FEFDCF8EB587FF02C09150B9F70895E9
:101D7000A4E0B0E0EEEBFEE00C94D314882311F065
:101D800081E0CFC080910B0181FDC9C08AE09FEF47
:101D90009EBD0DB407FEFDCF2EB58150C9F72A9820
:101DA00040E050E060E070E080E40E94600E81302E
:101DB00009F0A0C084E6809315014AEA51E060E092
:101DC00070E088E40E94600E813009F054C07E010A
:101DD0000894E11CF11C87019FEF9E012B5F3F4F90
:101DE0009EBD0DB407FEFDCF8EB5F80181938F0126
:101DF000E217F307A9F78B81813009F07BC08C8152
:101E00008A3A09F077C040E050E060E070E087E790
:101E10000E94600E823048F440E050E060E070E4E0
:101E200089E60E94600E882321F0809115018823A5
:101E300051F780911501882309F45CC040E050E01F
:101E400060E070E08AE70E94600E882309F052C0CB
:101E50009FEF9EBD0DB407FEFDCF8EB5F7018193B8
:101E60007F01E017F107A9F7898186FD02C012E022
:101E700042C016E040C040E050E060E070E087E71C
:101E80000E94600E823058F440E050E060E070E064
:101E900089E60E94600E823010F412E001C011E069
:101EA000123079F440E050E060E070E087E70E9493
:101EB000600E823078F440E050E060E070E089E647
:101EC00005C040E050E060E070E081E40E94600EF8
:101ED000882321F080911501882311F78091150145
:101EE000882341F040E052E060E070E080E50E942D
:101EF000600E811110E0109317012A9A8FEF8EBDAA
:101F00000DB407FEFDCF8EB5112321F080910B019A
:101F10008E7F03C080910B01816080930B018091C3
:101F20000B012496E6E00C94EF14882311F081E075
:101F3000089580910B0108950F93CF93DF93EB01E8
:101F4000882309F051C0002309F44EC080910B0191
:101F500080FF03C023E030E049C08091170182FD7B
:101F600007C069E0220F331F441F551F6A95D1F740
:101F70002A98013089F4BA01A90181E50E94600E16
:101F8000882321F560E072E0CE010E94E30D00E0BD
:101F90008823E1F401E01AC0BA01A90182E50E9498
:101FA000600E882399F460E072E0CE010E94E30D98
:101FB000882329F0015019F0C050DE4FF4CF40E0E3
:101FC00050E060E070E08CE40E94600E2A9A8FEF8F
:101FD0008EBD0DB407FEFDCF8EB520E030E00023AE
:101FE00029F021E030E002C024E030E0C901DF91B7
:101FF000CF910F910895CF92DF92EF92FF920F93BE
:10200000CF93DF93EB0169017A01882309F064C063
:10201000002309F461C080910B0180FF03C023E01D
:1020200030E05CC080910B0182FF03C022E030E011
:1020300055C08091170182FD07C079E0CC0CDD1CF2
:10204000EE1CFF1C7A95D1F72A98013069F4B7018C
:10205000A60188E50E94600E882381F56EEFCE010F
:102060000E94180E00E027C081FF0EC040E050E043
:1020700060E070E087E70E94600E402F50E060E073
:1020800070E087E50E94600EB701A60189E50E9415
:10209000600E882399F46CEFCE010E94180E8823FD
:1020A00029F0015019F0C050DE4FF5CF6DEF80E000
:1020B00090E00E94180E882309F401E02A9A8FEF1D
:1020C0008EBD0DB407FEFDCF8EB520E030E00023BD
:1020D00029F021E030E002C024E030E0C901DF91C6
:1020E000CF910F91FF90EF90DF90CF900895A0E1F6
:1020F000B0E0EDE7F0E10C94D5148A01882319F0E3
:1021000024E030E0E7C02A98633009F47FC06430EF
:1021100028F4613079F0623051F472C06B3009F408
:1021200096C06C3009F4AAC06A3009F486C024E075
:1021300030E0C6C040E050E060E070E089E40E941A
:10214000600E882309F0B7C060E170E0CE0101960F
:102150000E94E30D882309F4AEC08981829586959B
:10216000869583707A8549858130B1F4872F90E018
:102170000196342F20E0820F931FA0E0B0E02AE008
:10218000880F991FAA1FBB1F2A95D1F7F8018083DA
:102190009183A283B38392C042954695469543703E
:1021A000288530E0220F331F220F331F240F311DEB
:1021B0002F5F3F4F8F8190E083709070982F88271A
:1021C000990F990F280F391F40E050E08E818F70D2
:1021D0006B85661F6627661F860F8E5F7370770F8D
:1021E000870F90E0099704C0220F331F441F551F2B
:1021F0008A95D2F7F80120833183428353835EC0EE
:1022000080E092E0FA019183808358C082E380935A
:1022100016018FEF8EBD0DB407FEFDCF8EB59FEF7B
:102220009EBD0DB407FEFDCF8EB58F3F09F446C0AD
:10223000809116018823A1F73EC080910B0180FD9B
:1022400047C040E050E060E070E089E409C0809160
:102250000B0180FD3DC040E050E060E070E08AE4AA
:102260000E94600E882339F560E170E0C8010E9489
:10227000E30D20E030E0882319F51DC080910B01AB
:1022800080FD26C040E050E060E070E08AE70E94F8
:10229000600E882381F4F8019FEF98012D5F3F4F76
:1022A0009EBD0DB407FEFDCF8EB58083E217F30708
:1022B00029F03196F5CF21E030E002C020E030E097
:1022C0002A9A8FEF8EBD0DB407FEFDCF8EB502C0EA
:1022D00023E030E0C9016096E4E00C94F1148091B1
:1022E0001501882319F08150809315018091160102
:1022F000882319F08150809316019091140183B1C5
:10230000817080931401981749F480910B0190FF1C
:1023100002C0836001C08D7F80930B010895FB0193
:10232000DC0105900D920020E1F70895FB01DC012E
:1023300004C08D910190801921F441505040C8F79C
:10234000881B990B0895FB01DC0102C001900D92DE
:1023500041505040D8F70895DC0101C06D934150C1
:102360005040E0F70895FB019F01E8944230C4F02B
:102370004532B4F44A3029F497FB1EF490958195C8
:102380009F4F642F77270E94FE14805D8A330CF0E4
:10239000895D8193CB010097A1F716F45DE251931B
:1023A0001082C9010C94EC13AEE0B0E0EAEDF1E16B
:1023B0000C94D5140D891E8986E08C831A830983B9
:1023C0008FEF9FE79E838D83CE014996AC016F8985
:1023D000788DCE0101960E94F7112F813885020F6A
:1023E000131FF80110822E96E4E00C94F114ABE078
:1023F000B0E0EDEFF1E10C94C7143C012B015A0160
:10240000FC0117821682838181FD03C06FEF7FEF8D
:10241000C8C19AE0892E1E010894211C311CF301C9
:102420002381F20123FD859123FF81912F018823D0
:1024300009F4B4C1853239F423FD859123FF8191DC
:102440002F01853229F4B30190E00E94FC13E7CFFD
:10245000982FDD24CC249924FFE1FD15D0F09B3288
:1024600069F09C3228F4903259F0933291F40EC006
:102470009D3249F0903369F441E024C052E0D52AFE
:1024800084E0D82A28C098E0D92A25C0E0E1DE2AD5
:1024900022C0D7FC29C0892F80538A3070F4D6FE21
:1024A00005C0989C902C1124980E15C0C89CC02C77
:1024B0001124C80EF0E2DF2A0EC09E3229F4D6FCA9
:1024C0006DC140E4D42A07C09C3619F450E8D52ADF
:1024D00002C0983649F4F20123FD959123FF9191B2
:1024E0002F01992309F0B8CF892F8554833018F034
:1024F0008052833038F444E050E0A40EB51E5FE310
:1025000059830FC0933631F0933779F0933509F042
:1025100056C020C0F5018081898342E050E0A40EBE
:10252000B51E710101E010E012C0F501E080F180FC
:10253000D6FC03C06FEF7FEF02C0692D70E042E070
:1025400050E0A40EB51EC7010E94E1138C015FE7A5
:10255000D52214C0F501E080F180D6FC03C06FEFF6
:102560007FEF02C0692D70E042E050E0A40EB51E7E
:10257000C7010E94D6138C0150E8D52AD3FE07C0AC
:102580001AC0B30180E290E00E94FC13CA948C2D23
:1025900090E008171907A8F30EC0F701D7FC859142
:1025A000D7FE81917F01B30190E00E94FC13C1101E
:1025B000CA94015010400115110579F7ECC094360A
:1025C00011F0993671F5D7FE08C0F501E080F18071
:1025D0000281138144E050E00AC0F50180819181BD
:1025E0007C010027F7FC0095102F42E050E0A40E7C
:1025F000B51E5FE6D52217FF0AC010950095F0942E
:10260000E094E11CF11C011D111D80E8D82A2AE08C
:1026100030E0A101C801B7010E942814F82EF21879
:1026200040C0953729F41D2D1F7E2AE030E01DC0E3
:102630001D2D197F9F3661F0903720F4983509F0F1
:10264000ADC00FC0903739F0983709F0A7C004C06B
:1026500028E030E00AC0106114FD146020E130E091
:1026600004C014FD166020E132E017FF08C0F50138
:10267000608171818281938144E050E008C0F5015E
:1026800080819181BC0180E090E042E050E0A40EA6
:10269000B51EA1010E942814F82EF2188FE7D82E3B
:1026A000D122D6FE0BC05EEFD522F91438F4D4FE49
:1026B00007C0D2FC05C08FEED82202C01F2D01C07A
:1026C000192DD4FE0DC0FE01EF0DF11D8081803368
:1026D00019F499EED92208C01F5FD2FE05C003C0CD
:1026E0008D2D867809F01F5F0D2DD3FC14C0D0FE10
:1026F0000FC01C1510F09F2C0BC09F2C9C0C911A26
:102700001C2D06C0B30180E290E00E94FC131F5F05
:102710001C15C0F304C01C1510F4C11A01C0CC2450
:1027200004FF10C0B30180E390E00E94FC1302FF9D
:102730001EC001FD03C088E790E002C088E590E07C
:10274000B3010CC0802F867891F001FF02C08BE2AC
:1027500001C080E2D7FC8DE2B30190E00E94FC133F
:1027600006C0B30180E390E00E94FC139A94F91430
:10277000C0F3FA94F101EF0DF11DB301808190E0F7
:102780000E94FC13FF20A9F706C0B30180E290E08D
:102790000E94FC13CA94CC20C1F741CEF30166819C
:1027A0007781CB012B96E2E10C94E314FC010590B8
:1027B000615070400110D8F7809590958E0F9F1F43
:1027C0000895FC016150704001900110D8F7809588
:1027D00090958E0F9F1F0895DC01FC01672F71916A
:1027E0007723E1F7329704C07C916D9370836291F7
:1027F000AE17BF07C8F308950F931F93CF93DF93CE
:102800008C01EB018B8181FF1BC082FF0DC02E81EB
:102810003F818C819D812817390764F4E881F98113
:102820000193F983E88306C0E885F985802F09952F
:10283000892B31F48E819F8101969F838E8302C004
:102840000FEF1FEFC801DF91CF911F910F910895F6
:10285000FA01AA27283051F1203181F1E8946F93D1
:102860006E7F6E5F7F4F8F4F9F4FAF4FB1E03ED077
:10287000B4E03CD0670F781F891F9A1FA11D680F15
:10288000791F8A1F911DA11D6A0F711D811D911D48
:10289000A11D20D009F468943F912AE0269F1124BD
:1028A0003019305D3193DEF6CF010895462F477021
:1028B000405D4193B3E00FD0C9F7F6CF462F4F707C
:1028C000405D4A3318F0495D31FD4052419302D0DA
:1028D000A9F7EACFB4E0A695979587957795679580
:1028E000BA95C9F700976105710508959B01AC0180
:1028F0000A2E06945795479537952795BA95C9F7A7
:10290000620F731F841F951FA01D0895629FD00141
:10291000739FF001829FE00DF11D649FE00DF11D9A
:10292000929FF00D839FF00D749FF00D659FF00D49
:102930009927729FB00DE11DF91F639FB00DE11D36
:10294000F91FBD01CF0111240895A1E21A2EAA1B7F
:10295000BB1BFD010DC0AA1FBB1FEE1FFF1FA2174F
:10296000B307E407F50720F0A21BB30BE40BF50B4C
:10297000661F771F881F991F1A9469F760957095D5
:10298000809590959B01AC01BD01CF0108952F92D8
:102990003F924F925F926F927F928F929F92AF92EF
:1029A000BF92CF92DF92EF92FF920F931F93CF933C
:1029B000DF93CDB7DEB7CA1BDB0B0FB6F894DEBFD3
:1029C0000FBECDBF09942A88398848885F846E84F9
:1029D0007D848C849B84AA84B984C884DF80EE8043
:1029E000FD800C811B81AA81B981CE0FD11D0FB64C
:1029F000F894DEBF0FBECDBFED010895AA1BBB1B2F
:102A000051E107C0AA1FBB1FA617B70710F0A61BEE
:102A1000B70B881F991F5A95A9F780959095BC010F
:082A2000CD010895F894FFCFE9
:0C2A280025642C25640A0046415400017E
:00000001FF
/Designs/Data_loggers/GPSRL03A/glg.lst
0,0 → 1,7338
 
glg.elf: file format elf32-avr
 
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 0000000c 00800100 00002a28 00002a9c 2**0
CONTENTS, ALLOC, LOAD, DATA
1 .text 00002a28 00000000 00000000 00000074 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .bss 00000341 0080010c 00002a34 00002aa8 2**0
ALLOC
3 .stab 00002040 00000000 00000000 00002aa8 2**2
CONTENTS, READONLY, DEBUGGING
4 .stabstr 00000db4 00000000 00000000 00004ae8 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_aranges 00000060 00000000 00000000 0000589c 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_pubnames 0000019e 00000000 00000000 000058fc 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_info 00001f60 00000000 00000000 00005a9a 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_abbrev 000007b9 00000000 00000000 000079fa 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_line 00001b85 00000000 00000000 000081b3 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_frame 00000200 00000000 00000000 00009d38 2**2
CONTENTS, READONLY, DEBUGGING
11 .debug_str 000005cc 00000000 00000000 00009f38 2**0
CONTENTS, READONLY, DEBUGGING
12 .debug_loc 00002af1 00000000 00000000 0000a504 2**0
CONTENTS, READONLY, DEBUGGING
13 .debug_ranges 000001d0 00000000 00000000 0000cff5 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
 
00000000 <__vectors>:
0: 0c 94 41 00 jmp 0x82 ; 0x82 <__ctors_end>
4: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
8: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
c: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
10: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
14: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
18: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
1c: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
20: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
24: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
28: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
2c: 0c 94 18 03 jmp 0x630 ; 0x630 <__vector_11>
30: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
34: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
38: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
3c: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
40: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
44: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
48: 0c 94 b5 00 jmp 0x16a ; 0x16a <__vector_18>
4c: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
50: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
54: 0c 94 60 00 jmp 0xc0 ; 0xc0 <__vector_21>
58: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
5c: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
60: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
64: 0c 94 5e 00 jmp 0xbc ; 0xbc <__bad_interrupt>
 
00000068 <__c.1757>:
68: 24 47 50 52 4d 43 00 $GPRMC.
 
0000006f <__c.1755>:
6f: 24 47 50 47 47 41 00 $GPGGA.
 
00000076 <__c.1753>:
76: 2e 6c 6f 67 00 .log.
 
0000007b <__c.1747>:
7b: 24 47 50 52 4d 43 00 $GPRMC.
 
00000082 <__ctors_end>:
82: 11 24 eor r1, r1
84: 1f be out 0x3f, r1 ; 63
86: cf ef ldi r28, 0xFF ; 255
88: d4 e0 ldi r29, 0x04 ; 4
8a: de bf out 0x3e, r29 ; 62
8c: cd bf out 0x3d, r28 ; 61
 
0000008e <__do_copy_data>:
8e: 11 e0 ldi r17, 0x01 ; 1
90: a0 e0 ldi r26, 0x00 ; 0
92: b1 e0 ldi r27, 0x01 ; 1
94: e8 e2 ldi r30, 0x28 ; 40
96: fa e2 ldi r31, 0x2A ; 42
98: 02 c0 rjmp .+4 ; 0x9e <.do_copy_data_start>
 
0000009a <.do_copy_data_loop>:
9a: 05 90 lpm r0, Z+
9c: 0d 92 st X+, r0
 
0000009e <.do_copy_data_start>:
9e: ac 30 cpi r26, 0x0C ; 12
a0: b1 07 cpc r27, r17
a2: d9 f7 brne .-10 ; 0x9a <.do_copy_data_loop>
 
000000a4 <__do_clear_bss>:
a4: 14 e0 ldi r17, 0x04 ; 4
a6: ac e0 ldi r26, 0x0C ; 12
a8: b1 e0 ldi r27, 0x01 ; 1
aa: 01 c0 rjmp .+2 ; 0xae <.do_clear_bss_start>
 
000000ac <.do_clear_bss_loop>:
ac: 1d 92 st X+, r1
 
000000ae <.do_clear_bss_start>:
ae: ad 34 cpi r26, 0x4D ; 77
b0: b1 07 cpc r27, r17
b2: e1 f7 brne .-8 ; 0xac <.do_clear_bss_loop>
b4: 0e 94 35 01 call 0x26a ; 0x26a <main>
b8: 0c 94 12 15 jmp 0x2a24 ; 0x2a24 <_exit>
 
000000bc <__bad_interrupt>:
bc: 0c 94 00 00 jmp 0 ; 0x0 <__heap_end>
 
000000c0 <__vector_21>:
/*---------------------------------------------------------*/
/* ADC interrupt */
/*---------------------------------------------------------*/
 
ISR(ADC_vect)
{
c0: 1f 92 push r1
c2: 0f 92 push r0
c4: 0f b6 in r0, 0x3f ; 63
c6: 0f 92 push r0
c8: 11 24 eor r1, r1
ca: 2f 93 push r18
cc: 3f 93 push r19
ce: 8f 93 push r24
WORD n;
static BYTE l, h;
 
n = ADC;
d0: 20 91 78 00 lds r18, 0x0078
d4: 30 91 79 00 lds r19, 0x0079
 
if(ADMUX == POWER_check)
d8: 80 91 7c 00 lds r24, 0x007C
{
if (n < VTH_LOW) {
dc: 20 3d cpi r18, 0xD0 ; 208
de: 31 05 cpc r19, r1
e0: 70 f4 brcc .+28 ; 0xfe <__vector_21+0x3e>
if (l >= 15) {
e2: 80 91 0f 01 lds r24, 0x010F
e6: 8f 30 cpi r24, 0x0F ; 15
e8: 30 f0 brcs .+12 ; 0xf6 <__vector_21+0x36>
Stat |= 0x01;
ea: 80 91 6f 01 lds r24, 0x016F
ee: 81 60 ori r24, 0x01 ; 1
f0: 80 93 6f 01 sts 0x016F, r24
f4: 06 c0 rjmp .+12 ; 0x102 <__vector_21+0x42>
}
else {l++;}
f6: 8f 5f subi r24, 0xFF ; 255
f8: 80 93 0f 01 sts 0x010F, r24
fc: 02 c0 rjmp .+4 ; 0x102 <__vector_21+0x42>
}
else {l = 0;}
fe: 10 92 0f 01 sts 0x010F, r1
 
if (n > VTH_HIGH) {
102: 81 e0 ldi r24, 0x01 ; 1
104: 2c 32 cpi r18, 0x2C ; 44
106: 38 07 cpc r19, r24
108: 70 f0 brcs .+28 ; 0x126 <__vector_21+0x66>
if (h >= 15) {
10a: 80 91 0e 01 lds r24, 0x010E
10e: 8f 30 cpi r24, 0x0F ; 15
110: 30 f0 brcs .+12 ; 0x11e <__vector_21+0x5e>
Stat &= 0xFE;
112: 80 91 6f 01 lds r24, 0x016F
116: 8e 7f andi r24, 0xFE ; 254
118: 80 93 6f 01 sts 0x016F, r24
11c: 06 c0 rjmp .+12 ; 0x12a <__vector_21+0x6a>
}
else {h++;}
11e: 8f 5f subi r24, 0xFF ; 255
120: 80 93 0e 01 sts 0x010E, r24
124: 02 c0 rjmp .+4 ; 0x12a <__vector_21+0x6a>
}
else {h = 0;}
126: 10 92 0e 01 sts 0x010E, r1
 
battery = n;
12a: 30 93 75 01 sts 0x0175, r19
12e: 20 93 74 01 sts 0x0174, r18
ADMUX = ANALOG_IN1;
132: 82 e4 ldi r24, 0x42 ; 66
134: 80 93 7c 00 sts 0x007C, r24
}
 
if(ADMUX == ANALOG_IN1)
138: 80 91 7c 00 lds r24, 0x007C
{
intensity = n;
13c: 30 93 10 02 sts 0x0210, r19
140: 20 93 0f 02 sts 0x020F, r18
ADMUX = POWER_check;
144: 81 e4 ldi r24, 0x41 ; 65
146: 80 93 7c 00 sts 0x007C, r24
}
 
//!!!!
//Stat &= 0xFE;
 
ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;
14a: 8f ed ldi r24, 0xDF ; 223
14c: 80 93 7a 00 sts 0x007A, r24
}
150: 8f 91 pop r24
152: 3f 91 pop r19
154: 2f 91 pop r18
156: 0f 90 pop r0
158: 0f be out 0x3f, r0 ; 63
15a: 0f 90 pop r0
15c: 1f 90 pop r1
15e: 18 95 reti
 
00000160 <get_fattime>:
/* FatFs module. Any valid time must be returned even if */
/* the system does not support a real time clock. */
 
 
DWORD get_fattime ()
{
160: 60 e0 ldi r22, 0x00 ; 0
162: 70 e0 ldi r23, 0x00 ; 0
164: 81 ea ldi r24, 0xA1 ; 161
166: 96 e3 ldi r25, 0x36 ; 54
168: 08 95 ret
 
0000016a <__vector_18>:
return d;
}
 
/* USART0 RXC interrupt */
ISR(USART_RX_vect)
{
16a: 1f 92 push r1
16c: 0f 92 push r0
16e: 0f b6 in r0, 0x3f ; 63
170: 0f 92 push r0
172: 11 24 eor r1, r1
174: 8f 93 push r24
176: 9f 93 push r25
178: ef 93 push r30
17a: ff 93 push r31
uint8_t d, n, i;
 
 
d = UDR0;
17c: 90 91 c6 00 lds r25, 0x00C6
n = rxfifo.count;
180: 80 91 78 01 lds r24, 0x0178
if(n < sizeof(rxfifo.buff)) {
184: 86 39 cpi r24, 0x96 ; 150
186: 88 f4 brcc .+34 ; 0x1aa <__vector_18+0x40>
rxfifo.count = ++n;
188: 8f 5f subi r24, 0xFF ; 255
18a: 80 93 78 01 sts 0x0178, r24
i = rxfifo.idx_w;
18e: 80 91 76 01 lds r24, 0x0176
rxfifo.buff[i++] = d;
192: e8 2f mov r30, r24
194: f0 e0 ldi r31, 0x00 ; 0
196: ea 58 subi r30, 0x8A ; 138
198: fe 4f sbci r31, 0xFE ; 254
19a: 93 83 std Z+3, r25 ; 0x03
19c: 8f 5f subi r24, 0xFF ; 255
if(i >= sizeof(rxfifo.buff))
19e: 86 39 cpi r24, 0x96 ; 150
1a0: 08 f0 brcs .+2 ; 0x1a4 <__vector_18+0x3a>
1a2: 80 e0 ldi r24, 0x00 ; 0
i = 0;
rxfifo.idx_w = i;
1a4: 80 93 76 01 sts 0x0176, r24
1a8: 05 c0 rjmp .+10 ; 0x1b4 <__vector_18+0x4a>
} else {
Stat |= 2;
1aa: 80 91 6f 01 lds r24, 0x016F
1ae: 82 60 ori r24, 0x02 ; 2
1b0: 80 93 6f 01 sts 0x016F, r24
}
}
1b4: ff 91 pop r31
1b6: ef 91 pop r30
1b8: 9f 91 pop r25
1ba: 8f 91 pop r24
1bc: 0f 90 pop r0
1be: 0f be out 0x3f, r0 ; 63
1c0: 0f 90 pop r0
1c2: 1f 90 pop r1
1c4: 18 95 reti
 
000001c6 <get_line>:
/* Get a line received from GPS module */
/*----------------------------------------------------*/
 
static
BYTE get_line (void) // 0: Power fail occured, >0: Number of bytes received.
{
1c6: 90 e0 ldi r25, 0x00 ; 0
cli();
UCSR0B = 0;
rxfifo.idx_r = 0;
rxfifo.idx_w = 0;
rxfifo.count = 0;
UBRR0L = SYSCLK/16/GPS_BAUDRATE;
1c8: 52 e8 ldi r21, 0x82 ; 130
UCSR0B = _BV(RXCIE0)|_BV(RXEN0)|_BV(TXEN0);
1ca: 48 e9 ldi r20, 0x98 ; 152
1cc: 01 c0 rjmp .+2 ; 0x1d0 <get_line+0xa>
/* Get a line received from GPS module */
/*----------------------------------------------------*/
 
static
BYTE get_line (void) // 0: Power fail occured, >0: Number of bytes received.
{
1ce: 90 e0 ldi r25, 0x00 ; 0
BYTE c, i = 0;
 
 
for (;;) {
if (Stat & 1) return 0; // When power fail is detected, return with zero.
1d0: 80 91 6f 01 lds r24, 0x016F
1d4: 80 fd sbrc r24, 0
1d6: 46 c0 rjmp .+140 ; 0x264 <get_line+0x9e>
uint8_t uart_get ()
{
uint8_t d, i;
 
 
i = rxfifo.idx_r;
1d8: 30 91 77 01 lds r19, 0x0177
if (rxfifo.count == 0) return 0;
1dc: 80 91 78 01 lds r24, 0x0178
1e0: 88 23 and r24, r24
1e2: 11 f4 brne .+4 ; 0x1e8 <get_line+0x22>
1e4: 20 e0 ldi r18, 0x00 ; 0
1e6: 13 c0 rjmp .+38 ; 0x20e <get_line+0x48>
d = rxfifo.buff[i++];
1e8: e3 2f mov r30, r19
1ea: f0 e0 ldi r31, 0x00 ; 0
1ec: ea 58 subi r30, 0x8A ; 138
1ee: fe 4f sbci r31, 0xFE ; 254
1f0: 23 81 ldd r18, Z+3 ; 0x03
1f2: e3 2f mov r30, r19
1f4: ef 5f subi r30, 0xFF ; 255
cli();
1f6: f8 94 cli
rxfifo.count--;
1f8: 80 91 78 01 lds r24, 0x0178
1fc: 81 50 subi r24, 0x01 ; 1
1fe: 80 93 78 01 sts 0x0178, r24
sei();
202: 78 94 sei
if(i >= sizeof(rxfifo.buff))
204: e6 39 cpi r30, 0x96 ; 150
206: 08 f0 brcs .+2 ; 0x20a <get_line+0x44>
208: e0 e0 ldi r30, 0x00 ; 0
i = 0;
rxfifo.idx_r = i;
20a: e0 93 77 01 sts 0x0177, r30
 
 
for (;;) {
if (Stat & 1) return 0; // When power fail is detected, return with zero.
c = uart_get();
if (Stat & 2) { // When buffer overflow has occured, restart to receive line.
20e: 80 91 6f 01 lds r24, 0x016F
212: 81 ff sbrs r24, 1
214: 14 c0 rjmp .+40 ; 0x23e <get_line+0x78>
 
 
static
void uart_init (void)
{
cli();
216: f8 94 cli
UCSR0B = 0;
218: 10 92 c1 00 sts 0x00C1, r1
rxfifo.idx_r = 0;
21c: 10 92 77 01 sts 0x0177, r1
rxfifo.idx_w = 0;
220: 10 92 76 01 sts 0x0176, r1
rxfifo.count = 0;
224: 10 92 78 01 sts 0x0178, r1
UBRR0L = SYSCLK/16/GPS_BAUDRATE;
228: 50 93 c4 00 sts 0x00C4, r21
UCSR0B = _BV(RXCIE0)|_BV(RXEN0)|_BV(TXEN0);
22c: 40 93 c1 00 sts 0x00C1, r20
Stat &= 0xFD; // Clear overflow flag
230: 80 91 6f 01 lds r24, 0x016F
234: 8d 7f andi r24, 0xFD ; 253
236: 80 93 6f 01 sts 0x016F, r24
sei();
23a: 78 94 sei
23c: c8 cf rjmp .-112 ; 0x1ce <get_line+0x8>
c = uart_get();
if (Stat & 2) { // When buffer overflow has occured, restart to receive line.
uart_init();
i = 0; c = 0;
}
if (!c || (i == 0 && c != '$')) continue;
23e: 22 23 and r18, r18
240: 39 f2 breq .-114 ; 0x1d0 <get_line+0xa>
242: 99 23 and r25, r25
244: 19 f4 brne .+6 ; 0x24c <get_line+0x86>
246: 24 32 cpi r18, 0x24 ; 36
248: 09 f0 breq .+2 ; 0x24c <get_line+0x86>
24a: c2 cf rjmp .-124 ; 0x1d0 <get_line+0xa>
Buff[i++] = c;
24c: e9 2f mov r30, r25
24e: f0 e0 ldi r31, 0x00 ; 0
250: e3 5e subi r30, 0xE3 ; 227
252: fe 4f sbci r31, 0xFE ; 254
254: 20 83 st Z, r18
256: 9f 5f subi r25, 0xFF ; 255
if (c == '\n') break;
258: 2a 30 cpi r18, 0x0A ; 10
25a: 29 f0 breq .+10 ; 0x266 <get_line+0xa0>
if (i >= sizeof(Buff)) i = 0;
25c: 92 35 cpi r25, 0x52 ; 82
25e: 08 f0 brcs .+2 ; 0x262 <get_line+0x9c>
260: b6 cf rjmp .-148 ; 0x1ce <get_line+0x8>
262: b6 cf rjmp .-148 ; 0x1d0 <get_line+0xa>
264: 90 e0 ldi r25, 0x00 ; 0
}
return i;
}
266: 89 2f mov r24, r25
268: 08 95 ret
 
0000026a <main>:
/*-----------------------------------------------------------------------*/
/* Main */
 
 
int main ()
{
26a: a2 e0 ldi r26, 0x02 ; 2
26c: b0 e0 ldi r27, 0x00 ; 0
26e: eb e3 ldi r30, 0x3B ; 59
270: f1 e0 ldi r31, 0x01 ; 1
272: 0c 94 c7 14 jmp 0x298e ; 0x298e <__prologue_saves__>
 
 
static
void ioinit (void)
{
PORTB = 0b00001101; // Port B
276: 8d e0 ldi r24, 0x0D ; 13
278: 85 b9 out 0x05, r24 ; 5
DDRB = 0b00101110;
27a: 8e e2 ldi r24, 0x2E ; 46
27c: 84 b9 out 0x04, r24 ; 4
PORTC = 0b00111111; // Port C
27e: 8f e3 ldi r24, 0x3F ; 63
280: 88 b9 out 0x08, r24 ; 8
DDRC = 0b00000000;
282: 17 b8 out 0x07, r1 ; 7
PORTD = 0b10101110; // Port D
284: 8e ea ldi r24, 0xAE ; 174
286: 8b b9 out 0x0b, r24 ; 11
DDRD = 0b01010010;
288: 82 e5 ldi r24, 0x52 ; 82
28a: 8a b9 out 0x0a, r24 ; 10
 
SPCR = 0b01010000; /* Initialize SPI port (Mode 0) */
28c: 80 e5 ldi r24, 0x50 ; 80
28e: 8c bd out 0x2c, r24 ; 44
SPSR = 0b00000001;
290: 81 e0 ldi r24, 0x01 ; 1
292: 8d bd out 0x2d, r24 ; 45
 
OCR1A = SYSCLK/8/100-1; // Timer1: 100Hz interval (OC1A)
294: 83 ed ldi r24, 0xD3 ; 211
296: 90 e3 ldi r25, 0x30 ; 48
298: 90 93 89 00 sts 0x0089, r25
29c: 80 93 88 00 sts 0x0088, r24
TCCR1B = 0b00001010;
2a0: 8a e0 ldi r24, 0x0A ; 10
2a2: 80 93 81 00 sts 0x0081, r24
TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
2a6: 82 e0 ldi r24, 0x02 ; 2
2a8: 80 93 6f 00 sts 0x006F, r24
 
OCR0A = SYSCLK/64/4000/2-1; // Timer0: 4kHz sound (OC0A)
2ac: 82 e1 ldi r24, 0x12 ; 18
2ae: 87 bd out 0x27, r24 ; 39
TCCR0A = 0b01000010;
2b0: 82 e4 ldi r24, 0x42 ; 66
2b2: 84 bd out 0x24, r24 ; 36
 
ADMUX = POWER_check; // Select ADC input
2b4: 81 e4 ldi r24, 0x41 ; 65
2b6: 80 93 7c 00 sts 0x007C, r24
ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;
2ba: 8f ed ldi r24, 0xDF ; 223
2bc: 80 93 7a 00 sts 0x007A, r24
 
sei();
2c0: 78 94 sei
BYTE b, err, *p = NULL;
WORD s;
 
 
ioinit();
f_mount(0, &fatfs); /* Enable file I/O layer */
2c2: 6d e2 ldi r22, 0x2D ; 45
2c4: 72 e0 ldi r23, 0x02 ; 2
2c6: 80 e0 ldi r24, 0x00 ; 0
2c8: 0e 94 7f 09 call 0x12fe ; 0x12fe <f_mount>
2cc: ee 24 eor r14, r14
2ce: ff 24 eor r15, r15
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
BEEP_ON();
2d0: 53 e0 ldi r21, 0x03 ; 3
2d2: a5 2e mov r10, r21
DELAY(len);
2d4: 45 e0 ldi r20, 0x05 ; 5
2d6: b4 2e mov r11, r20
beep(5, 1); // Single beep. Start to get current time.
uart_init();
do { // Wait for valid RMC sentence.
b = get_line();
if (!b) break;
if (gp_comp(Buff, PSTR("$GPRMC"))) continue;
2d8: 3d e1 ldi r19, 0x1D ; 29
2da: c3 2e mov r12, r19
2dc: 31 e0 ldi r19, 0x01 ; 1
2de: d3 2e mov r13, r19
// || !gp_comp(Buff, PSTR("$GPGSV"))
// || !gp_comp(Buff, PSTR("$GPZDA"))
// || !gp_comp(Buff, PSTR("$GPVTG"))
)
{
if (f_write(&file1, Buff, b, &s) || b != s) { err = 5; break; };
2e0: 4e 01 movw r8, r28
2e2: 08 94 sec
2e4: 81 1c adc r8, r1
2e6: 91 1c adc r9, r1
itoa(battery,&Value1,10); // convert number to character
2e8: 28 e1 ldi r18, 0x18 ; 24
2ea: 22 2e mov r2, r18
2ec: 21 e0 ldi r18, 0x01 ; 1
2ee: 32 2e mov r3, r18
itoa(intensity,&Value2,10);
2f0: 90 e7 ldi r25, 0x70 ; 112
2f2: 69 2e mov r6, r25
2f4: 91 e0 ldi r25, 0x01 ; 1
2f6: 79 2e mov r7, r25
sprintf(Buff,"%d,%d\n",Value1,Value2);
2f8: 80 e0 ldi r24, 0x00 ; 0
2fa: 48 2e mov r4, r24
2fc: 81 e0 ldi r24, 0x01 ; 1
2fe: 58 2e mov r5, r24
 
 
static
void uart_stop (void)
{
UCSR0B = 0;
300: 10 92 c1 00 sts 0x00C1, r1
ioinit();
f_mount(0, &fatfs); /* Enable file I/O layer */
 
for (;;) {
uart_stop();
GPS_OFF();
304: 29 98 cbi 0x05, 1 ; 5
Timer = 100;
306: 84 e6 ldi r24, 0x64 ; 100
308: 80 93 1c 01 sts 0x011C, r24
do {
if (Stat & 1) Timer = 100;
30c: 94 e6 ldi r25, 0x64 ; 100
30e: 80 91 6f 01 lds r24, 0x016F
312: 80 ff sbrs r24, 0
314: 02 c0 rjmp .+4 ; 0x31a <main+0xb0>
316: 90 93 1c 01 sts 0x011C, r25
} while (Timer);
31a: 80 91 1c 01 lds r24, 0x011C
31e: 88 23 and r24, r24
320: b1 f7 brne .-20 ; 0x30e <main+0xa4>
 
GPS_ON();
322: 29 9a sbi 0x05, 1 ; 5
Timer = 255;
324: 8f ef ldi r24, 0xFF ; 255
326: 80 93 1c 01 sts 0x011C, r24
do {
if ((Stat & 1) || (disk_status(0) & STA_NODISK)) Timer = 255;
32a: 1f ef ldi r17, 0xFF ; 255
32c: 80 91 6f 01 lds r24, 0x016F
330: 80 fd sbrc r24, 0
332: 05 c0 rjmp .+10 ; 0x33e <main+0xd4>
334: 80 e0 ldi r24, 0x00 ; 0
336: 0e 94 95 0f call 0x1f2a ; 0x1f2a <disk_status>
33a: 81 ff sbrs r24, 1
33c: 02 c0 rjmp .+4 ; 0x342 <main+0xd8>
33e: 10 93 1c 01 sts 0x011C, r17
} while (Timer);
342: 80 91 1c 01 lds r24, 0x011C
346: 88 23 and r24, r24
348: 89 f7 brne .-30 ; 0x32c <main+0xc2>
34a: 91 e0 ldi r25, 0x01 ; 1
34c: 0e c0 rjmp .+28 ; 0x36a <main+0x100>
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
BEEP_ON();
34e: a5 bc out 0x25, r10 ; 37
DELAY(len);
350: b0 92 1c 01 sts 0x011C, r11
354: 80 91 1c 01 lds r24, 0x011C
358: 88 23 and r24, r24
35a: e1 f7 brne .-8 ; 0x354 <main+0xea>
BEEP_OFF();
35c: 15 bc out 0x25, r1 ; 37
DELAY(len);
35e: b0 92 1c 01 sts 0x011C, r11
362: 80 91 1c 01 lds r24, 0x011C
366: 88 23 and r24, r24
368: e1 f7 brne .-8 ; 0x362 <main+0xf8>
/* Controls */
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
36a: 91 50 subi r25, 0x01 ; 1
36c: 80 f7 brcc .-32 ; 0x34e <main+0xe4>
 
 
static
void uart_init (void)
{
cli();
36e: f8 94 cli
UCSR0B = 0;
370: 10 92 c1 00 sts 0x00C1, r1
rxfifo.idx_r = 0;
374: 10 92 77 01 sts 0x0177, r1
rxfifo.idx_w = 0;
378: 10 92 76 01 sts 0x0176, r1
rxfifo.count = 0;
37c: 10 92 78 01 sts 0x0178, r1
UBRR0L = SYSCLK/16/GPS_BAUDRATE;
380: 82 e8 ldi r24, 0x82 ; 130
382: 80 93 c4 00 sts 0x00C4, r24
UCSR0B = _BV(RXCIE0)|_BV(RXEN0)|_BV(TXEN0);
386: 88 e9 ldi r24, 0x98 ; 152
388: 80 93 c1 00 sts 0x00C1, r24
Stat &= 0xFD; // Clear overflow flag
38c: 80 91 6f 01 lds r24, 0x016F
390: 8d 7f andi r24, 0xFD ; 253
392: 80 93 6f 01 sts 0x016F, r24
sei();
396: 78 94 sei
398: 02 c0 rjmp .+4 ; 0x39e <main+0x134>
39a: ee 24 eor r14, r14
39c: ff 24 eor r15, r15
} while (Timer);
 
beep(5, 1); // Single beep. Start to get current time.
uart_init();
do { // Wait for valid RMC sentence.
b = get_line();
39e: 0e 94 e3 00 call 0x1c6 ; 0x1c6 <get_line>
if (!b) break;
3a2: 88 23 and r24, r24
3a4: 09 f4 brne .+2 ; 0x3a8 <main+0x13e>
3a6: ac cf rjmp .-168 ; 0x300 <main+0x96>
if (gp_comp(Buff, PSTR("$GPRMC"))) continue;
3a8: 2b e7 ldi r18, 0x7B ; 123
3aa: 30 e0 ldi r19, 0x00 ; 0
3ac: ad e1 ldi r26, 0x1D ; 29
3ae: b1 e0 ldi r27, 0x01 ; 1
3b0: f9 01 movw r30, r18
BYTE gp_comp (BYTE *str1, const prog_uint8_t *str2)
{
BYTE c;
 
do {
c = pgm_read_byte(str2++);
3b2: 2f 5f subi r18, 0xFF ; 255
3b4: 3f 4f sbci r19, 0xFF ; 255
3b6: 94 91 lpm r25, Z
} while (c && c == *str1++);
3b8: 99 23 and r25, r25
3ba: 29 f0 breq .+10 ; 0x3c6 <main+0x15c>
3bc: 8c 91 ld r24, X
3be: 98 17 cp r25, r24
3c0: 71 f4 brne .+28 ; 0x3de <main+0x174>
3c2: 11 96 adiw r26, 0x01 ; 1
3c4: f5 cf rjmp .-22 ; 0x3b0 <main+0x146>
3c6: ed e1 ldi r30, 0x1D ; 29
3c8: f1 e0 ldi r31, 0x01 ; 1
3ca: 82 e0 ldi r24, 0x02 ; 2
BYTE c;
 
 
while (col) {
do {
c = *buf++;
3cc: 90 81 ld r25, Z
if (c <= ' ') return NULL;
3ce: 91 32 cpi r25, 0x21 ; 33
3d0: 20 f3 brcs .-56 ; 0x39a <main+0x130>
BYTE c;
 
 
while (col) {
do {
c = *buf++;
3d2: 31 96 adiw r30, 0x01 ; 1
if (c <= ' ') return NULL;
} while (c != ',');
3d4: 9c 32 cpi r25, 0x2C ; 44
3d6: d1 f7 brne .-12 ; 0x3cc <main+0x162>
col--;
3d8: 81 50 subi r24, 0x01 ; 1
BYTE col /* Column number (0 is the 1st item) */
) {
BYTE c;
 
 
while (col) {
3da: c1 f7 brne .-16 ; 0x3cc <main+0x162>
c = *buf++;
if (c <= ' ') return NULL;
} while (c != ',');
col--;
}
return (BYTE*)buf;
3dc: 7f 01 movw r14, r30
do { // Wait for valid RMC sentence.
b = get_line();
if (!b) break;
if (gp_comp(Buff, PSTR("$GPRMC"))) continue;
p = gp_col(Buff,2);
} while (!p || *p != 'A');
3de: e1 14 cp r14, r1
3e0: f1 04 cpc r15, r1
3e2: e9 f2 breq .-70 ; 0x39e <main+0x134>
3e4: f7 01 movw r30, r14
3e6: 80 81 ld r24, Z
3e8: 81 34 cpi r24, 0x41 ; 65
3ea: c9 f6 brne .-78 ; 0x39e <main+0x134>
3ec: ed e1 ldi r30, 0x1D ; 29
3ee: f1 e0 ldi r31, 0x01 ; 1
3f0: 89 e0 ldi r24, 0x09 ; 9
BYTE c;
 
 
while (col) {
do {
c = *buf++;
3f2: 90 81 ld r25, Z
if (c <= ' ') return NULL;
3f4: 91 32 cpi r25, 0x21 ; 33
3f6: 08 f4 brcc .+2 ; 0x3fa <main+0x190>
3f8: f0 c0 rjmp .+480 ; 0x5da <__stack+0xdb>
BYTE c;
 
 
while (col) {
do {
c = *buf++;
3fa: 31 96 adiw r30, 0x01 ; 1
if (c <= ' ') return NULL;
} while (c != ',');
3fc: 9c 32 cpi r25, 0x2C ; 44
3fe: c9 f7 brne .-14 ; 0x3f2 <main+0x188>
col--;
400: 81 50 subi r24, 0x01 ; 1
BYTE col /* Column number (0 is the 1st item) */
) {
BYTE c;
 
 
while (col) {
402: b9 f7 brne .-18 ; 0x3f2 <main+0x188>
c = *buf++;
if (c <= ' ') return NULL;
} while (c != ',');
col--;
}
return (BYTE*)buf;
404: 7f 01 movw r14, r30
p = gp_col(Buff,2);
} while (!p || *p != 'A');
if (!b) continue;
p = gp_col(Buff,9); // Open log file with the name of current date (YYMMDD.log in UTC).
if (!p) {err = 3; break;}
406: 30 97 sbiw r30, 0x00 ; 0
408: 09 f4 brne .+2 ; 0x40c <main+0x1a2>
40a: e7 c0 rjmp .+462 ; 0x5da <__stack+0xdb>
 
memcpy(&Buff[0], p+4, 2);
40c: 84 81 ldd r24, Z+4 ; 0x04
40e: 95 81 ldd r25, Z+5 ; 0x05
410: 90 93 1e 01 sts 0x011E, r25
414: 80 93 1d 01 sts 0x011D, r24
memcpy(&Buff[2], p+2, 2);
418: 82 81 ldd r24, Z+2 ; 0x02
41a: 93 81 ldd r25, Z+3 ; 0x03
41c: 90 93 20 01 sts 0x0120, r25
420: 80 93 1f 01 sts 0x011F, r24
memcpy(&Buff[4], p+0, 2);
424: 80 81 ld r24, Z
426: 91 81 ldd r25, Z+1 ; 0x01
428: 90 93 22 01 sts 0x0122, r25
42c: 80 93 21 01 sts 0x0121, r24
strcpy_P(&Buff[6], PSTR(".log"));
430: 66 e7 ldi r22, 0x76 ; 118
432: 70 e0 ldi r23, 0x00 ; 0
434: 83 e2 ldi r24, 0x23 ; 35
436: 91 e0 ldi r25, 0x01 ; 1
438: 0e 94 8f 11 call 0x231e ; 0x231e <strcpy_P>
if (f_open(&file1, Buff, FA_OPEN_ALWAYS | FA_WRITE) || f_lseek(&file1, file1.fsize)) { err = 4; break; }
43c: 42 e1 ldi r20, 0x12 ; 18
43e: 6d e1 ldi r22, 0x1D ; 29
440: 71 e0 ldi r23, 0x01 ; 1
442: 81 e1 ldi r24, 0x11 ; 17
444: 92 e0 ldi r25, 0x02 ; 2
446: 0e 94 d7 09 call 0x13ae ; 0x13ae <f_open>
44a: 89 2b or r24, r25
44c: 09 f0 breq .+2 ; 0x450 <main+0x1e6>
44e: c7 c0 rjmp .+398 ; 0x5de <__stack+0xdf>
450: 40 91 1b 02 lds r20, 0x021B
454: 50 91 1c 02 lds r21, 0x021C
458: 60 91 1d 02 lds r22, 0x021D
45c: 70 91 1e 02 lds r23, 0x021E
460: 81 e1 ldi r24, 0x11 ; 17
462: 92 e0 ldi r25, 0x02 ; 2
464: 0e 94 3c 05 call 0xa78 ; 0xa78 <f_lseek>
468: 89 2b or r24, r25
46a: 09 f0 breq .+2 ; 0x46e <main+0x204>
46c: b8 c0 rjmp .+368 ; 0x5de <__stack+0xdf>
46e: 92 e0 ldi r25, 0x02 ; 2
470: 0e c0 rjmp .+28 ; 0x48e <main+0x224>
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
BEEP_ON();
472: a5 bc out 0x25, r10 ; 37
DELAY(len);
474: b0 92 1c 01 sts 0x011C, r11
478: 80 91 1c 01 lds r24, 0x011C
47c: 88 23 and r24, r24
47e: e1 f7 brne .-8 ; 0x478 <main+0x20e>
BEEP_OFF();
480: 15 bc out 0x25, r1 ; 37
DELAY(len);
482: b0 92 1c 01 sts 0x011C, r11
486: 80 91 1c 01 lds r24, 0x011C
48a: 88 23 and r24, r24
48c: e1 f7 brne .-8 ; 0x486 <main+0x21c>
/* Controls */
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
48e: 91 50 subi r25, 0x01 ; 1
490: 80 f7 brcc .-32 ; 0x472 <main+0x208>
492: 85 c0 rjmp .+266 ; 0x59e <__stack+0x9f>
if (f_open(&file1, Buff, FA_OPEN_ALWAYS | FA_WRITE) || f_lseek(&file1, file1.fsize)) { err = 4; break; }
 
beep(5, 2); // Two beeps. Start logging.
err = 0;
while ((b = get_line()) > 0) {
if ( !gp_comp(Buff, PSTR("$GPGGA")) // Which sentence is logged?
494: 2f e6 ldi r18, 0x6F ; 111
496: 30 e0 ldi r19, 0x00 ; 0
498: ad e1 ldi r26, 0x1D ; 29
49a: b1 e0 ldi r27, 0x01 ; 1
49c: f9 01 movw r30, r18
BYTE gp_comp (BYTE *str1, const prog_uint8_t *str2)
{
BYTE c;
 
do {
c = pgm_read_byte(str2++);
49e: 2f 5f subi r18, 0xFF ; 255
4a0: 3f 4f sbci r19, 0xFF ; 255
4a2: 94 91 lpm r25, Z
} while (c && c == *str1++);
4a4: 99 23 and r25, r25
4a6: 89 f0 breq .+34 ; 0x4ca <main+0x260>
4a8: 8c 91 ld r24, X
4aa: 98 17 cp r25, r24
4ac: 09 f0 breq .+2 ; 0x4b0 <main+0x246>
4ae: ae c0 rjmp .+348 ; 0x60c <__stack+0x10d>
4b0: 11 96 adiw r26, 0x01 ; 1
4b2: f4 cf rjmp .-24 ; 0x49c <main+0x232>
BYTE gp_comp (BYTE *str1, const prog_uint8_t *str2)
{
BYTE c;
 
do {
c = pgm_read_byte(str2++);
4b4: 11 96 adiw r26, 0x01 ; 1
4b6: f9 01 movw r30, r18
4b8: 2f 5f subi r18, 0xFF ; 255
4ba: 3f 4f sbci r19, 0xFF ; 255
4bc: 94 91 lpm r25, Z
} while (c && c == *str1++);
4be: 99 23 and r25, r25
4c0: 21 f0 breq .+8 ; 0x4ca <main+0x260>
4c2: 8c 91 ld r24, X
4c4: 98 17 cp r25, r24
4c6: b1 f3 breq .-20 ; 0x4b4 <main+0x24a>
4c8: 57 c0 rjmp .+174 ; 0x578 <__stack+0x79>
// || !gp_comp(Buff, PSTR("$GPGSV"))
// || !gp_comp(Buff, PSTR("$GPZDA"))
// || !gp_comp(Buff, PSTR("$GPVTG"))
)
{
if (f_write(&file1, Buff, b, &s) || b != s) { err = 5; break; };
4ca: 04 2f mov r16, r20
4cc: 10 e0 ldi r17, 0x00 ; 0
4ce: 94 01 movw r18, r8
4d0: a8 01 movw r20, r16
4d2: 6d e1 ldi r22, 0x1D ; 29
4d4: 71 e0 ldi r23, 0x01 ; 1
4d6: 81 e1 ldi r24, 0x11 ; 17
4d8: 92 e0 ldi r25, 0x02 ; 2
4da: 0e 94 0e 07 call 0xe1c ; 0xe1c <f_write>
4de: 89 2b or r24, r25
4e0: 09 f0 breq .+2 ; 0x4e4 <main+0x27a>
4e2: 64 c0 rjmp .+200 ; 0x5ac <__stack+0xad>
4e4: 89 81 ldd r24, Y+1 ; 0x01
4e6: 9a 81 ldd r25, Y+2 ; 0x02
4e8: 08 17 cp r16, r24
4ea: 19 07 cpc r17, r25
4ec: 09 f0 breq .+2 ; 0x4f0 <main+0x286>
4ee: 5e c0 rjmp .+188 ; 0x5ac <__stack+0xad>
itoa(battery,&Value1,10); // convert number to character
4f0: 4a e0 ldi r20, 0x0A ; 10
4f2: 50 e0 ldi r21, 0x00 ; 0
4f4: 68 e1 ldi r22, 0x18 ; 24
4f6: 71 e0 ldi r23, 0x01 ; 1
4f8: 80 91 74 01 lds r24, 0x0174
4fc: 90 91 75 01 lds r25, 0x0175
500: 0e 94 b3 11 call 0x2366 ; 0x2366 <itoa>
itoa(intensity,&Value2,10);
504: 4a e0 ldi r20, 0x0A ; 10
506: 50 e0 ldi r21, 0x00 ; 0
508: 60 e7 ldi r22, 0x70 ; 112
50a: 71 e0 ldi r23, 0x01 ; 1
50c: 80 91 0f 02 lds r24, 0x020F
510: 90 91 10 02 lds r25, 0x0210
514: 0e 94 b3 11 call 0x2366 ; 0x2366 <itoa>
sprintf(Buff,"%d,%d\n",Value1,Value2);
518: 7f 92 push r7
51a: 6f 92 push r6
51c: 3f 92 push r3
51e: 2f 92 push r2
520: 5f 92 push r5
522: 4f 92 push r4
524: df 92 push r13
526: cf 92 push r12
528: 0e 94 d4 11 call 0x23a8 ; 0x23a8 <sprintf>
if (f_write(&file1, Buff,strlen(Buff), &s) || (strlen(Buff) != s)) { err = 8; break; };
52c: f6 01 movw r30, r12
52e: 01 90 ld r0, Z+
530: 00 20 and r0, r0
532: e9 f7 brne .-6 ; 0x52e <__stack+0x2f>
534: 31 97 sbiw r30, 0x01 ; 1
536: ec 19 sub r30, r12
538: fd 09 sbc r31, r13
53a: 94 01 movw r18, r8
53c: af 01 movw r20, r30
53e: 6d e1 ldi r22, 0x1D ; 29
540: 71 e0 ldi r23, 0x01 ; 1
542: 81 e1 ldi r24, 0x11 ; 17
544: 92 e0 ldi r25, 0x02 ; 2
546: 0e 94 0e 07 call 0xe1c ; 0xe1c <f_write>
54a: 2d b7 in r18, 0x3d ; 61
54c: 3e b7 in r19, 0x3e ; 62
54e: 28 5f subi r18, 0xF8 ; 248
550: 3f 4f sbci r19, 0xFF ; 255
552: 0f b6 in r0, 0x3f ; 63
554: f8 94 cli
556: 3e bf out 0x3e, r19 ; 62
558: 0f be out 0x3f, r0 ; 63
55a: 2d bf out 0x3d, r18 ; 61
55c: 89 2b or r24, r25
55e: 41 f5 brne .+80 ; 0x5b0 <__stack+0xb1>
560: d6 01 movw r26, r12
562: 0d 90 ld r0, X+
564: 00 20 and r0, r0
566: e9 f7 brne .-6 ; 0x562 <__stack+0x63>
568: 11 97 sbiw r26, 0x01 ; 1
56a: ac 19 sub r26, r12
56c: bd 09 sbc r27, r13
56e: 89 81 ldd r24, Y+1 ; 0x01
570: 9a 81 ldd r25, Y+2 ; 0x02
572: a8 17 cp r26, r24
574: b9 07 cpc r27, r25
576: e1 f4 brne .+56 ; 0x5b0 <__stack+0xb1>
}
if ((Stat & 4) == 0) continue;
578: 80 91 6f 01 lds r24, 0x016F
57c: 82 ff sbrs r24, 2
57e: 0f c0 rjmp .+30 ; 0x59e <__stack+0x9f>
if (f_sync(&file1)) { err = 6; break; };// Synchronize the file in interval of 300 sec.
580: 81 e1 ldi r24, 0x11 ; 17
582: 92 e0 ldi r25, 0x02 ; 2
584: 0e 94 a9 06 call 0xd52 ; 0xd52 <f_sync>
588: 89 2b or r24, r25
58a: 11 f0 breq .+4 ; 0x590 <__stack+0x91>
58c: 96 e0 ldi r25, 0x06 ; 6
58e: 28 c0 rjmp .+80 ; 0x5e0 <__stack+0xe1>
cli(); Stat &= 0xFB; sei(); // Clear sync request
590: f8 94 cli
592: 80 91 6f 01 lds r24, 0x016F
596: 8b 7f andi r24, 0xFB ; 251
598: 80 93 6f 01 sts 0x016F, r24
59c: 78 94 sei
strcpy_P(&Buff[6], PSTR(".log"));
if (f_open(&file1, Buff, FA_OPEN_ALWAYS | FA_WRITE) || f_lseek(&file1, file1.fsize)) { err = 4; break; }
 
beep(5, 2); // Two beeps. Start logging.
err = 0;
while ((b = get_line()) > 0) {
59e: 0e 94 e3 00 call 0x1c6 ; 0x1c6 <get_line>
5a2: 48 2f mov r20, r24
5a4: 88 23 and r24, r24
5a6: 09 f0 breq .+2 ; 0x5aa <__stack+0xab>
5a8: 75 cf rjmp .-278 ; 0x494 <main+0x22a>
5aa: 35 c0 rjmp .+106 ; 0x616 <__stack+0x117>
5ac: 95 e0 ldi r25, 0x05 ; 5
5ae: 18 c0 rjmp .+48 ; 0x5e0 <__stack+0xe1>
5b0: 98 e0 ldi r25, 0x08 ; 8
5b2: 16 c0 rjmp .+44 ; 0x5e0 <__stack+0xe1>
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
BEEP_ON();
5b4: a5 bc out 0x25, r10 ; 37
DELAY(len);
5b6: 32 e3 ldi r19, 0x32 ; 50
5b8: 30 93 1c 01 sts 0x011C, r19
5bc: 80 91 1c 01 lds r24, 0x011C
5c0: 88 23 and r24, r24
5c2: e1 f7 brne .-8 ; 0x5bc <__stack+0xbd>
BEEP_OFF();
5c4: 15 bc out 0x25, r1 ; 37
DELAY(len);
5c6: 82 e3 ldi r24, 0x32 ; 50
5c8: 80 93 1c 01 sts 0x011C, r24
5cc: 80 91 1c 01 lds r24, 0x011C
5d0: 88 23 and r24, r24
5d2: e1 f7 brne .-8 ; 0x5cc <__stack+0xcd>
/* Controls */
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
5d4: 91 50 subi r25, 0x01 ; 1
5d6: 70 f7 brcc .-36 ; 0x5b4 <__stack+0xb5>
5d8: 93 ce rjmp .-730 ; 0x300 <main+0x96>
5da: 93 e0 ldi r25, 0x03 ; 3
5dc: 01 c0 rjmp .+2 ; 0x5e0 <__stack+0xe1>
5de: 94 e0 ldi r25, 0x04 ; 4
 
 
static
void uart_stop (void)
{
UCSR0B = 0;
5e0: 10 92 c1 00 sts 0x00C1, r1
beep(50, 1);
}
 
// Unrecoverble error. Enter shutdown state.
uart_stop();
GPS_OFF();
5e4: 29 98 cbi 0x05, 1 ; 5
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
BEEP_ON();
5e6: 33 e0 ldi r19, 0x03 ; 3
DELAY(len);
5e8: 29 e1 ldi r18, 0x19 ; 25
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
BEEP_ON();
5ea: 35 bd out 0x25, r19 ; 37
DELAY(len);
5ec: 20 93 1c 01 sts 0x011C, r18
5f0: 80 91 1c 01 lds r24, 0x011C
5f4: 88 23 and r24, r24
5f6: e1 f7 brne .-8 ; 0x5f0 <__stack+0xf1>
BEEP_OFF();
5f8: 15 bc out 0x25, r1 ; 37
DELAY(len);
5fa: 20 93 1c 01 sts 0x011C, r18
5fe: 80 91 1c 01 lds r24, 0x011C
602: 88 23 and r24, r24
604: e1 f7 brne .-8 ; 0x5fe <__stack+0xff>
606: 91 50 subi r25, 0x01 ; 1
/* Controls */
 
static
void beep (BYTE len, BYTE cnt)
{
while (cnt--) {
608: 81 f7 brne .-32 ; 0x5ea <__stack+0xeb>
60a: ff cf rjmp .-2 ; 0x60a <__stack+0x10b>
 
beep(5, 2); // Two beeps. Start logging.
err = 0;
while ((b = get_line()) > 0) {
if ( !gp_comp(Buff, PSTR("$GPGGA")) // Which sentence is logged?
|| !gp_comp(Buff, PSTR("$GPRMC"))
60c: 28 e6 ldi r18, 0x68 ; 104
60e: 30 e0 ldi r19, 0x00 ; 0
610: ad e1 ldi r26, 0x1D ; 29
612: b1 e0 ldi r27, 0x01 ; 1
614: 50 cf rjmp .-352 ; 0x4b6 <main+0x24c>
 
 
static
void uart_stop (void)
{
UCSR0B = 0;
616: 10 92 c1 00 sts 0x00C1, r1
}
if (err) break;
 
// Turn-off GPS power and close the log file by power supply is discharged.
uart_stop();
GPS_OFF();
61a: 29 98 cbi 0x05, 1 ; 5
if (f_close(&file1)) { err = 7; break; };
61c: 81 e1 ldi r24, 0x11 ; 17
61e: 92 e0 ldi r25, 0x02 ; 2
620: 0e 94 00 07 call 0xe00 ; 0xe00 <f_close>
624: 89 2b or r24, r25
626: 11 f0 breq .+4 ; 0x62c <__stack+0x12d>
628: 97 e0 ldi r25, 0x07 ; 7
62a: da cf rjmp .-76 ; 0x5e0 <__stack+0xe1>
62c: 91 e0 ldi r25, 0x01 ; 1
62e: d2 cf rjmp .-92 ; 0x5d4 <__stack+0xd5>
 
00000630 <__vector_11>:
/* 100Hz timer interrupt generated by OC1A */
/*---------------------------------------------------------*/
 
 
ISR(TIMER1_COMPA_vect)
{
630: 1f 92 push r1
632: 0f 92 push r0
634: 0f b6 in r0, 0x3f ; 63
636: 0f 92 push r0
638: 11 24 eor r1, r1
63a: 2f 93 push r18
63c: 8f 93 push r24
63e: 9f 93 push r25
BYTE n;
static WORD ivt_sync;
 
 
n = Timer;
640: 80 91 1c 01 lds r24, 0x011C
if (n) Timer = n - 1;
644: 88 23 and r24, r24
646: 19 f0 breq .+6 ; 0x64e <__vector_11+0x1e>
648: 81 50 subi r24, 0x01 ; 1
64a: 80 93 1c 01 sts 0x011C, r24
 
if (++ivt_sync >= 180 * 100) {
64e: 80 91 0c 01 lds r24, 0x010C
652: 90 91 0d 01 lds r25, 0x010D
656: 01 96 adiw r24, 0x01 ; 1
658: 90 93 0d 01 sts 0x010D, r25
65c: 80 93 0c 01 sts 0x010C, r24
660: 80 55 subi r24, 0x50 ; 80
662: 96 44 sbci r25, 0x46 ; 70
664: 48 f0 brcs .+18 ; 0x678 <__vector_11+0x48>
ivt_sync = 0;
666: 10 92 0d 01 sts 0x010D, r1
66a: 10 92 0c 01 sts 0x010C, r1
Stat |= 4;
66e: 80 91 6f 01 lds r24, 0x016F
672: 84 60 ori r24, 0x04 ; 4
674: 80 93 6f 01 sts 0x016F, r24
}
 
disk_timerproc(); /* Drive timer procedure of low level disk I/O module */
678: 0e 94 6f 11 call 0x22de ; 0x22de <disk_timerproc>
 
}
67c: 9f 91 pop r25
67e: 8f 91 pop r24
680: 2f 91 pop r18
682: 0f 90 pop r0
684: 0f be out 0x3f, r0 ; 63
686: 0f 90 pop r0
688: 1f 90 pop r1
68a: 18 95 reti
 
0000068c <validate>:
static
FRESULT validate ( /* FR_OK(0): The id is valid, !=0: Not valid */
const FATFS *fs, /* Pointer to the file system object */
WORD id /* id member of the target object to be checked */
)
{
68c: fc 01 movw r30, r24
if (!fs || fs->id != id)
68e: 00 97 sbiw r24, 0x00 ; 0
690: 69 f0 breq .+26 ; 0x6ac <validate+0x20>
692: 80 81 ld r24, Z
694: 91 81 ldd r25, Z+1 ; 0x01
696: 86 17 cp r24, r22
698: 97 07 cpc r25, r23
69a: 41 f4 brne .+16 ; 0x6ac <validate+0x20>
return FR_INVALID_OBJECT;
if (disk_status(0) & STA_NOINIT)
69c: 80 e0 ldi r24, 0x00 ; 0
69e: 0e 94 95 0f call 0x1f2a ; 0x1f2a <disk_status>
6a2: 28 2f mov r18, r24
6a4: 30 e0 ldi r19, 0x00 ; 0
6a6: 21 70 andi r18, 0x01 ; 1
6a8: 30 70 andi r19, 0x00 ; 0
6aa: 02 c0 rjmp .+4 ; 0x6b0 <validate+0x24>
6ac: 2c e0 ldi r18, 0x0C ; 12
6ae: 30 e0 ldi r19, 0x00 ; 0
return FR_NOT_READY;
 
return FR_OK;
}
6b0: c9 01 movw r24, r18
6b2: 08 95 ret
 
000006b4 <move_window>:
 
static
BOOL move_window ( /* TRUE: successful, FALSE: failed */
DWORD sector /* Sector number to make apperance in the FatFs->win */
) /* Move to zero only writes back dirty window */
{
6b4: a0 e0 ldi r26, 0x00 ; 0
6b6: b0 e0 ldi r27, 0x00 ; 0
6b8: e0 e6 ldi r30, 0x60 ; 96
6ba: f3 e0 ldi r31, 0x03 ; 3
6bc: 0c 94 cb 14 jmp 0x2996 ; 0x2996 <__prologue_saves__+0x8>
6c0: 4b 01 movw r8, r22
6c2: 5c 01 movw r10, r24
DWORD wsect;
FATFS *fs = FatFs;
6c4: c0 91 10 01 lds r28, 0x0110
6c8: d0 91 11 01 lds r29, 0x0111
 
 
wsect = fs->winsect;
6cc: cc 80 ldd r12, Y+4 ; 0x04
6ce: dd 80 ldd r13, Y+5 ; 0x05
6d0: ee 80 ldd r14, Y+6 ; 0x06
6d2: ff 80 ldd r15, Y+7 ; 0x07
if (wsect != sector) { /* Changed current window */
6d4: c6 16 cp r12, r22
6d6: d7 06 cpc r13, r23
6d8: e8 06 cpc r14, r24
6da: f9 06 cpc r15, r25
6dc: 09 f4 brne .+2 ; 0x6e0 <move_window+0x2c>
6de: 4e c0 rjmp .+156 ; 0x77c <move_window+0xc8>
#if !_FS_READONLY
BYTE n;
if (fs->winflag) { /* Write back dirty window if needed */
6e0: 8f 8d ldd r24, Y+31 ; 0x1f
6e2: 88 23 and r24, r24
6e4: a1 f1 breq .+104 ; 0x74e <move_window+0x9a>
if (disk_write(0, fs->win, wsect, 1) != RES_OK)
6e6: 80 e2 ldi r24, 0x20 ; 32
6e8: 68 2e mov r6, r24
6ea: 71 2c mov r7, r1
6ec: 6c 0e add r6, r28
6ee: 7d 1e adc r7, r29
6f0: 01 e0 ldi r16, 0x01 ; 1
6f2: a7 01 movw r20, r14
6f4: 96 01 movw r18, r12
6f6: b3 01 movw r22, r6
6f8: 80 e0 ldi r24, 0x00 ; 0
6fa: 0e 94 fb 0f call 0x1ff6 ; 0x1ff6 <disk_write>
6fe: 89 2b or r24, r25
700: d9 f5 brne .+118 ; 0x778 <move_window+0xc4>
return FALSE;
fs->winflag = 0;
702: 1f 8e std Y+31, r1 ; 0x1f
if (wsect < (fs->fatbase + fs->sects_fat)) { /* In FAT area */
704: 8c 89 ldd r24, Y+20 ; 0x14
706: 9d 89 ldd r25, Y+21 ; 0x15
708: a0 e0 ldi r26, 0x00 ; 0
70a: b0 e0 ldi r27, 0x00 ; 0
70c: 28 85 ldd r18, Y+8 ; 0x08
70e: 39 85 ldd r19, Y+9 ; 0x09
710: 4a 85 ldd r20, Y+10 ; 0x0a
712: 5b 85 ldd r21, Y+11 ; 0x0b
714: 82 0f add r24, r18
716: 93 1f adc r25, r19
718: a4 1f adc r26, r20
71a: b5 1f adc r27, r21
71c: c8 16 cp r12, r24
71e: d9 06 cpc r13, r25
720: ea 06 cpc r14, r26
722: fb 06 cpc r15, r27
724: a0 f4 brcc .+40 ; 0x74e <move_window+0x9a>
for (n = fs->n_fats; n >= 2; n--) { /* Refrect the change to all FAT copies */
726: 1e 8d ldd r17, Y+30 ; 0x1e
728: 10 c0 rjmp .+32 ; 0x74a <move_window+0x96>
wsect += fs->sects_fat;
72a: 8c 89 ldd r24, Y+20 ; 0x14
72c: 9d 89 ldd r25, Y+21 ; 0x15
72e: a0 e0 ldi r26, 0x00 ; 0
730: b0 e0 ldi r27, 0x00 ; 0
732: c8 0e add r12, r24
734: d9 1e adc r13, r25
736: ea 1e adc r14, r26
738: fb 1e adc r15, r27
disk_write(0, fs->win, wsect, 1);
73a: 01 e0 ldi r16, 0x01 ; 1
73c: a7 01 movw r20, r14
73e: 96 01 movw r18, r12
740: b3 01 movw r22, r6
742: 80 e0 ldi r24, 0x00 ; 0
744: 0e 94 fb 0f call 0x1ff6 ; 0x1ff6 <disk_write>
if (fs->winflag) { /* Write back dirty window if needed */
if (disk_write(0, fs->win, wsect, 1) != RES_OK)
return FALSE;
fs->winflag = 0;
if (wsect < (fs->fatbase + fs->sects_fat)) { /* In FAT area */
for (n = fs->n_fats; n >= 2; n--) { /* Refrect the change to all FAT copies */
748: 11 50 subi r17, 0x01 ; 1
74a: 12 30 cpi r17, 0x02 ; 2
74c: 70 f7 brcc .-36 ; 0x72a <move_window+0x76>
disk_write(0, fs->win, wsect, 1);
}
}
}
#endif
if (sector) {
74e: 81 14 cp r8, r1
750: 91 04 cpc r9, r1
752: a1 04 cpc r10, r1
754: b1 04 cpc r11, r1
756: 91 f0 breq .+36 ; 0x77c <move_window+0xc8>
if (disk_read(0, fs->win, sector, 1) != RES_OK)
758: be 01 movw r22, r28
75a: 60 5e subi r22, 0xE0 ; 224
75c: 7f 4f sbci r23, 0xFF ; 255
75e: 01 e0 ldi r16, 0x01 ; 1
760: a5 01 movw r20, r10
762: 94 01 movw r18, r8
764: 80 e0 ldi r24, 0x00 ; 0
766: 0e 94 9c 0f call 0x1f38 ; 0x1f38 <disk_read>
76a: 89 2b or r24, r25
76c: 29 f4 brne .+10 ; 0x778 <move_window+0xc4>
return FALSE;
fs->winsect = sector;
76e: 8c 82 std Y+4, r8 ; 0x04
770: 9d 82 std Y+5, r9 ; 0x05
772: ae 82 std Y+6, r10 ; 0x06
774: bf 82 std Y+7, r11 ; 0x07
776: 02 c0 rjmp .+4 ; 0x77c <move_window+0xc8>
778: 80 e0 ldi r24, 0x00 ; 0
77a: 01 c0 rjmp .+2 ; 0x77e <move_window+0xca>
77c: 81 e0 ldi r24, 0x01 ; 1
}
}
return TRUE;
}
77e: cd b7 in r28, 0x3d ; 61
780: de b7 in r29, 0x3e ; 62
782: ee e0 ldi r30, 0x0E ; 14
784: 0c 94 e7 14 jmp 0x29ce ; 0x29ce <__epilogue_restores__+0x8>
 
00000788 <put_cluster>:
static
BOOL put_cluster ( /* TRUE: successful, FALSE: failed */
CLUST clust, /* Cluster# to change */
CLUST val /* New value to mark the cluster */
)
{
788: a0 e0 ldi r26, 0x00 ; 0
78a: b0 e0 ldi r27, 0x00 ; 0
78c: ea ec ldi r30, 0xCA ; 202
78e: f3 e0 ldi r31, 0x03 ; 3
790: 0c 94 cb 14 jmp 0x2996 ; 0x2996 <__prologue_saves__+0x8>
794: ec 01 movw r28, r24
796: 4b 01 movw r8, r22
WORD bc;
BYTE *p;
DWORD fatsect;
FATFS *fs = FatFs;
798: e0 90 10 01 lds r14, 0x0110
79c: f0 90 11 01 lds r15, 0x0111
 
 
fatsect = fs->fatbase;
7a0: f7 01 movw r30, r14
7a2: a0 84 ldd r10, Z+8 ; 0x08
7a4: b1 84 ldd r11, Z+9 ; 0x09
7a6: c2 84 ldd r12, Z+10 ; 0x0a
7a8: d3 84 ldd r13, Z+11 ; 0x0b
switch (fs->fs_type) {
7aa: 84 8d ldd r24, Z+28 ; 0x1c
7ac: 81 30 cpi r24, 0x01 ; 1
7ae: 21 f0 breq .+8 ; 0x7b8 <put_cluster+0x30>
7b0: 82 30 cpi r24, 0x02 ; 2
7b2: 09 f0 breq .+2 ; 0x7b6 <put_cluster+0x2e>
7b4: 72 c0 rjmp .+228 ; 0x89a <put_cluster+0x112>
7b6: 5a c0 rjmp .+180 ; 0x86c <put_cluster+0xe4>
case FS_FAT12 :
bc = (WORD)clust * 3 / 2;
7b8: 8e 01 movw r16, r28
7ba: 00 0f add r16, r16
7bc: 11 1f adc r17, r17
7be: 0c 0f add r16, r28
7c0: 1d 1f adc r17, r29
7c2: 16 95 lsr r17
7c4: 07 95 ror r16
if (!move_window(fatsect + bc / 512)) return FALSE;
7c6: b8 01 movw r22, r16
7c8: 67 2f mov r22, r23
7ca: 77 27 eor r23, r23
7cc: 66 95 lsr r22
7ce: 80 e0 ldi r24, 0x00 ; 0
7d0: 90 e0 ldi r25, 0x00 ; 0
7d2: 6a 0d add r22, r10
7d4: 7b 1d adc r23, r11
7d6: 8c 1d adc r24, r12
7d8: 9d 1d adc r25, r13
7da: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
7de: 88 23 and r24, r24
7e0: 09 f4 brne .+2 ; 0x7e4 <put_cluster+0x5c>
7e2: 5b c0 rjmp .+182 ; 0x89a <put_cluster+0x112>
p = &fs->win[bc % 512];
7e4: d8 01 movw r26, r16
7e6: b1 70 andi r27, 0x01 ; 1
*p = (clust & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
7e8: 51 e0 ldi r21, 0x01 ; 1
7ea: 65 2e mov r6, r21
7ec: 71 2c mov r7, r1
7ee: 6c 22 and r6, r28
7f0: 7d 22 and r7, r29
7f2: c0 ff sbrs r28, 0
7f4: 0a c0 rjmp .+20 ; 0x80a <put_cluster+0x82>
7f6: f7 01 movw r30, r14
7f8: ea 0f add r30, r26
7fa: fb 1f adc r31, r27
7fc: 80 a1 ldd r24, Z+32 ; 0x20
7fe: 8f 70 andi r24, 0x0F ; 15
800: 98 2d mov r25, r8
802: 92 95 swap r25
804: 90 7f andi r25, 0xF0 ; 240
806: 98 2b or r25, r24
808: 01 c0 rjmp .+2 ; 0x80c <put_cluster+0x84>
80a: 98 2d mov r25, r8
80c: ae 0d add r26, r14
80e: bf 1d adc r27, r15
810: fd 01 movw r30, r26
812: 90 a3 std Z+32, r25 ; 0x20
bc++;
814: e8 01 movw r28, r16
816: 21 96 adiw r28, 0x01 ; 1
fs->winflag = 1;
818: 81 e0 ldi r24, 0x01 ; 1
81a: f7 01 movw r30, r14
81c: 87 8f std Z+31, r24 ; 0x1f
if (!move_window(fatsect + bc / 512)) return FALSE;
81e: be 01 movw r22, r28
820: 67 2f mov r22, r23
822: 77 27 eor r23, r23
824: 66 95 lsr r22
826: 80 e0 ldi r24, 0x00 ; 0
828: 90 e0 ldi r25, 0x00 ; 0
82a: 6a 0d add r22, r10
82c: 7b 1d adc r23, r11
82e: 8c 1d adc r24, r12
830: 9d 1d adc r25, r13
832: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
836: 88 23 and r24, r24
838: 81 f1 breq .+96 ; 0x89a <put_cluster+0x112>
p = &fs->win[bc % 512];
83a: de 01 movw r26, r28
83c: b1 70 andi r27, 0x01 ; 1
*p = (clust & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
83e: 61 14 cp r6, r1
840: 71 04 cpc r7, r1
842: 39 f0 breq .+14 ; 0x852 <put_cluster+0xca>
844: 34 e0 ldi r19, 0x04 ; 4
846: 96 94 lsr r9
848: 87 94 ror r8
84a: 3a 95 dec r19
84c: e1 f7 brne .-8 ; 0x846 <put_cluster+0xbe>
84e: 98 2d mov r25, r8
850: 08 c0 rjmp .+16 ; 0x862 <put_cluster+0xda>
852: f7 01 movw r30, r14
854: ea 0f add r30, r26
856: fb 1f adc r31, r27
858: 90 a1 ldd r25, Z+32 ; 0x20
85a: 90 7f andi r25, 0xF0 ; 240
85c: 89 2d mov r24, r9
85e: 8f 70 andi r24, 0x0F ; 15
860: 98 2b or r25, r24
862: ae 0d add r26, r14
864: bf 1d adc r27, r15
866: fd 01 movw r30, r26
868: 90 a3 std Z+32, r25 ; 0x20
86a: 13 c0 rjmp .+38 ; 0x892 <put_cluster+0x10a>
break;
 
case FS_FAT16 :
if (!move_window(fatsect + clust / 256)) return FALSE;
86c: 6d 2f mov r22, r29
86e: 77 27 eor r23, r23
870: 80 e0 ldi r24, 0x00 ; 0
872: 90 e0 ldi r25, 0x00 ; 0
874: 6a 0d add r22, r10
876: 7b 1d adc r23, r11
878: 8c 1d adc r24, r12
87a: 9d 1d adc r25, r13
87c: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
880: 88 23 and r24, r24
882: 59 f0 breq .+22 ; 0x89a <put_cluster+0x112>
ST_WORD(&fs->win[((WORD)clust * 2) % 512], (WORD)val);
884: cc 0f add r28, r28
886: dd 1f adc r29, r29
888: d1 70 andi r29, 0x01 ; 1
88a: ce 0d add r28, r14
88c: df 1d adc r29, r15
88e: 99 a2 std Y+33, r9 ; 0x21
890: 88 a2 std Y+32, r8 ; 0x20
break;
#endif
default :
return FALSE;
}
fs->winflag = 1;
892: 81 e0 ldi r24, 0x01 ; 1
894: f7 01 movw r30, r14
896: 87 8f std Z+31, r24 ; 0x1f
898: 01 c0 rjmp .+2 ; 0x89c <put_cluster+0x114>
return TRUE;
89a: 80 e0 ldi r24, 0x00 ; 0
}
89c: cd b7 in r28, 0x3d ; 61
89e: de b7 in r29, 0x3e ; 62
8a0: ee e0 ldi r30, 0x0E ; 14
8a2: 0c 94 e7 14 jmp 0x29ce ; 0x29ce <__epilogue_restores__+0x8>
 
000008a6 <get_cluster>:
 
static
CLUST get_cluster ( /* 0,>=2: successful, 1: failed */
CLUST clust /* Cluster# to get the link information */
)
{
8a6: a0 e0 ldi r26, 0x00 ; 0
8a8: b0 e0 ldi r27, 0x00 ; 0
8aa: e9 e5 ldi r30, 0x59 ; 89
8ac: f4 e0 ldi r31, 0x04 ; 4
8ae: 0c 94 ce 14 jmp 0x299c ; 0x299c <__prologue_saves__+0xe>
8b2: 8c 01 movw r16, r24
WORD wc, bc;
DWORD fatsect;
FATFS *fs = FatFs;
8b4: e0 90 10 01 lds r14, 0x0110
8b8: f0 90 11 01 lds r15, 0x0111
 
 
if (clust >= 2 && clust < fs->max_clust) { /* Valid cluster# */
8bc: 82 30 cpi r24, 0x02 ; 2
8be: 91 05 cpc r25, r1
8c0: 08 f4 brcc .+2 ; 0x8c4 <get_cluster+0x1e>
8c2: 67 c0 rjmp .+206 ; 0x992 <get_cluster+0xec>
8c4: e7 01 movw r28, r14
8c6: 8e 89 ldd r24, Y+22 ; 0x16
8c8: 9f 89 ldd r25, Y+23 ; 0x17
8ca: 08 17 cp r16, r24
8cc: 19 07 cpc r17, r25
8ce: 08 f0 brcs .+2 ; 0x8d2 <get_cluster+0x2c>
8d0: 60 c0 rjmp .+192 ; 0x992 <get_cluster+0xec>
fatsect = fs->fatbase;
8d2: a8 84 ldd r10, Y+8 ; 0x08
8d4: b9 84 ldd r11, Y+9 ; 0x09
8d6: ca 84 ldd r12, Y+10 ; 0x0a
8d8: db 84 ldd r13, Y+11 ; 0x0b
switch (fs->fs_type) {
8da: 8c 8d ldd r24, Y+28 ; 0x1c
8dc: 81 30 cpi r24, 0x01 ; 1
8de: 21 f0 breq .+8 ; 0x8e8 <get_cluster+0x42>
8e0: 82 30 cpi r24, 0x02 ; 2
8e2: 09 f0 breq .+2 ; 0x8e6 <get_cluster+0x40>
8e4: 56 c0 rjmp .+172 ; 0x992 <get_cluster+0xec>
8e6: 40 c0 rjmp .+128 ; 0x968 <get_cluster+0xc2>
case FS_FAT12 :
bc = (WORD)clust * 3 / 2;
8e8: e8 01 movw r28, r16
8ea: cc 0f add r28, r28
8ec: dd 1f adc r29, r29
8ee: c0 0f add r28, r16
8f0: d1 1f adc r29, r17
8f2: d6 95 lsr r29
8f4: c7 95 ror r28
if (!move_window(fatsect + bc / 512)) break;
8f6: be 01 movw r22, r28
8f8: 67 2f mov r22, r23
8fa: 77 27 eor r23, r23
8fc: 66 95 lsr r22
8fe: 80 e0 ldi r24, 0x00 ; 0
900: 90 e0 ldi r25, 0x00 ; 0
902: 6a 0d add r22, r10
904: 7b 1d adc r23, r11
906: 8c 1d adc r24, r12
908: 9d 1d adc r25, r13
90a: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
90e: 88 23 and r24, r24
910: 09 f4 brne .+2 ; 0x914 <get_cluster+0x6e>
912: 3f c0 rjmp .+126 ; 0x992 <get_cluster+0xec>
wc = fs->win[bc % 512]; bc++;
914: fe 01 movw r30, r28
916: f1 70 andi r31, 0x01 ; 1
918: ee 0d add r30, r14
91a: ff 1d adc r31, r15
91c: 90 a0 ldd r9, Z+32 ; 0x20
91e: 21 96 adiw r28, 0x01 ; 1
if (!move_window(fatsect + bc / 512)) break;
920: be 01 movw r22, r28
922: 67 2f mov r22, r23
924: 77 27 eor r23, r23
926: 66 95 lsr r22
928: 80 e0 ldi r24, 0x00 ; 0
92a: 90 e0 ldi r25, 0x00 ; 0
92c: 6a 0d add r22, r10
92e: 7b 1d adc r23, r11
930: 8c 1d adc r24, r12
932: 9d 1d adc r25, r13
934: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
938: 88 23 and r24, r24
93a: 59 f1 breq .+86 ; 0x992 <get_cluster+0xec>
fatsect = fs->fatbase;
switch (fs->fs_type) {
case FS_FAT12 :
bc = (WORD)clust * 3 / 2;
if (!move_window(fatsect + bc / 512)) break;
wc = fs->win[bc % 512]; bc++;
93c: 29 2d mov r18, r9
93e: 30 e0 ldi r19, 0x00 ; 0
if (!move_window(fatsect + bc / 512)) break;
wc |= (WORD)fs->win[bc % 512] << 8;
940: d1 70 andi r29, 0x01 ; 1
942: ec 0e add r14, r28
944: fd 1e adc r15, r29
946: f7 01 movw r30, r14
948: 90 a1 ldd r25, Z+32 ; 0x20
94a: 80 e0 ldi r24, 0x00 ; 0
94c: 28 2b or r18, r24
94e: 39 2b or r19, r25
return (clust & 1) ? (wc >> 4) : (wc & 0xFFF);
950: 00 ff sbrs r16, 0
952: 07 c0 rjmp .+14 ; 0x962 <get_cluster+0xbc>
954: f9 01 movw r30, r18
956: 94 e0 ldi r25, 0x04 ; 4
958: f6 95 lsr r31
95a: e7 95 ror r30
95c: 9a 95 dec r25
95e: e1 f7 brne .-8 ; 0x958 <get_cluster+0xb2>
960: 1a c0 rjmp .+52 ; 0x996 <get_cluster+0xf0>
962: f9 01 movw r30, r18
964: ff 70 andi r31, 0x0F ; 15
966: 17 c0 rjmp .+46 ; 0x996 <get_cluster+0xf0>
 
case FS_FAT16 :
if (!move_window(fatsect + clust / 256)) break;
968: 61 2f mov r22, r17
96a: 77 27 eor r23, r23
96c: 80 e0 ldi r24, 0x00 ; 0
96e: 90 e0 ldi r25, 0x00 ; 0
970: 6a 0d add r22, r10
972: 7b 1d adc r23, r11
974: 8c 1d adc r24, r12
976: 9d 1d adc r25, r13
978: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
97c: 88 23 and r24, r24
97e: 49 f0 breq .+18 ; 0x992 <get_cluster+0xec>
return LD_WORD(&fs->win[((WORD)clust * 2) % 512]);
980: 00 0f add r16, r16
982: 11 1f adc r17, r17
984: 11 70 andi r17, 0x01 ; 1
986: e0 0e add r14, r16
988: f1 1e adc r15, r17
98a: e7 01 movw r28, r14
98c: e8 a1 ldd r30, Y+32 ; 0x20
98e: f9 a1 ldd r31, Y+33 ; 0x21
990: 02 c0 rjmp .+4 ; 0x996 <get_cluster+0xf0>
992: e1 e0 ldi r30, 0x01 ; 1
994: f0 e0 ldi r31, 0x00 ; 0
#endif
}
}
 
return 1; /* There is no cluster information, or an error occured */
}
996: cf 01 movw r24, r30
998: cd b7 in r28, 0x3d ; 61
99a: de b7 in r29, 0x3e ; 62
99c: eb e0 ldi r30, 0x0B ; 11
99e: 0c 94 ea 14 jmp 0x29d4 ; 0x29d4 <__epilogue_restores__+0xe>
 
000009a2 <create_chain>:
#if !_FS_READONLY
static
CLUST create_chain ( /* 0: no free cluster, 1: error, >=2: new cluster number */
CLUST clust /* Cluster# to stretch, 0 means create new */
)
{
9a2: a0 e0 ldi r26, 0x00 ; 0
9a4: b0 e0 ldi r27, 0x00 ; 0
9a6: e7 ed ldi r30, 0xD7 ; 215
9a8: f4 e0 ldi r31, 0x04 ; 4
9aa: 0c 94 cf 14 jmp 0x299e ; 0x299e <__prologue_saves__+0x10>
9ae: 7c 01 movw r14, r24
CLUST cstat, ncl, scl, mcl;
FATFS *fs = FatFs;
9b0: c0 90 10 01 lds r12, 0x0110
9b4: d0 90 11 01 lds r13, 0x0111
 
 
mcl = fs->max_clust;
9b8: f6 01 movw r30, r12
9ba: a6 88 ldd r10, Z+22 ; 0x16
9bc: b7 88 ldd r11, Z+23 ; 0x17
if (clust == 0) { /* Create new chain */
9be: 00 97 sbiw r24, 0x00 ; 0
9c0: 49 f4 brne .+18 ; 0x9d4 <create_chain+0x32>
scl = fs->last_clust; /* Get last allocated cluster */
9c2: 00 8d ldd r16, Z+24 ; 0x18
9c4: 11 8d ldd r17, Z+25 ; 0x19
if (scl < 2 || scl >= mcl) scl = 1;
9c6: 02 30 cpi r16, 0x02 ; 2
9c8: 11 05 cpc r17, r1
9ca: 88 f0 brcs .+34 ; 0x9ee <create_chain+0x4c>
9cc: 0a 15 cp r16, r10
9ce: 1b 05 cpc r17, r11
9d0: 70 f4 brcc .+28 ; 0x9ee <create_chain+0x4c>
9d2: 0f c0 rjmp .+30 ; 0x9f2 <create_chain+0x50>
}
else { /* Stretch existing chain */
cstat = get_cluster(clust); /* Check the cluster status */
9d4: 0e 94 53 04 call 0x8a6 ; 0x8a6 <get_cluster>
9d8: 9c 01 movw r18, r24
if (cstat < 2) return 1; /* It is an invalid cluster */
9da: 82 30 cpi r24, 0x02 ; 2
9dc: 91 05 cpc r25, r1
9de: 08 f4 brcc .+2 ; 0x9e2 <create_chain+0x40>
9e0: 40 c0 rjmp .+128 ; 0xa62 <create_chain+0xc0>
if (cstat < mcl) return cstat; /* It is already followed by next cluster */
9e2: 8a 15 cp r24, r10
9e4: 9b 05 cpc r25, r11
9e6: 08 f4 brcc .+2 ; 0x9ea <create_chain+0x48>
9e8: 41 c0 rjmp .+130 ; 0xa6c <create_chain+0xca>
9ea: 87 01 movw r16, r14
9ec: 02 c0 rjmp .+4 ; 0x9f2 <create_chain+0x50>
9ee: 01 e0 ldi r16, 0x01 ; 1
9f0: 10 e0 ldi r17, 0x00 ; 0
9f2: e8 01 movw r28, r16
scl = clust;
}
 
ncl = scl; /* Start cluster */
for (;;) {
ncl++; /* Next cluster */
9f4: 21 96 adiw r28, 0x01 ; 1
if (ncl >= mcl) { /* Wrap around */
9f6: ca 15 cp r28, r10
9f8: db 05 cpc r29, r11
9fa: 28 f0 brcs .+10 ; 0xa06 <create_chain+0x64>
ncl = 2;
if (ncl > scl) return 0; /* No free custer */
9fc: 02 30 cpi r16, 0x02 ; 2
9fe: 11 05 cpc r17, r1
a00: 98 f1 brcs .+102 ; 0xa68 <create_chain+0xc6>
a02: c2 e0 ldi r28, 0x02 ; 2
a04: d0 e0 ldi r29, 0x00 ; 0
}
cstat = get_cluster(ncl); /* Get the cluster status */
a06: ce 01 movw r24, r28
a08: 0e 94 53 04 call 0x8a6 ; 0x8a6 <get_cluster>
a0c: 9c 01 movw r18, r24
if (cstat == 0) break; /* Found a free cluster */
a0e: 00 97 sbiw r24, 0x00 ; 0
a10: 39 f0 breq .+14 ; 0xa20 <create_chain+0x7e>
if (cstat == 1) return 1; /* Any error occured */
a12: 81 30 cpi r24, 0x01 ; 1
a14: 91 05 cpc r25, r1
a16: 51 f1 breq .+84 ; 0xa6c <create_chain+0xca>
if (ncl == scl) return 0; /* No free custer */
a18: c0 17 cp r28, r16
a1a: d1 07 cpc r29, r17
a1c: 59 f7 brne .-42 ; 0x9f4 <create_chain+0x52>
a1e: 24 c0 rjmp .+72 ; 0xa68 <create_chain+0xc6>
a20: 1c 2f mov r17, r28
a22: 0d 2f mov r16, r29
}
 
if (!put_cluster(ncl, (CLUST)0x0FFFFFFF)) return 1; /* Mark the new cluster "in use" */
a24: 6f ef ldi r22, 0xFF ; 255
a26: 7f ef ldi r23, 0xFF ; 255
a28: ce 01 movw r24, r28
a2a: 0e 94 c4 03 call 0x788 ; 0x788 <put_cluster>
a2e: 88 23 and r24, r24
a30: c1 f0 breq .+48 ; 0xa62 <create_chain+0xc0>
if (clust && !put_cluster(clust, ncl)) return 1; /* Link it to previous one if needed */
a32: e1 14 cp r14, r1
a34: f1 04 cpc r15, r1
a36: 31 f0 breq .+12 ; 0xa44 <create_chain+0xa2>
a38: be 01 movw r22, r28
a3a: c7 01 movw r24, r14
a3c: 0e 94 c4 03 call 0x788 ; 0x788 <put_cluster>
a40: 88 23 and r24, r24
a42: 79 f0 breq .+30 ; 0xa62 <create_chain+0xc0>
 
fs->last_clust = ncl; /* Update fsinfo */
a44: f6 01 movw r30, r12
a46: 10 8f std Z+24, r17 ; 0x18
a48: 01 8f std Z+25, r16 ; 0x19
if (fs->free_clust != (CLUST)0xFFFFFFFF) {
a4a: 82 8d ldd r24, Z+26 ; 0x1a
a4c: 93 8d ldd r25, Z+27 ; 0x1b
a4e: ff ef ldi r31, 0xFF ; 255
a50: 8f 3f cpi r24, 0xFF ; 255
a52: 9f 07 cpc r25, r31
a54: 21 f0 breq .+8 ; 0xa5e <create_chain+0xbc>
fs->free_clust--;
a56: 01 97 sbiw r24, 0x01 ; 1
a58: f6 01 movw r30, r12
a5a: 93 8f std Z+27, r25 ; 0x1b
a5c: 82 8f std Z+26, r24 ; 0x1a
a5e: 9e 01 movw r18, r28
a60: 05 c0 rjmp .+10 ; 0xa6c <create_chain+0xca>
a62: 21 e0 ldi r18, 0x01 ; 1
a64: 30 e0 ldi r19, 0x00 ; 0
a66: 02 c0 rjmp .+4 ; 0xa6c <create_chain+0xca>
a68: 20 e0 ldi r18, 0x00 ; 0
a6a: 30 e0 ldi r19, 0x00 ; 0
fs->fsi_flag = 1;
#endif
}
 
return ncl; /* Return new cluster number */
}
a6c: c9 01 movw r24, r18
a6e: cd b7 in r28, 0x3d ; 61
a70: de b7 in r29, 0x3e ; 62
a72: ea e0 ldi r30, 0x0A ; 10
a74: 0c 94 eb 14 jmp 0x29d6 ; 0x29d6 <__epilogue_restores__+0x10>
 
00000a78 <f_lseek>:
 
FRESULT f_lseek (
FIL *fp, /* Pointer to the file object */
DWORD ofs /* File pointer from top of file */
)
{
a78: a0 e0 ldi r26, 0x00 ; 0
a7a: b0 e0 ldi r27, 0x00 ; 0
a7c: e2 e4 ldi r30, 0x42 ; 66
a7e: f5 e0 ldi r31, 0x05 ; 5
a80: 0c 94 cb 14 jmp 0x2996 ; 0x2996 <__prologue_saves__+0x8>
a84: ec 01 movw r28, r24
a86: 7a 01 movw r14, r20
a88: 8b 01 movw r16, r22
CLUST clust;
DWORD csize;
BYTE csect;
FRESULT res;
FATFS *fs = fp->fs;
a8a: 6c 80 ldd r6, Y+4 ; 0x04
a8c: 7d 80 ldd r7, Y+5 ; 0x05
 
 
res = validate(fs, fp->id); /* Check validity of the object */
a8e: 68 81 ld r22, Y
a90: 79 81 ldd r23, Y+1 ; 0x01
a92: c3 01 movw r24, r6
a94: 0e 94 46 03 call 0x68c ; 0x68c <validate>
a98: 4c 01 movw r8, r24
if (res) return res;
a9a: 00 97 sbiw r24, 0x00 ; 0
a9c: 09 f0 breq .+2 ; 0xaa0 <f_lseek+0x28>
a9e: d6 c0 rjmp .+428 ; 0xc4c <f_lseek+0x1d4>
 
if (fp->flag & FA__ERROR) return FR_RW_ERROR;
aa0: 8a 81 ldd r24, Y+2 ; 0x02
aa2: 87 fd sbrc r24, 7
aa4: d0 c0 rjmp .+416 ; 0xc46 <f_lseek+0x1ce>
#if !_FS_READONLY
if (ofs > fp->fsize && !(fp->flag & FA_WRITE))
aa6: aa 84 ldd r10, Y+10 ; 0x0a
aa8: bb 84 ldd r11, Y+11 ; 0x0b
aaa: cc 84 ldd r12, Y+12 ; 0x0c
aac: dd 84 ldd r13, Y+13 ; 0x0d
aae: ae 14 cp r10, r14
ab0: bf 04 cpc r11, r15
ab2: c0 06 cpc r12, r16
ab4: d1 06 cpc r13, r17
ab6: 10 f4 brcc .+4 ; 0xabc <f_lseek+0x44>
ab8: 81 ff sbrs r24, 1
aba: 02 c0 rjmp .+4 ; 0xac0 <f_lseek+0x48>
abc: 57 01 movw r10, r14
abe: 68 01 movw r12, r16
#else
if (ofs > fp->fsize)
#endif
ofs = fp->fsize;
fp->fptr = 0; fp->sect_clust = 1; /* Set file R/W pointer to top of the file */
ac0: 1e 82 std Y+6, r1 ; 0x06
ac2: 1f 82 std Y+7, r1 ; 0x07
ac4: 18 86 std Y+8, r1 ; 0x08
ac6: 19 86 std Y+9, r1 ; 0x09
ac8: 81 e0 ldi r24, 0x01 ; 1
aca: 8b 83 std Y+3, r24 ; 0x03
 
/* Move file R/W pointer if needed */
if (ofs) {
acc: a1 14 cp r10, r1
ace: b1 04 cpc r11, r1
ad0: c1 04 cpc r12, r1
ad2: d1 04 cpc r13, r1
ad4: 09 f4 brne .+2 ; 0xad8 <f_lseek+0x60>
ad6: 9d c0 rjmp .+314 ; 0xc12 <f_lseek+0x19a>
clust = fp->org_clust; /* Get start cluster */
ad8: 6e 85 ldd r22, Y+14 ; 0x0e
ada: 7f 85 ldd r23, Y+15 ; 0x0f
#if !_FS_READONLY
if (!clust) { /* If the file does not have a cluster chain, create new cluster chain */
adc: 61 15 cp r22, r1
ade: 71 05 cpc r23, r1
ae0: 71 f4 brne .+28 ; 0xafe <f_lseek+0x86>
clust = create_chain(0);
ae2: 80 e0 ldi r24, 0x00 ; 0
ae4: 90 e0 ldi r25, 0x00 ; 0
ae6: 0e 94 d1 04 call 0x9a2 ; 0x9a2 <create_chain>
aea: bc 01 movw r22, r24
if (clust == 1) goto fk_error;
aec: 81 30 cpi r24, 0x01 ; 1
aee: 91 05 cpc r25, r1
af0: 09 f4 brne .+2 ; 0xaf4 <f_lseek+0x7c>
af2: a6 c0 rjmp .+332 ; 0xc40 <f_lseek+0x1c8>
fp->org_clust = clust;
af4: 9f 87 std Y+15, r25 ; 0x0f
af6: 8e 87 std Y+14, r24 ; 0x0e
}
#endif
if (clust) { /* If the file has a cluster chain, it can be followed */
af8: 00 97 sbiw r24, 0x00 ; 0
afa: 09 f4 brne .+2 ; 0xafe <f_lseek+0x86>
afc: 8a c0 rjmp .+276 ; 0xc12 <f_lseek+0x19a>
csize = (DWORD)fs->sects_clust * 512; /* Cluster size in unit of byte */
afe: f3 01 movw r30, r6
b00: 85 8d ldd r24, Z+29 ; 0x1d
b02: e8 2e mov r14, r24
b04: ff 24 eor r15, r15
b06: 00 e0 ldi r16, 0x00 ; 0
b08: 10 e0 ldi r17, 0x00 ; 0
b0a: f9 e0 ldi r31, 0x09 ; 9
b0c: ee 0c add r14, r14
b0e: ff 1c adc r15, r15
b10: 00 1f adc r16, r16
b12: 11 1f adc r17, r17
b14: fa 95 dec r31
b16: d1 f7 brne .-12 ; 0xb0c <f_lseek+0x94>
for (;;) { /* Loop to skip leading clusters */
fp->curr_clust = clust; /* Update current cluster */
b18: 79 8b std Y+17, r23 ; 0x11
b1a: 68 8b std Y+16, r22 ; 0x10
if (ofs <= csize) break;
b1c: ea 14 cp r14, r10
b1e: fb 04 cpc r15, r11
b20: 0c 05 cpc r16, r12
b22: 1d 05 cpc r17, r13
b24: 58 f5 brcc .+86 ; 0xb7c <f_lseek+0x104>
#if !_FS_READONLY
if (fp->flag & FA_WRITE) /* Check if in write mode or not */
b26: 8a 81 ldd r24, Y+2 ; 0x02
b28: 81 ff sbrs r24, 1
b2a: 04 c0 rjmp .+8 ; 0xb34 <f_lseek+0xbc>
clust = create_chain(clust); /* Force streached if in write mode */
b2c: cb 01 movw r24, r22
b2e: 0e 94 d1 04 call 0x9a2 ; 0x9a2 <create_chain>
b32: 03 c0 rjmp .+6 ; 0xb3a <f_lseek+0xc2>
else
#endif
clust = get_cluster(clust); /* Only follow cluster chain if not in write mode */
b34: cb 01 movw r24, r22
b36: 0e 94 53 04 call 0x8a6 ; 0x8a6 <get_cluster>
b3a: bc 01 movw r22, r24
if (clust == 0) { /* Stop if could not follow the cluster chain */
b3c: 00 97 sbiw r24, 0x00 ; 0
b3e: e1 f0 breq .+56 ; 0xb78 <f_lseek+0x100>
ofs = csize; break;
}
if (clust == 1 || clust >= fs->max_clust) goto fk_error;
b40: 81 30 cpi r24, 0x01 ; 1
b42: 91 05 cpc r25, r1
b44: 09 f4 brne .+2 ; 0xb48 <f_lseek+0xd0>
b46: 7c c0 rjmp .+248 ; 0xc40 <f_lseek+0x1c8>
b48: f3 01 movw r30, r6
b4a: 86 89 ldd r24, Z+22 ; 0x16
b4c: 97 89 ldd r25, Z+23 ; 0x17
b4e: 68 17 cp r22, r24
b50: 79 07 cpc r23, r25
b52: 08 f0 brcs .+2 ; 0xb56 <f_lseek+0xde>
b54: 75 c0 rjmp .+234 ; 0xc40 <f_lseek+0x1c8>
fp->fptr += csize; /* Update R/W pointer */
b56: 8e 81 ldd r24, Y+6 ; 0x06
b58: 9f 81 ldd r25, Y+7 ; 0x07
b5a: a8 85 ldd r26, Y+8 ; 0x08
b5c: b9 85 ldd r27, Y+9 ; 0x09
b5e: 8e 0d add r24, r14
b60: 9f 1d adc r25, r15
b62: a0 1f adc r26, r16
b64: b1 1f adc r27, r17
b66: 8e 83 std Y+6, r24 ; 0x06
b68: 9f 83 std Y+7, r25 ; 0x07
b6a: a8 87 std Y+8, r26 ; 0x08
b6c: b9 87 std Y+9, r27 ; 0x09
ofs -= csize;
b6e: ae 18 sub r10, r14
b70: bf 08 sbc r11, r15
b72: c0 0a sbc r12, r16
b74: d1 0a sbc r13, r17
b76: d0 cf rjmp .-96 ; 0xb18 <f_lseek+0xa0>
}
b78: 57 01 movw r10, r14
b7a: 68 01 movw r12, r16
csect = (BYTE)((ofs - 1) / 512); /* Sector offset in the cluster */
b7c: d6 01 movw r26, r12
b7e: c5 01 movw r24, r10
b80: 01 97 sbiw r24, 0x01 ; 1
b82: a1 09 sbc r26, r1
b84: b1 09 sbc r27, r1
b86: e9 e0 ldi r30, 0x09 ; 9
b88: b6 95 lsr r27
b8a: a7 95 ror r26
b8c: 97 95 ror r25
b8e: 87 95 ror r24
b90: ea 95 dec r30
b92: d1 f7 brne .-12 ; 0xb88 <f_lseek+0x110>
b94: f8 2e mov r15, r24
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
CLUST clust /* Cluster# to be converted */
)
{
FATFS *fs = FatFs;
b96: 00 91 10 01 lds r16, 0x0110
b9a: 10 91 11 01 lds r17, 0x0111
 
 
clust -= 2;
b9e: 62 50 subi r22, 0x02 ; 2
ba0: 70 40 sbci r23, 0x00 ; 0
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
ba2: f8 01 movw r30, r16
ba4: 86 89 ldd r24, Z+22 ; 0x16
ba6: 97 89 ldd r25, Z+23 ; 0x17
ba8: 02 97 sbiw r24, 0x02 ; 2
baa: 68 17 cp r22, r24
bac: 79 07 cpc r23, r25
bae: 28 f0 brcs .+10 ; 0xbba <f_lseek+0x142>
bb0: 20 e0 ldi r18, 0x00 ; 0
bb2: 30 e0 ldi r19, 0x00 ; 0
bb4: 40 e0 ldi r20, 0x00 ; 0
bb6: 50 e0 ldi r21, 0x00 ; 0
bb8: 14 c0 rjmp .+40 ; 0xbe2 <f_lseek+0x16a>
return (DWORD)clust * fs->sects_clust + fs->database;
bba: 80 e0 ldi r24, 0x00 ; 0
bbc: 90 e0 ldi r25, 0x00 ; 0
bbe: f8 01 movw r30, r16
bc0: 25 8d ldd r18, Z+29 ; 0x1d
bc2: 30 e0 ldi r19, 0x00 ; 0
bc4: 40 e0 ldi r20, 0x00 ; 0
bc6: 50 e0 ldi r21, 0x00 ; 0
bc8: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
bcc: 9b 01 movw r18, r22
bce: ac 01 movw r20, r24
bd0: f8 01 movw r30, r16
bd2: 80 89 ldd r24, Z+16 ; 0x10
bd4: 91 89 ldd r25, Z+17 ; 0x11
bd6: a2 89 ldd r26, Z+18 ; 0x12
bd8: b3 89 ldd r27, Z+19 ; 0x13
bda: 28 0f add r18, r24
bdc: 39 1f adc r19, r25
bde: 4a 1f adc r20, r26
be0: 5b 1f adc r21, r27
if (clust == 1 || clust >= fs->max_clust) goto fk_error;
fp->fptr += csize; /* Update R/W pointer */
ofs -= csize;
}
csect = (BYTE)((ofs - 1) / 512); /* Sector offset in the cluster */
fp->curr_sect = clust2sect(clust) + csect; /* Current sector */
be2: 2f 0d add r18, r15
be4: 31 1d adc r19, r1
be6: 41 1d adc r20, r1
be8: 51 1d adc r21, r1
bea: 2a 8b std Y+18, r18 ; 0x12
bec: 3b 8b std Y+19, r19 ; 0x13
bee: 4c 8b std Y+20, r20 ; 0x14
bf0: 5d 8b std Y+21, r21 ; 0x15
fp->sect_clust = fs->sects_clust - csect; /* Left sector counter in the cluster */
bf2: f3 01 movw r30, r6
bf4: 85 8d ldd r24, Z+29 ; 0x1d
bf6: 8f 19 sub r24, r15
bf8: 8b 83 std Y+3, r24 ; 0x03
fp->fptr += ofs; /* Update file R/W pointer */
bfa: 8e 81 ldd r24, Y+6 ; 0x06
bfc: 9f 81 ldd r25, Y+7 ; 0x07
bfe: a8 85 ldd r26, Y+8 ; 0x08
c00: b9 85 ldd r27, Y+9 ; 0x09
c02: 8a 0d add r24, r10
c04: 9b 1d adc r25, r11
c06: ac 1d adc r26, r12
c08: bd 1d adc r27, r13
c0a: 8e 83 std Y+6, r24 ; 0x06
c0c: 9f 83 std Y+7, r25 ; 0x07
c0e: a8 87 std Y+8, r26 ; 0x08
c10: b9 87 std Y+9, r27 ; 0x09
}
}
#if !_FS_READONLY
if ((fp->flag & FA_WRITE) && fp->fptr > fp->fsize) { /* Set updated flag if in write mode */
c12: 6a 81 ldd r22, Y+2 ; 0x02
c14: 61 ff sbrs r22, 1
c16: 1a c0 rjmp .+52 ; 0xc4c <f_lseek+0x1d4>
c18: 2e 81 ldd r18, Y+6 ; 0x06
c1a: 3f 81 ldd r19, Y+7 ; 0x07
c1c: 48 85 ldd r20, Y+8 ; 0x08
c1e: 59 85 ldd r21, Y+9 ; 0x09
c20: 8a 85 ldd r24, Y+10 ; 0x0a
c22: 9b 85 ldd r25, Y+11 ; 0x0b
c24: ac 85 ldd r26, Y+12 ; 0x0c
c26: bd 85 ldd r27, Y+13 ; 0x0d
c28: 82 17 cp r24, r18
c2a: 93 07 cpc r25, r19
c2c: a4 07 cpc r26, r20
c2e: b5 07 cpc r27, r21
c30: 68 f4 brcc .+26 ; 0xc4c <f_lseek+0x1d4>
fp->fsize = fp->fptr;
c32: 2a 87 std Y+10, r18 ; 0x0a
c34: 3b 87 std Y+11, r19 ; 0x0b
c36: 4c 87 std Y+12, r20 ; 0x0c
c38: 5d 87 std Y+13, r21 ; 0x0d
fp->flag |= FA__WRITTEN;
c3a: 60 62 ori r22, 0x20 ; 32
c3c: 6a 83 std Y+2, r22 ; 0x02
c3e: 06 c0 rjmp .+12 ; 0xc4c <f_lseek+0x1d4>
#endif
 
return FR_OK;
 
fk_error: /* Abort this function due to an unrecoverable error */
fp->flag |= FA__ERROR;
c40: 8a 81 ldd r24, Y+2 ; 0x02
c42: 80 68 ori r24, 0x80 ; 128
c44: 8a 83 std Y+2, r24 ; 0x02
c46: 68 e0 ldi r22, 0x08 ; 8
c48: 86 2e mov r8, r22
c4a: 91 2c mov r9, r1
return FR_RW_ERROR;
}
c4c: c4 01 movw r24, r8
c4e: cd b7 in r28, 0x3d ; 61
c50: de b7 in r29, 0x3e ; 62
c52: ee e0 ldi r30, 0x0E ; 14
c54: 0c 94 e7 14 jmp 0x29ce ; 0x29ce <__epilogue_restores__+0x8>
 
00000c58 <next_dir_entry>:
 
static
BOOL next_dir_entry ( /* TRUE: successful, FALSE: could not move next */
DIR *dirobj /* Pointer to directory object */
)
{
c58: ef 92 push r14
c5a: ff 92 push r15
c5c: 0f 93 push r16
c5e: 1f 93 push r17
c60: cf 93 push r28
c62: df 93 push r29
c64: 8c 01 movw r16, r24
CLUST clust;
WORD idx;
FATFS *fs = FatFs;
c66: c0 91 10 01 lds r28, 0x0110
c6a: d0 91 11 01 lds r29, 0x0111
 
 
idx = dirobj->index + 1;
c6e: fc 01 movw r30, r24
c70: e2 80 ldd r14, Z+2 ; 0x02
c72: f3 80 ldd r15, Z+3 ; 0x03
c74: 08 94 sec
c76: e1 1c adc r14, r1
c78: f1 1c adc r15, r1
if ((idx & 15) == 0) { /* Table sector changed? */
c7a: c7 01 movw r24, r14
c7c: 8f 70 andi r24, 0x0F ; 15
c7e: 90 70 andi r25, 0x00 ; 0
c80: 89 2b or r24, r25
c82: 09 f0 breq .+2 ; 0xc86 <next_dir_entry+0x2e>
c84: 5b c0 rjmp .+182 ; 0xd3c <next_dir_entry+0xe4>
dirobj->sect++; /* Next sector */
c86: 82 85 ldd r24, Z+10 ; 0x0a
c88: 93 85 ldd r25, Z+11 ; 0x0b
c8a: a4 85 ldd r26, Z+12 ; 0x0c
c8c: b5 85 ldd r27, Z+13 ; 0x0d
c8e: 01 96 adiw r24, 0x01 ; 1
c90: a1 1d adc r26, r1
c92: b1 1d adc r27, r1
c94: 82 87 std Z+10, r24 ; 0x0a
c96: 93 87 std Z+11, r25 ; 0x0b
c98: a4 87 std Z+12, r26 ; 0x0c
c9a: b5 87 std Z+13, r27 ; 0x0d
if (!dirobj->clust) { /* In static table */
c9c: 40 85 ldd r20, Z+8 ; 0x08
c9e: 51 85 ldd r21, Z+9 ; 0x09
ca0: 41 15 cp r20, r1
ca2: 51 05 cpc r21, r1
ca4: 39 f4 brne .+14 ; 0xcb4 <next_dir_entry+0x5c>
if (idx >= fs->n_rootdir) return FALSE; /* Reached to end of table */
ca6: 8a 81 ldd r24, Y+2 ; 0x02
ca8: 9b 81 ldd r25, Y+3 ; 0x03
caa: e8 16 cp r14, r24
cac: f9 06 cpc r15, r25
cae: 08 f4 brcc .+2 ; 0xcb2 <next_dir_entry+0x5a>
cb0: 45 c0 rjmp .+138 ; 0xd3c <next_dir_entry+0xe4>
cb2: 49 c0 rjmp .+146 ; 0xd46 <next_dir_entry+0xee>
} else { /* In dynamic table */
if (((idx / 16) & (fs->sects_clust - 1)) == 0) { /* Cluster changed? */
cb4: 8d 8d ldd r24, Y+29 ; 0x1d
cb6: 90 e0 ldi r25, 0x00 ; 0
cb8: 01 97 sbiw r24, 0x01 ; 1
cba: 97 01 movw r18, r14
cbc: a4 e0 ldi r26, 0x04 ; 4
cbe: 36 95 lsr r19
cc0: 27 95 ror r18
cc2: aa 95 dec r26
cc4: e1 f7 brne .-8 ; 0xcbe <next_dir_entry+0x66>
cc6: 82 23 and r24, r18
cc8: 93 23 and r25, r19
cca: 89 2b or r24, r25
ccc: b9 f5 brne .+110 ; 0xd3c <next_dir_entry+0xe4>
clust = get_cluster(dirobj->clust); /* Get next cluster */
cce: ca 01 movw r24, r20
cd0: 0e 94 53 04 call 0x8a6 ; 0x8a6 <get_cluster>
cd4: bc 01 movw r22, r24
if (clust < 2 || clust >= fs->max_clust) /* Reached to end of table */
cd6: 82 30 cpi r24, 0x02 ; 2
cd8: 91 05 cpc r25, r1
cda: a8 f1 brcs .+106 ; 0xd46 <next_dir_entry+0xee>
cdc: 8e 89 ldd r24, Y+22 ; 0x16
cde: 9f 89 ldd r25, Y+23 ; 0x17
ce0: 68 17 cp r22, r24
ce2: 79 07 cpc r23, r25
ce4: 80 f5 brcc .+96 ; 0xd46 <next_dir_entry+0xee>
return FALSE;
dirobj->clust = clust; /* Initialize for new cluster */
ce6: f8 01 movw r30, r16
ce8: 71 87 std Z+9, r23 ; 0x09
cea: 60 87 std Z+8, r22 ; 0x08
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
CLUST clust /* Cluster# to be converted */
)
{
FATFS *fs = FatFs;
cec: c0 91 10 01 lds r28, 0x0110
cf0: d0 91 11 01 lds r29, 0x0111
 
 
clust -= 2;
cf4: 62 50 subi r22, 0x02 ; 2
cf6: 70 40 sbci r23, 0x00 ; 0
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
cf8: 8e 89 ldd r24, Y+22 ; 0x16
cfa: 9f 89 ldd r25, Y+23 ; 0x17
cfc: 02 97 sbiw r24, 0x02 ; 2
cfe: 68 17 cp r22, r24
d00: 79 07 cpc r23, r25
d02: 28 f0 brcs .+10 ; 0xd0e <next_dir_entry+0xb6>
d04: 20 e0 ldi r18, 0x00 ; 0
d06: 30 e0 ldi r19, 0x00 ; 0
d08: 40 e0 ldi r20, 0x00 ; 0
d0a: 50 e0 ldi r21, 0x00 ; 0
d0c: 12 c0 rjmp .+36 ; 0xd32 <next_dir_entry+0xda>
return (DWORD)clust * fs->sects_clust + fs->database;
d0e: 80 e0 ldi r24, 0x00 ; 0
d10: 90 e0 ldi r25, 0x00 ; 0
d12: 2d 8d ldd r18, Y+29 ; 0x1d
d14: 30 e0 ldi r19, 0x00 ; 0
d16: 40 e0 ldi r20, 0x00 ; 0
d18: 50 e0 ldi r21, 0x00 ; 0
d1a: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
d1e: 9b 01 movw r18, r22
d20: ac 01 movw r20, r24
d22: 88 89 ldd r24, Y+16 ; 0x10
d24: 99 89 ldd r25, Y+17 ; 0x11
d26: aa 89 ldd r26, Y+18 ; 0x12
d28: bb 89 ldd r27, Y+19 ; 0x13
d2a: 28 0f add r18, r24
d2c: 39 1f adc r19, r25
d2e: 4a 1f adc r20, r26
d30: 5b 1f adc r21, r27
if (((idx / 16) & (fs->sects_clust - 1)) == 0) { /* Cluster changed? */
clust = get_cluster(dirobj->clust); /* Get next cluster */
if (clust < 2 || clust >= fs->max_clust) /* Reached to end of table */
return FALSE;
dirobj->clust = clust; /* Initialize for new cluster */
dirobj->sect = clust2sect(clust);
d32: f8 01 movw r30, r16
d34: 22 87 std Z+10, r18 ; 0x0a
d36: 33 87 std Z+11, r19 ; 0x0b
d38: 44 87 std Z+12, r20 ; 0x0c
d3a: 55 87 std Z+13, r21 ; 0x0d
}
}
}
dirobj->index = idx; /* Lower 4 bit of dirobj->index indicates offset in dirobj->sect */
d3c: f8 01 movw r30, r16
d3e: f3 82 std Z+3, r15 ; 0x03
d40: e2 82 std Z+2, r14 ; 0x02
d42: 81 e0 ldi r24, 0x01 ; 1
d44: 01 c0 rjmp .+2 ; 0xd48 <next_dir_entry+0xf0>
return TRUE;
d46: 80 e0 ldi r24, 0x00 ; 0
}
d48: cd b7 in r28, 0x3d ; 61
d4a: de b7 in r29, 0x3e ; 62
d4c: e6 e0 ldi r30, 0x06 ; 6
d4e: 0c 94 ef 14 jmp 0x29de ; 0x29de <__epilogue_restores__+0x18>
 
00000d52 <f_sync>:
/*-----------------------------------------------------------------------*/
 
FRESULT f_sync (
FIL *fp /* Pointer to the file object */
)
{
d52: ef 92 push r14
d54: ff 92 push r15
d56: 0f 93 push r16
d58: 1f 93 push r17
d5a: cf 93 push r28
d5c: df 93 push r29
d5e: ec 01 movw r28, r24
BYTE *dir;
FRESULT res;
FATFS *fs = fp->fs;
 
 
res = validate(fs, fp->id); /* Check validity of the object */
d60: 68 81 ld r22, Y
d62: 79 81 ldd r23, Y+1 ; 0x01
d64: 8c 81 ldd r24, Y+4 ; 0x04
d66: 9d 81 ldd r25, Y+5 ; 0x05
d68: 0e 94 46 03 call 0x68c ; 0x68c <validate>
d6c: 7c 01 movw r14, r24
if (res == FR_OK) {
d6e: 00 97 sbiw r24, 0x00 ; 0
d70: 09 f0 breq .+2 ; 0xd74 <f_sync+0x22>
d72: 40 c0 rjmp .+128 ; 0xdf4 <f_sync+0xa2>
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
d74: 8a 81 ldd r24, Y+2 ; 0x02
d76: 85 ff sbrs r24, 5
d78: 3d c0 rjmp .+122 ; 0xdf4 <f_sync+0xa2>
/* Update the directory entry */
if (!move_window(fp->dir_sect))
d7a: 6e 89 ldd r22, Y+22 ; 0x16
d7c: 7f 89 ldd r23, Y+23 ; 0x17
d7e: 88 8d ldd r24, Y+24 ; 0x18
d80: 99 8d ldd r25, Y+25 ; 0x19
d82: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
d86: 88 23 and r24, r24
d88: 91 f1 breq .+100 ; 0xdee <f_sync+0x9c>
return FR_RW_ERROR;
dir = fp->dir_ptr;
d8a: 0a 8d ldd r16, Y+26 ; 0x1a
d8c: 1b 8d ldd r17, Y+27 ; 0x1b
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
d8e: f8 01 movw r30, r16
d90: 83 85 ldd r24, Z+11 ; 0x0b
d92: 80 62 ori r24, 0x20 ; 32
d94: 83 87 std Z+11, r24 ; 0x0b
ST_DWORD(&dir[DIR_FileSize], fp->fsize); /* Update file size */
d96: 8a 85 ldd r24, Y+10 ; 0x0a
d98: 9b 85 ldd r25, Y+11 ; 0x0b
d9a: ac 85 ldd r26, Y+12 ; 0x0c
d9c: bd 85 ldd r27, Y+13 ; 0x0d
d9e: 84 8f std Z+28, r24 ; 0x1c
da0: 95 8f std Z+29, r25 ; 0x1d
da2: a6 8f std Z+30, r26 ; 0x1e
da4: b7 8f std Z+31, r27 ; 0x1f
ST_WORD(&dir[DIR_FstClusLO], fp->org_clust); /* Update start cluster */
da6: 8e 85 ldd r24, Y+14 ; 0x0e
da8: 9f 85 ldd r25, Y+15 ; 0x0f
daa: 93 8f std Z+27, r25 ; 0x1b
dac: 82 8f std Z+26, r24 ; 0x1a
#if _FAT32
ST_WORD(&dir[DIR_FstClusHI], fp->org_clust >> 16);
#endif
tim = get_fattime(); /* Updated time */
dae: 0e 94 b0 00 call 0x160 ; 0x160 <get_fattime>
ST_DWORD(&dir[DIR_WrtTime], tim);
db2: f8 01 movw r30, r16
db4: 66 8b std Z+22, r22 ; 0x16
db6: 77 8b std Z+23, r23 ; 0x17
db8: 80 8f std Z+24, r24 ; 0x18
dba: 91 8f std Z+25, r25 ; 0x19
fp->flag &= ~FA__WRITTEN;
dbc: 8a 81 ldd r24, Y+2 ; 0x02
dbe: 8f 7d andi r24, 0xDF ; 223
dc0: 8a 83 std Y+2, r24 ; 0x02
FRESULT sync (void) /* FR_OK: successful, FR_RW_ERROR: failed */
{
FATFS *fs = FatFs;
 
 
fs->winflag = 1;
dc2: e0 91 10 01 lds r30, 0x0110
dc6: f0 91 11 01 lds r31, 0x0111
dca: 81 e0 ldi r24, 0x01 ; 1
dcc: 87 8f std Z+31, r24 ; 0x1f
if (!move_window(0)) return FR_RW_ERROR;
dce: 60 e0 ldi r22, 0x00 ; 0
dd0: 70 e0 ldi r23, 0x00 ; 0
dd2: 80 e0 ldi r24, 0x00 ; 0
dd4: 90 e0 ldi r25, 0x00 ; 0
dd6: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
dda: 88 23 and r24, r24
ddc: 41 f0 breq .+16 ; 0xdee <f_sync+0x9c>
ST_DWORD(&fs->win[FSI_Nxt_Free], fs->last_clust);
disk_write(0, fs->win, fs->fsi_sector, 1);
fs->fsi_flag = 0;
}
#endif
if (disk_ioctl(0, CTRL_SYNC, NULL) != RES_OK) return FR_RW_ERROR;
dde: 40 e0 ldi r20, 0x00 ; 0
de0: 50 e0 ldi r21, 0x00 ; 0
de2: 63 e0 ldi r22, 0x03 ; 3
de4: 80 e0 ldi r24, 0x00 ; 0
de6: 0e 94 77 10 call 0x20ee ; 0x20ee <disk_ioctl>
dea: 89 2b or r24, r25
dec: 19 f0 breq .+6 ; 0xdf4 <f_sync+0xa2>
dee: b8 e0 ldi r27, 0x08 ; 8
df0: eb 2e mov r14, r27
df2: f1 2c mov r15, r1
fp->flag &= ~FA__WRITTEN;
res = sync();
}
}
return res;
}
df4: c7 01 movw r24, r14
df6: cd b7 in r28, 0x3d ; 61
df8: de b7 in r29, 0x3e ; 62
dfa: e6 e0 ldi r30, 0x06 ; 6
dfc: 0c 94 ef 14 jmp 0x29de ; 0x29de <__epilogue_restores__+0x18>
 
00000e00 <f_close>:
/*-----------------------------------------------------------------------*/
 
FRESULT f_close (
FIL *fp /* Pointer to the file object to be closed */
)
{
e00: cf 93 push r28
e02: df 93 push r29
e04: ec 01 movw r28, r24
FRESULT res;
 
 
#if !_FS_READONLY
res = f_sync(fp);
e06: 0e 94 a9 06 call 0xd52 ; 0xd52 <f_sync>
e0a: 9c 01 movw r18, r24
#else
res = validate(fp->fs, fp->id);
#endif
if (res == FR_OK)
e0c: 00 97 sbiw r24, 0x00 ; 0
e0e: 11 f4 brne .+4 ; 0xe14 <f_close+0x14>
fp->fs = NULL;
e10: 1d 82 std Y+5, r1 ; 0x05
e12: 1c 82 std Y+4, r1 ; 0x04
 
return res;
}
e14: c9 01 movw r24, r18
e16: df 91 pop r29
e18: cf 91 pop r28
e1a: 08 95 ret
 
00000e1c <f_write>:
FIL *fp, /* Pointer to the file object */
const void *buff, /* Pointer to the data to be written */
WORD btw, /* Number of bytes to write */
WORD *bw /* Pointer to number of bytes written */
)
{
e1c: a0 e0 ldi r26, 0x00 ; 0
e1e: b0 e0 ldi r27, 0x00 ; 0
e20: e4 e1 ldi r30, 0x14 ; 20
e22: f7 e0 ldi r31, 0x07 ; 7
e24: 0c 94 c8 14 jmp 0x2990 ; 0x2990 <__prologue_saves__+0x2>
e28: ec 01 movw r28, r24
e2a: 16 2f mov r17, r22
e2c: 07 2f mov r16, r23
e2e: 7a 01 movw r14, r20
e30: 39 01 movw r6, r18
WORD wcnt;
CLUST clust;
BYTE cc;
FRESULT res;
const BYTE *wbuff = buff;
FATFS *fs = fp->fs;
e32: ac 80 ldd r10, Y+4 ; 0x04
e34: bd 80 ldd r11, Y+5 ; 0x05
 
 
*bw = 0;
e36: f9 01 movw r30, r18
e38: 11 82 std Z+1, r1 ; 0x01
e3a: 10 82 st Z, r1
res = validate(fs, fp->id); /* Check validity of the object */
e3c: 68 81 ld r22, Y
e3e: 79 81 ldd r23, Y+1 ; 0x01
e40: c5 01 movw r24, r10
e42: 0e 94 46 03 call 0x68c ; 0x68c <validate>
e46: 4c 01 movw r8, r24
if (res) return res;
e48: 00 97 sbiw r24, 0x00 ; 0
e4a: 09 f0 breq .+2 ; 0xe4e <f_write+0x32>
e4c: 3b c1 rjmp .+630 ; 0x10c4 <f_write+0x2a8>
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
e4e: 8a 81 ldd r24, Y+2 ; 0x02
e50: 87 fd sbrc r24, 7
e52: 35 c1 rjmp .+618 ; 0x10be <f_write+0x2a2>
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
e54: 81 fd sbrc r24, 1
e56: 04 c0 rjmp .+8 ; 0xe60 <f_write+0x44>
e58: 36 e0 ldi r19, 0x06 ; 6
e5a: 83 2e mov r8, r19
e5c: 91 2c mov r9, r1
e5e: 32 c1 rjmp .+612 ; 0x10c4 <f_write+0x2a8>
if (fp->fsize + btw < fp->fsize) return FR_OK; /* File size cannot reach 4GB */
e60: 2a 85 ldd r18, Y+10 ; 0x0a
e62: 3b 85 ldd r19, Y+11 ; 0x0b
e64: 4c 85 ldd r20, Y+12 ; 0x0c
e66: 5d 85 ldd r21, Y+13 ; 0x0d
e68: c7 01 movw r24, r14
e6a: a0 e0 ldi r26, 0x00 ; 0
e6c: b0 e0 ldi r27, 0x00 ; 0
e6e: 82 0f add r24, r18
e70: 93 1f adc r25, r19
e72: a4 1f adc r26, r20
e74: b5 1f adc r27, r21
e76: 82 17 cp r24, r18
e78: 93 07 cpc r25, r19
e7a: a4 07 cpc r26, r20
e7c: b5 07 cpc r27, r21
e7e: 08 f4 brcc .+2 ; 0xe82 <f_write+0x66>
e80: 21 c1 rjmp .+578 ; 0x10c4 <f_write+0x2a8>
DWORD sect;
WORD wcnt;
CLUST clust;
BYTE cc;
FRESULT res;
const BYTE *wbuff = buff;
e82: 81 2f mov r24, r17
e84: 90 2f mov r25, r16
e86: 9c 01 movw r18, r24
e88: 69 01 movw r12, r18
fs->winsect = fp->curr_sect;
}
}
if (!move_window(fp->curr_sect)) /* Move sector window */
goto fw_error;
wcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes bytes to sector window */
e8a: 41 2c mov r4, r1
e8c: 22 e0 ldi r18, 0x02 ; 2
e8e: 52 2e mov r5, r18
if (wcnt > btw) wcnt = btw;
memcpy(&fs->win[(WORD)fp->fptr % 512], wbuff, wcnt);
fs->winflag = 1;
e90: 33 24 eor r3, r3
e92: 33 94 inc r3
e94: f8 c0 rjmp .+496 ; 0x1086 <f_write+0x26a>
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
if (fp->fsize + btw < fp->fsize) return FR_OK; /* File size cannot reach 4GB */
 
for ( ; btw; /* Repeat until all data transferred */
wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
if ((fp->fptr % 512) == 0) { /* On the sector boundary */
e96: 2e 81 ldd r18, Y+6 ; 0x06
e98: 3f 81 ldd r19, Y+7 ; 0x07
e9a: 48 85 ldd r20, Y+8 ; 0x08
e9c: 59 85 ldd r21, Y+9 ; 0x09
e9e: da 01 movw r26, r20
ea0: c9 01 movw r24, r18
ea2: 91 70 andi r25, 0x01 ; 1
ea4: a0 70 andi r26, 0x00 ; 0
ea6: b0 70 andi r27, 0x00 ; 0
ea8: 00 97 sbiw r24, 0x00 ; 0
eaa: a1 05 cpc r26, r1
eac: b1 05 cpc r27, r1
eae: 09 f0 breq .+2 ; 0xeb2 <f_write+0x96>
eb0: b1 c0 rjmp .+354 ; 0x1014 <f_write+0x1f8>
if (--(fp->sect_clust)) { /* Decrement left sector counter */
eb2: 8b 81 ldd r24, Y+3 ; 0x03
eb4: 81 50 subi r24, 0x01 ; 1
eb6: 8b 83 std Y+3, r24 ; 0x03
eb8: 88 23 and r24, r24
eba: 49 f0 breq .+18 ; 0xece <f_write+0xb2>
sect = fp->curr_sect + 1; /* Get current sector */
ebc: 2a 89 ldd r18, Y+18 ; 0x12
ebe: 3b 89 ldd r19, Y+19 ; 0x13
ec0: 4c 89 ldd r20, Y+20 ; 0x14
ec2: 5d 89 ldd r21, Y+21 ; 0x15
ec4: 2f 5f subi r18, 0xFF ; 255
ec6: 3f 4f sbci r19, 0xFF ; 255
ec8: 4f 4f sbci r20, 0xFF ; 255
eca: 5f 4f sbci r21, 0xFF ; 255
ecc: 51 c0 rjmp .+162 ; 0xf70 <f_write+0x154>
} else { /* On the cluster boundary, get next cluster */
if (fp->fptr == 0) { /* Is top of the file */
ece: 21 15 cp r18, r1
ed0: 31 05 cpc r19, r1
ed2: 41 05 cpc r20, r1
ed4: 51 05 cpc r21, r1
ed6: 69 f4 brne .+26 ; 0xef2 <f_write+0xd6>
clust = fp->org_clust;
ed8: 6e 85 ldd r22, Y+14 ; 0x0e
eda: 7f 85 ldd r23, Y+15 ; 0x0f
if (clust == 0) /* No cluster is created yet */
edc: 61 15 cp r22, r1
ede: 71 05 cpc r23, r1
ee0: 89 f4 brne .+34 ; 0xf04 <f_write+0xe8>
fp->org_clust = clust = create_chain(0); /* Create a new cluster chain */
ee2: 80 e0 ldi r24, 0x00 ; 0
ee4: 90 e0 ldi r25, 0x00 ; 0
ee6: 0e 94 d1 04 call 0x9a2 ; 0x9a2 <create_chain>
eea: bc 01 movw r22, r24
eec: 9f 87 std Y+15, r25 ; 0x0f
eee: 8e 87 std Y+14, r24 ; 0x0e
ef0: 05 c0 rjmp .+10 ; 0xefc <f_write+0xe0>
} else { /* Middle or end of file */
clust = create_chain(fp->curr_clust); /* Trace or streach cluster chain */
ef2: 88 89 ldd r24, Y+16 ; 0x10
ef4: 99 89 ldd r25, Y+17 ; 0x11
ef6: 0e 94 d1 04 call 0x9a2 ; 0x9a2 <create_chain>
efa: bc 01 movw r22, r24
}
if (clust == 0) break; /* Disk full */
efc: 61 15 cp r22, r1
efe: 71 05 cpc r23, r1
f00: 09 f4 brne .+2 ; 0xf04 <f_write+0xe8>
f02: c5 c0 rjmp .+394 ; 0x108e <f_write+0x272>
if (clust == 1 || clust >= fs->max_clust) goto fw_error;
f04: 61 30 cpi r22, 0x01 ; 1
f06: 71 05 cpc r23, r1
f08: 09 f4 brne .+2 ; 0xf0c <f_write+0xf0>
f0a: d6 c0 rjmp .+428 ; 0x10b8 <f_write+0x29c>
f0c: f5 01 movw r30, r10
f0e: 86 89 ldd r24, Z+22 ; 0x16
f10: 97 89 ldd r25, Z+23 ; 0x17
f12: 68 17 cp r22, r24
f14: 79 07 cpc r23, r25
f16: 08 f0 brcs .+2 ; 0xf1a <f_write+0xfe>
f18: cf c0 rjmp .+414 ; 0x10b8 <f_write+0x29c>
fp->curr_clust = clust; /* Current cluster */
f1a: 79 8b std Y+17, r23 ; 0x11
f1c: 68 8b std Y+16, r22 ; 0x10
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
CLUST clust /* Cluster# to be converted */
)
{
FATFS *fs = FatFs;
f1e: 00 91 10 01 lds r16, 0x0110
f22: 10 91 11 01 lds r17, 0x0111
 
 
clust -= 2;
f26: 62 50 subi r22, 0x02 ; 2
f28: 70 40 sbci r23, 0x00 ; 0
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
f2a: f8 01 movw r30, r16
f2c: 86 89 ldd r24, Z+22 ; 0x16
f2e: 97 89 ldd r25, Z+23 ; 0x17
f30: 02 97 sbiw r24, 0x02 ; 2
f32: 68 17 cp r22, r24
f34: 79 07 cpc r23, r25
f36: 28 f0 brcs .+10 ; 0xf42 <f_write+0x126>
f38: 20 e0 ldi r18, 0x00 ; 0
f3a: 30 e0 ldi r19, 0x00 ; 0
f3c: 40 e0 ldi r20, 0x00 ; 0
f3e: 50 e0 ldi r21, 0x00 ; 0
f40: 14 c0 rjmp .+40 ; 0xf6a <f_write+0x14e>
return (DWORD)clust * fs->sects_clust + fs->database;
f42: 80 e0 ldi r24, 0x00 ; 0
f44: 90 e0 ldi r25, 0x00 ; 0
f46: f8 01 movw r30, r16
f48: 25 8d ldd r18, Z+29 ; 0x1d
f4a: 30 e0 ldi r19, 0x00 ; 0
f4c: 40 e0 ldi r20, 0x00 ; 0
f4e: 50 e0 ldi r21, 0x00 ; 0
f50: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
f54: 9b 01 movw r18, r22
f56: ac 01 movw r20, r24
f58: f8 01 movw r30, r16
f5a: 80 89 ldd r24, Z+16 ; 0x10
f5c: 91 89 ldd r25, Z+17 ; 0x11
f5e: a2 89 ldd r26, Z+18 ; 0x12
f60: b3 89 ldd r27, Z+19 ; 0x13
f62: 28 0f add r18, r24
f64: 39 1f adc r19, r25
f66: 4a 1f adc r20, r26
f68: 5b 1f adc r21, r27
}
if (clust == 0) break; /* Disk full */
if (clust == 1 || clust >= fs->max_clust) goto fw_error;
fp->curr_clust = clust; /* Current cluster */
sect = clust2sect(clust); /* Get current sector */
fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */
f6a: f5 01 movw r30, r10
f6c: 85 8d ldd r24, Z+29 ; 0x1d
f6e: 8b 83 std Y+3, r24 ; 0x03
}
fp->curr_sect = sect; /* Update current sector */
f70: 2a 8b std Y+18, r18 ; 0x12
f72: 3b 8b std Y+19, r19 ; 0x13
f74: 4c 8b std Y+20, r20 ; 0x14
f76: 5d 8b std Y+21, r21 ; 0x15
cc = btw / 512; /* When left bytes >= 512, */
f78: 0f 2d mov r16, r15
f7a: 06 95 lsr r16
if (cc) { /* Write maximum contiguous sectors directly */
f7c: 61 f1 breq .+88 ; 0xfd6 <f_write+0x1ba>
f7e: 6b 81 ldd r22, Y+3 ; 0x03
f80: 10 2f mov r17, r16
f82: 60 17 cp r22, r16
f84: 08 f4 brcc .+2 ; 0xf88 <f_write+0x16c>
f86: 16 2f mov r17, r22
if (cc > fp->sect_clust) cc = fp->sect_clust;
if (disk_write(0, wbuff, sect, cc) != RES_OK)
f88: 01 2f mov r16, r17
f8a: b6 01 movw r22, r12
f8c: 80 e0 ldi r24, 0x00 ; 0
f8e: 0e 94 fb 0f call 0x1ff6 ; 0x1ff6 <disk_write>
f92: 89 2b or r24, r25
f94: 09 f0 breq .+2 ; 0xf98 <f_write+0x17c>
f96: 90 c0 rjmp .+288 ; 0x10b8 <f_write+0x29c>
goto fw_error;
fp->sect_clust -= cc - 1;
f98: 8b 81 ldd r24, Y+3 ; 0x03
f9a: 8f 5f subi r24, 0xFF ; 255
f9c: 81 1b sub r24, r17
f9e: 8b 83 std Y+3, r24 ; 0x03
fp->curr_sect += cc - 1;
fa0: 81 2f mov r24, r17
fa2: 90 e0 ldi r25, 0x00 ; 0
fa4: 01 97 sbiw r24, 0x01 ; 1
fa6: 9c 01 movw r18, r24
fa8: 44 27 eor r20, r20
faa: 37 fd sbrc r19, 7
fac: 40 95 com r20
fae: 54 2f mov r21, r20
fb0: 8c 01 movw r16, r24
fb2: 0f 5f subi r16, 0xFF ; 255
fb4: 1f 4f sbci r17, 0xFF ; 255
fb6: 8a 89 ldd r24, Y+18 ; 0x12
fb8: 9b 89 ldd r25, Y+19 ; 0x13
fba: ac 89 ldd r26, Y+20 ; 0x14
fbc: bd 89 ldd r27, Y+21 ; 0x15
fbe: 82 0f add r24, r18
fc0: 93 1f adc r25, r19
fc2: a4 1f adc r26, r20
fc4: b5 1f adc r27, r21
fc6: 8a 8b std Y+18, r24 ; 0x12
fc8: 9b 8b std Y+19, r25 ; 0x13
fca: ac 8b std Y+20, r26 ; 0x14
fcc: bd 8b std Y+21, r27 ; 0x15
wcnt = cc * 512; continue;
fce: 10 2f mov r17, r16
fd0: 00 27 eor r16, r16
fd2: 11 0f add r17, r17
fd4: 3e c0 rjmp .+124 ; 0x1052 <f_write+0x236>
}
if (fp->fptr >= fp->fsize) { /* Flush R/W window if needed */
fd6: 2e 81 ldd r18, Y+6 ; 0x06
fd8: 3f 81 ldd r19, Y+7 ; 0x07
fda: 48 85 ldd r20, Y+8 ; 0x08
fdc: 59 85 ldd r21, Y+9 ; 0x09
fde: 8a 85 ldd r24, Y+10 ; 0x0a
fe0: 9b 85 ldd r25, Y+11 ; 0x0b
fe2: ac 85 ldd r26, Y+12 ; 0x0c
fe4: bd 85 ldd r27, Y+13 ; 0x0d
fe6: 28 17 cp r18, r24
fe8: 39 07 cpc r19, r25
fea: 4a 07 cpc r20, r26
fec: 5b 07 cpc r21, r27
fee: 90 f0 brcs .+36 ; 0x1014 <f_write+0x1f8>
if (!move_window(0)) goto fw_error;
ff0: 60 e0 ldi r22, 0x00 ; 0
ff2: 70 e0 ldi r23, 0x00 ; 0
ff4: 80 e0 ldi r24, 0x00 ; 0
ff6: 90 e0 ldi r25, 0x00 ; 0
ff8: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
ffc: 88 23 and r24, r24
ffe: 09 f4 brne .+2 ; 0x1002 <f_write+0x1e6>
1000: 5b c0 rjmp .+182 ; 0x10b8 <f_write+0x29c>
fs->winsect = fp->curr_sect;
1002: 8a 89 ldd r24, Y+18 ; 0x12
1004: 9b 89 ldd r25, Y+19 ; 0x13
1006: ac 89 ldd r26, Y+20 ; 0x14
1008: bd 89 ldd r27, Y+21 ; 0x15
100a: f5 01 movw r30, r10
100c: 84 83 std Z+4, r24 ; 0x04
100e: 95 83 std Z+5, r25 ; 0x05
1010: a6 83 std Z+6, r26 ; 0x06
1012: b7 83 std Z+7, r27 ; 0x07
}
}
if (!move_window(fp->curr_sect)) /* Move sector window */
1014: 6a 89 ldd r22, Y+18 ; 0x12
1016: 7b 89 ldd r23, Y+19 ; 0x13
1018: 8c 89 ldd r24, Y+20 ; 0x14
101a: 9d 89 ldd r25, Y+21 ; 0x15
101c: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
1020: 88 23 and r24, r24
1022: 09 f4 brne .+2 ; 0x1026 <f_write+0x20a>
1024: 49 c0 rjmp .+146 ; 0x10b8 <f_write+0x29c>
goto fw_error;
wcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes bytes to sector window */
1026: 2e 81 ldd r18, Y+6 ; 0x06
1028: 3f 81 ldd r19, Y+7 ; 0x07
102a: 31 70 andi r19, 0x01 ; 1
102c: c2 01 movw r24, r4
102e: 82 1b sub r24, r18
1030: 93 0b sbc r25, r19
1032: 87 01 movw r16, r14
1034: 8e 15 cp r24, r14
1036: 9f 05 cpc r25, r15
1038: 08 f4 brcc .+2 ; 0x103c <f_write+0x220>
103a: 8c 01 movw r16, r24
if (wcnt > btw) wcnt = btw;
memcpy(&fs->win[(WORD)fp->fptr % 512], wbuff, wcnt);
103c: 20 5e subi r18, 0xE0 ; 224
103e: 3f 4f sbci r19, 0xFF ; 255
1040: 2a 0d add r18, r10
1042: 3b 1d adc r19, r11
1044: a8 01 movw r20, r16
1046: b6 01 movw r22, r12
1048: c9 01 movw r24, r18
104a: 0e 94 a3 11 call 0x2346 ; 0x2346 <memcpy>
fs->winflag = 1;
104e: f5 01 movw r30, r10
1050: 37 8e std Z+31, r3 ; 0x1f
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
if (fp->fsize + btw < fp->fsize) return FR_OK; /* File size cannot reach 4GB */
 
for ( ; btw; /* Repeat until all data transferred */
wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
1052: c0 0e add r12, r16
1054: d1 1e adc r13, r17
1056: c8 01 movw r24, r16
1058: a0 e0 ldi r26, 0x00 ; 0
105a: b0 e0 ldi r27, 0x00 ; 0
105c: 2e 81 ldd r18, Y+6 ; 0x06
105e: 3f 81 ldd r19, Y+7 ; 0x07
1060: 48 85 ldd r20, Y+8 ; 0x08
1062: 59 85 ldd r21, Y+9 ; 0x09
1064: 28 0f add r18, r24
1066: 39 1f adc r19, r25
1068: 4a 1f adc r20, r26
106a: 5b 1f adc r21, r27
106c: 2e 83 std Y+6, r18 ; 0x06
106e: 3f 83 std Y+7, r19 ; 0x07
1070: 48 87 std Y+8, r20 ; 0x08
1072: 59 87 std Y+9, r21 ; 0x09
1074: f3 01 movw r30, r6
1076: 80 81 ld r24, Z
1078: 91 81 ldd r25, Z+1 ; 0x01
107a: 80 0f add r24, r16
107c: 91 1f adc r25, r17
107e: 91 83 std Z+1, r25 ; 0x01
1080: 80 83 st Z, r24
1082: e0 1a sub r14, r16
1084: f1 0a sbc r15, r17
if (res) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
if (fp->fsize + btw < fp->fsize) return FR_OK; /* File size cannot reach 4GB */
 
for ( ; btw; /* Repeat until all data transferred */
1086: e1 14 cp r14, r1
1088: f1 04 cpc r15, r1
108a: 09 f0 breq .+2 ; 0x108e <f_write+0x272>
108c: 04 cf rjmp .-504 ; 0xe96 <f_write+0x7a>
if (wcnt > btw) wcnt = btw;
memcpy(&fs->win[(WORD)fp->fptr % 512], wbuff, wcnt);
fs->winflag = 1;
}
 
if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
108e: 2e 81 ldd r18, Y+6 ; 0x06
1090: 3f 81 ldd r19, Y+7 ; 0x07
1092: 48 85 ldd r20, Y+8 ; 0x08
1094: 59 85 ldd r21, Y+9 ; 0x09
1096: 8a 85 ldd r24, Y+10 ; 0x0a
1098: 9b 85 ldd r25, Y+11 ; 0x0b
109a: ac 85 ldd r26, Y+12 ; 0x0c
109c: bd 85 ldd r27, Y+13 ; 0x0d
109e: 82 17 cp r24, r18
10a0: 93 07 cpc r25, r19
10a2: a4 07 cpc r26, r20
10a4: b5 07 cpc r27, r21
10a6: 20 f4 brcc .+8 ; 0x10b0 <f_write+0x294>
10a8: 2a 87 std Y+10, r18 ; 0x0a
10aa: 3b 87 std Y+11, r19 ; 0x0b
10ac: 4c 87 std Y+12, r20 ; 0x0c
10ae: 5d 87 std Y+13, r21 ; 0x0d
fp->flag |= FA__WRITTEN; /* Set file changed flag */
10b0: 8a 81 ldd r24, Y+2 ; 0x02
10b2: 80 62 ori r24, 0x20 ; 32
10b4: 8a 83 std Y+2, r24 ; 0x02
10b6: 06 c0 rjmp .+12 ; 0x10c4 <f_write+0x2a8>
return FR_OK;
 
fw_error: /* Abort this function due to an unrecoverable error */
fp->flag |= FA__ERROR;
10b8: 8a 81 ldd r24, Y+2 ; 0x02
10ba: 80 68 ori r24, 0x80 ; 128
10bc: 8a 83 std Y+2, r24 ; 0x02
10be: 88 e0 ldi r24, 0x08 ; 8
10c0: 88 2e mov r8, r24
10c2: 91 2c mov r9, r1
return FR_RW_ERROR;
}
10c4: c4 01 movw r24, r8
10c6: cd b7 in r28, 0x3d ; 61
10c8: de b7 in r29, 0x3e ; 62
10ca: e1 e1 ldi r30, 0x11 ; 17
10cc: 0c 94 e4 14 jmp 0x29c8 ; 0x29c8 <__epilogue_restores__+0x2>
 
000010d0 <f_read>:
FIL *fp, /* Pointer to the file object */
void *buff, /* Pointer to data buffer */
WORD btr, /* Number of bytes to read */
WORD *br /* Pointer to number of bytes read */
)
{
10d0: a0 e0 ldi r26, 0x00 ; 0
10d2: b0 e0 ldi r27, 0x00 ; 0
10d4: ee e6 ldi r30, 0x6E ; 110
10d6: f8 e0 ldi r31, 0x08 ; 8
10d8: 0c 94 c9 14 jmp 0x2992 ; 0x2992 <__prologue_saves__+0x4>
10dc: ec 01 movw r28, r24
10de: 16 2f mov r17, r22
10e0: 07 2f mov r16, r23
10e2: 7a 01 movw r14, r20
10e4: 39 01 movw r6, r18
DWORD sect, remain;
WORD rcnt;
CLUST clust;
BYTE cc, *rbuff = buff;
FRESULT res;
FATFS *fs = fp->fs;
10e6: 8c 80 ldd r8, Y+4 ; 0x04
10e8: 9d 80 ldd r9, Y+5 ; 0x05
 
 
*br = 0;
10ea: f9 01 movw r30, r18
10ec: 11 82 std Z+1, r1 ; 0x01
10ee: 10 82 st Z, r1
res = validate(fs, fp->id); /* Check validity of the object */
10f0: 68 81 ld r22, Y
10f2: 79 81 ldd r23, Y+1 ; 0x01
10f4: c4 01 movw r24, r8
10f6: 0e 94 46 03 call 0x68c ; 0x68c <validate>
10fa: 5c 01 movw r10, r24
if (res) return res;
10fc: 00 97 sbiw r24, 0x00 ; 0
10fe: 09 f0 breq .+2 ; 0x1102 <f_read+0x32>
1100: f8 c0 rjmp .+496 ; 0x12f2 <f_read+0x222>
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
1102: 8a 81 ldd r24, Y+2 ; 0x02
1104: 87 fd sbrc r24, 7
1106: f2 c0 rjmp .+484 ; 0x12ec <f_read+0x21c>
if (!(fp->flag & FA_READ)) return FR_DENIED; /* Check access mode */
1108: 80 fd sbrc r24, 0
110a: 04 c0 rjmp .+8 ; 0x1114 <f_read+0x44>
110c: 76 e0 ldi r23, 0x06 ; 6
110e: a7 2e mov r10, r23
1110: b1 2c mov r11, r1
1112: ef c0 rjmp .+478 ; 0x12f2 <f_read+0x222>
remain = fp->fsize - fp->fptr;
1114: 2a 85 ldd r18, Y+10 ; 0x0a
1116: 3b 85 ldd r19, Y+11 ; 0x0b
1118: 4c 85 ldd r20, Y+12 ; 0x0c
111a: 5d 85 ldd r21, Y+13 ; 0x0d
111c: 8e 81 ldd r24, Y+6 ; 0x06
111e: 9f 81 ldd r25, Y+7 ; 0x07
1120: a8 85 ldd r26, Y+8 ; 0x08
1122: b9 85 ldd r27, Y+9 ; 0x09
1124: 28 1b sub r18, r24
1126: 39 0b sbc r19, r25
1128: 4a 0b sbc r20, r26
112a: 5b 0b sbc r21, r27
if (btr > remain) btr = (WORD)remain; /* Truncate read count by number of bytes left */
112c: c7 01 movw r24, r14
112e: a0 e0 ldi r26, 0x00 ; 0
1130: b0 e0 ldi r27, 0x00 ; 0
1132: 28 17 cp r18, r24
1134: 39 07 cpc r19, r25
1136: 4a 07 cpc r20, r26
1138: 5b 07 cpc r21, r27
113a: 08 f4 brcc .+2 ; 0x113e <f_read+0x6e>
113c: 79 01 movw r14, r18
)
{
DWORD sect, remain;
WORD rcnt;
CLUST clust;
BYTE cc, *rbuff = buff;
113e: 81 2f mov r24, r17
1140: 90 2f mov r25, r16
1142: 9c 01 movw r18, r24
1144: 69 01 movw r12, r18
fp->curr_sect += cc - 1;
rcnt = cc * 512; continue;
}
}
if (!move_window(fp->curr_sect)) goto fr_error; /* Move sector window */
rcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes from sector window */
1146: 41 2c mov r4, r1
1148: 62 e0 ldi r22, 0x02 ; 2
114a: 56 2e mov r5, r22
114c: c7 c0 rjmp .+398 ; 0x12dc <f_read+0x20c>
remain = fp->fsize - fp->fptr;
if (btr > remain) btr = (WORD)remain; /* Truncate read count by number of bytes left */
 
for ( ; btr; /* Repeat until all data transferred */
rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
if ((fp->fptr % 512) == 0) { /* On the sector boundary */
114e: 2e 81 ldd r18, Y+6 ; 0x06
1150: 3f 81 ldd r19, Y+7 ; 0x07
1152: 48 85 ldd r20, Y+8 ; 0x08
1154: 59 85 ldd r21, Y+9 ; 0x09
1156: da 01 movw r26, r20
1158: c9 01 movw r24, r18
115a: 91 70 andi r25, 0x01 ; 1
115c: a0 70 andi r26, 0x00 ; 0
115e: b0 70 andi r27, 0x00 ; 0
1160: 00 97 sbiw r24, 0x00 ; 0
1162: a1 05 cpc r26, r1
1164: b1 05 cpc r27, r1
1166: 09 f0 breq .+2 ; 0x116a <f_read+0x9a>
1168: 84 c0 rjmp .+264 ; 0x1272 <f_read+0x1a2>
if (--fp->sect_clust) { /* Decrement left sector counter */
116a: 8b 81 ldd r24, Y+3 ; 0x03
116c: 81 50 subi r24, 0x01 ; 1
116e: 8b 83 std Y+3, r24 ; 0x03
1170: 88 23 and r24, r24
1172: 49 f0 breq .+18 ; 0x1186 <f_read+0xb6>
sect = fp->curr_sect + 1; /* Get current sector */
1174: 2a 89 ldd r18, Y+18 ; 0x12
1176: 3b 89 ldd r19, Y+19 ; 0x13
1178: 4c 89 ldd r20, Y+20 ; 0x14
117a: 5d 89 ldd r21, Y+21 ; 0x15
117c: 2f 5f subi r18, 0xFF ; 255
117e: 3f 4f sbci r19, 0xFF ; 255
1180: 4f 4f sbci r20, 0xFF ; 255
1182: 5f 4f sbci r21, 0xFF ; 255
1184: 43 c0 rjmp .+134 ; 0x120c <f_read+0x13c>
} else { /* On the cluster boundary, get next cluster */
clust = (fp->fptr == 0) ?
1186: 21 15 cp r18, r1
1188: 31 05 cpc r19, r1
118a: 41 05 cpc r20, r1
118c: 51 05 cpc r21, r1
118e: 19 f4 brne .+6 ; 0x1196 <f_read+0xc6>
1190: 6e 85 ldd r22, Y+14 ; 0x0e
1192: 7f 85 ldd r23, Y+15 ; 0x0f
1194: 05 c0 rjmp .+10 ; 0x11a0 <f_read+0xd0>
1196: 88 89 ldd r24, Y+16 ; 0x10
1198: 99 89 ldd r25, Y+17 ; 0x11
119a: 0e 94 53 04 call 0x8a6 ; 0x8a6 <get_cluster>
119e: bc 01 movw r22, r24
fp->org_clust : get_cluster(fp->curr_clust);
if (clust < 2 || clust >= fs->max_clust)
11a0: 62 30 cpi r22, 0x02 ; 2
11a2: 71 05 cpc r23, r1
11a4: 08 f4 brcc .+2 ; 0x11a8 <f_read+0xd8>
11a6: 9f c0 rjmp .+318 ; 0x12e6 <f_read+0x216>
11a8: f4 01 movw r30, r8
11aa: 86 89 ldd r24, Z+22 ; 0x16
11ac: 97 89 ldd r25, Z+23 ; 0x17
11ae: 68 17 cp r22, r24
11b0: 79 07 cpc r23, r25
11b2: 08 f0 brcs .+2 ; 0x11b6 <f_read+0xe6>
11b4: 98 c0 rjmp .+304 ; 0x12e6 <f_read+0x216>
goto fr_error;
fp->curr_clust = clust; /* Current cluster */
11b6: 79 8b std Y+17, r23 ; 0x11
11b8: 68 8b std Y+16, r22 ; 0x10
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
CLUST clust /* Cluster# to be converted */
)
{
FATFS *fs = FatFs;
11ba: 00 91 10 01 lds r16, 0x0110
11be: 10 91 11 01 lds r17, 0x0111
 
 
clust -= 2;
11c2: 62 50 subi r22, 0x02 ; 2
11c4: 70 40 sbci r23, 0x00 ; 0
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
11c6: f8 01 movw r30, r16
11c8: 86 89 ldd r24, Z+22 ; 0x16
11ca: 97 89 ldd r25, Z+23 ; 0x17
11cc: 02 97 sbiw r24, 0x02 ; 2
11ce: 68 17 cp r22, r24
11d0: 79 07 cpc r23, r25
11d2: 28 f0 brcs .+10 ; 0x11de <f_read+0x10e>
11d4: 20 e0 ldi r18, 0x00 ; 0
11d6: 30 e0 ldi r19, 0x00 ; 0
11d8: 40 e0 ldi r20, 0x00 ; 0
11da: 50 e0 ldi r21, 0x00 ; 0
11dc: 14 c0 rjmp .+40 ; 0x1206 <f_read+0x136>
return (DWORD)clust * fs->sects_clust + fs->database;
11de: 80 e0 ldi r24, 0x00 ; 0
11e0: 90 e0 ldi r25, 0x00 ; 0
11e2: f8 01 movw r30, r16
11e4: 25 8d ldd r18, Z+29 ; 0x1d
11e6: 30 e0 ldi r19, 0x00 ; 0
11e8: 40 e0 ldi r20, 0x00 ; 0
11ea: 50 e0 ldi r21, 0x00 ; 0
11ec: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
11f0: 9b 01 movw r18, r22
11f2: ac 01 movw r20, r24
11f4: f8 01 movw r30, r16
11f6: 80 89 ldd r24, Z+16 ; 0x10
11f8: 91 89 ldd r25, Z+17 ; 0x11
11fa: a2 89 ldd r26, Z+18 ; 0x12
11fc: b3 89 ldd r27, Z+19 ; 0x13
11fe: 28 0f add r18, r24
1200: 39 1f adc r19, r25
1202: 4a 1f adc r20, r26
1204: 5b 1f adc r21, r27
fp->org_clust : get_cluster(fp->curr_clust);
if (clust < 2 || clust >= fs->max_clust)
goto fr_error;
fp->curr_clust = clust; /* Current cluster */
sect = clust2sect(clust); /* Get current sector */
fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */
1206: f4 01 movw r30, r8
1208: 85 8d ldd r24, Z+29 ; 0x1d
120a: 8b 83 std Y+3, r24 ; 0x03
}
fp->curr_sect = sect; /* Update current sector */
120c: 2a 8b std Y+18, r18 ; 0x12
120e: 3b 8b std Y+19, r19 ; 0x13
1210: 4c 8b std Y+20, r20 ; 0x14
1212: 5d 8b std Y+21, r21 ; 0x15
cc = btr / 512; /* When left bytes >= 512, */
1214: 0f 2d mov r16, r15
1216: 06 95 lsr r16
if (cc) { /* Read maximum contiguous sectors directly */
1218: 61 f1 breq .+88 ; 0x1272 <f_read+0x1a2>
121a: 6b 81 ldd r22, Y+3 ; 0x03
121c: 10 2f mov r17, r16
121e: 60 17 cp r22, r16
1220: 08 f4 brcc .+2 ; 0x1224 <f_read+0x154>
1222: 16 2f mov r17, r22
if (cc > fp->sect_clust) cc = fp->sect_clust;
if (disk_read(0, rbuff, sect, cc) != RES_OK)
1224: 01 2f mov r16, r17
1226: b6 01 movw r22, r12
1228: 80 e0 ldi r24, 0x00 ; 0
122a: 0e 94 9c 0f call 0x1f38 ; 0x1f38 <disk_read>
122e: 89 2b or r24, r25
1230: 09 f0 breq .+2 ; 0x1234 <f_read+0x164>
1232: 59 c0 rjmp .+178 ; 0x12e6 <f_read+0x216>
goto fr_error;
fp->sect_clust -= cc - 1;
1234: 8b 81 ldd r24, Y+3 ; 0x03
1236: 8f 5f subi r24, 0xFF ; 255
1238: 81 1b sub r24, r17
123a: 8b 83 std Y+3, r24 ; 0x03
fp->curr_sect += cc - 1;
123c: 81 2f mov r24, r17
123e: 90 e0 ldi r25, 0x00 ; 0
1240: 01 97 sbiw r24, 0x01 ; 1
1242: 9c 01 movw r18, r24
1244: 44 27 eor r20, r20
1246: 37 fd sbrc r19, 7
1248: 40 95 com r20
124a: 54 2f mov r21, r20
124c: 8c 01 movw r16, r24
124e: 0f 5f subi r16, 0xFF ; 255
1250: 1f 4f sbci r17, 0xFF ; 255
1252: 8a 89 ldd r24, Y+18 ; 0x12
1254: 9b 89 ldd r25, Y+19 ; 0x13
1256: ac 89 ldd r26, Y+20 ; 0x14
1258: bd 89 ldd r27, Y+21 ; 0x15
125a: 82 0f add r24, r18
125c: 93 1f adc r25, r19
125e: a4 1f adc r26, r20
1260: b5 1f adc r27, r21
1262: 8a 8b std Y+18, r24 ; 0x12
1264: 9b 8b std Y+19, r25 ; 0x13
1266: ac 8b std Y+20, r26 ; 0x14
1268: bd 8b std Y+21, r27 ; 0x15
rcnt = cc * 512; continue;
126a: 10 2f mov r17, r16
126c: 00 27 eor r16, r16
126e: 11 0f add r17, r17
1270: 1b c0 rjmp .+54 ; 0x12a8 <f_read+0x1d8>
}
}
if (!move_window(fp->curr_sect)) goto fr_error; /* Move sector window */
1272: 6a 89 ldd r22, Y+18 ; 0x12
1274: 7b 89 ldd r23, Y+19 ; 0x13
1276: 8c 89 ldd r24, Y+20 ; 0x14
1278: 9d 89 ldd r25, Y+21 ; 0x15
127a: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
127e: 88 23 and r24, r24
1280: 91 f1 breq .+100 ; 0x12e6 <f_read+0x216>
rcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes from sector window */
1282: 8e 81 ldd r24, Y+6 ; 0x06
1284: 9f 81 ldd r25, Y+7 ; 0x07
1286: 91 70 andi r25, 0x01 ; 1
1288: 92 01 movw r18, r4
128a: 28 1b sub r18, r24
128c: 39 0b sbc r19, r25
128e: 87 01 movw r16, r14
1290: 2e 15 cp r18, r14
1292: 3f 05 cpc r19, r15
1294: 08 f4 brcc .+2 ; 0x1298 <f_read+0x1c8>
1296: 89 01 movw r16, r18
if (rcnt > btr) rcnt = btr;
memcpy(rbuff, &fs->win[(WORD)fp->fptr % 512], rcnt);
1298: 80 96 adiw r24, 0x20 ; 32
129a: 88 0d add r24, r8
129c: 99 1d adc r25, r9
129e: a8 01 movw r20, r16
12a0: bc 01 movw r22, r24
12a2: c6 01 movw r24, r12
12a4: 0e 94 a3 11 call 0x2346 ; 0x2346 <memcpy>
if (!(fp->flag & FA_READ)) return FR_DENIED; /* Check access mode */
remain = fp->fsize - fp->fptr;
if (btr > remain) btr = (WORD)remain; /* Truncate read count by number of bytes left */
 
for ( ; btr; /* Repeat until all data transferred */
rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
12a8: c0 0e add r12, r16
12aa: d1 1e adc r13, r17
12ac: c8 01 movw r24, r16
12ae: a0 e0 ldi r26, 0x00 ; 0
12b0: b0 e0 ldi r27, 0x00 ; 0
12b2: 2e 81 ldd r18, Y+6 ; 0x06
12b4: 3f 81 ldd r19, Y+7 ; 0x07
12b6: 48 85 ldd r20, Y+8 ; 0x08
12b8: 59 85 ldd r21, Y+9 ; 0x09
12ba: 28 0f add r18, r24
12bc: 39 1f adc r19, r25
12be: 4a 1f adc r20, r26
12c0: 5b 1f adc r21, r27
12c2: 2e 83 std Y+6, r18 ; 0x06
12c4: 3f 83 std Y+7, r19 ; 0x07
12c6: 48 87 std Y+8, r20 ; 0x08
12c8: 59 87 std Y+9, r21 ; 0x09
12ca: f3 01 movw r30, r6
12cc: 80 81 ld r24, Z
12ce: 91 81 ldd r25, Z+1 ; 0x01
12d0: 80 0f add r24, r16
12d2: 91 1f adc r25, r17
12d4: 91 83 std Z+1, r25 ; 0x01
12d6: 80 83 st Z, r24
12d8: e0 1a sub r14, r16
12da: f1 0a sbc r15, r17
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_READ)) return FR_DENIED; /* Check access mode */
remain = fp->fsize - fp->fptr;
if (btr > remain) btr = (WORD)remain; /* Truncate read count by number of bytes left */
 
for ( ; btr; /* Repeat until all data transferred */
12dc: e1 14 cp r14, r1
12de: f1 04 cpc r15, r1
12e0: 09 f0 breq .+2 ; 0x12e4 <f_read+0x214>
12e2: 35 cf rjmp .-406 ; 0x114e <f_read+0x7e>
12e4: 06 c0 rjmp .+12 ; 0x12f2 <f_read+0x222>
}
 
return FR_OK;
 
fr_error: /* Abort this function due to an unrecoverable error */
fp->flag |= FA__ERROR;
12e6: 8a 81 ldd r24, Y+2 ; 0x02
12e8: 80 68 ori r24, 0x80 ; 128
12ea: 8a 83 std Y+2, r24 ; 0x02
12ec: 48 e0 ldi r20, 0x08 ; 8
12ee: a4 2e mov r10, r20
12f0: b1 2c mov r11, r1
return FR_RW_ERROR;
}
12f2: c5 01 movw r24, r10
12f4: cd b7 in r28, 0x3d ; 61
12f6: de b7 in r29, 0x3e ; 62
12f8: e0 e1 ldi r30, 0x10 ; 16
12fa: 0c 94 e5 14 jmp 0x29ca ; 0x29ca <__epilogue_restores__+0x4>
 
000012fe <f_mount>:
 
FRESULT f_mount (
BYTE drv, /* Logical drive number to be mounted/unmounted */
FATFS *fs /* Pointer to new file system object (NULL for unmount)*/
)
{
12fe: cf 93 push r28
1300: df 93 push r29
1302: fb 01 movw r30, r22
FATFS *fsobj;
 
 
if (drv) return FR_INVALID_DRIVE;
1304: 88 23 and r24, r24
1306: 19 f0 breq .+6 ; 0x130e <f_mount+0x10>
1308: 25 e0 ldi r18, 0x05 ; 5
130a: 30 e0 ldi r19, 0x00 ; 0
130c: 1d c0 rjmp .+58 ; 0x1348 <f_mount+0x4a>
fsobj = FatFs;
130e: a0 91 10 01 lds r26, 0x0110
1312: b0 91 11 01 lds r27, 0x0111
FatFs = fs;
1316: 70 93 11 01 sts 0x0111, r23
131a: 60 93 10 01 sts 0x0110, r22
if (fsobj) memset(fsobj, 0, sizeof(FATFS));
131e: 10 97 sbiw r26, 0x00 ; 0
1320: 41 f0 breq .+16 ; 0x1332 <f_mount+0x34>
1322: 80 e2 ldi r24, 0x20 ; 32
1324: 92 e0 ldi r25, 0x02 ; 2
1326: ed 01 movw r28, r26
1328: 9c 01 movw r18, r24
132a: 19 92 st Y+, r1
132c: 21 50 subi r18, 0x01 ; 1
132e: 30 40 sbci r19, 0x00 ; 0
1330: e1 f7 brne .-8 ; 0x132a <f_mount+0x2c>
if (fs) memset(fs, 0, sizeof(FATFS));
1332: 30 97 sbiw r30, 0x00 ; 0
1334: 39 f0 breq .+14 ; 0x1344 <f_mount+0x46>
1336: 80 e2 ldi r24, 0x20 ; 32
1338: 92 e0 ldi r25, 0x02 ; 2
133a: df 01 movw r26, r30
133c: ec 01 movw r28, r24
133e: 1d 92 st X+, r1
1340: 21 97 sbiw r28, 0x01 ; 1
1342: e9 f7 brne .-6 ; 0x133e <f_mount+0x40>
1344: 20 e0 ldi r18, 0x00 ; 0
1346: 30 e0 ldi r19, 0x00 ; 0
 
return FR_OK;
}
1348: c9 01 movw r24, r18
134a: df 91 pop r29
134c: cf 91 pop r28
134e: 08 95 ret
 
00001350 <check_fs>:
 
static
BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record or error */
DWORD sect /* Sector# to check if it is a FAT boot record or not */
)
{
1350: 0f 93 push r16
1352: cf 93 push r28
1354: df 93 push r29
1356: 9b 01 movw r18, r22
1358: ac 01 movw r20, r24
FATFS *fs = FatFs;
135a: c0 91 10 01 lds r28, 0x0110
135e: d0 91 11 01 lds r29, 0x0111
 
if (disk_read(0, fs->win, sect, 1) != RES_OK) /* Load boot record */
1362: be 01 movw r22, r28
1364: 60 5e subi r22, 0xE0 ; 224
1366: 7f 4f sbci r23, 0xFF ; 255
1368: 01 e0 ldi r16, 0x01 ; 1
136a: 80 e0 ldi r24, 0x00 ; 0
136c: 0e 94 9c 0f call 0x1f38 ; 0x1f38 <disk_read>
1370: 89 2b or r24, r25
1372: c1 f4 brne .+48 ; 0x13a4 <check_fs+0x54>
return 2;
if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature */
1374: c2 5e subi r28, 0xE2 ; 226
1376: dd 4f sbci r29, 0xFD ; 253
1378: 88 81 ld r24, Y
137a: 99 81 ldd r25, Y+1 ; 0x01
137c: ce 51 subi r28, 0x1E ; 30
137e: d2 40 sbci r29, 0x02 ; 2
1380: 85 55 subi r24, 0x55 ; 85
1382: 9a 4a sbci r25, 0xAA ; 170
1384: 79 f4 brne .+30 ; 0x13a4 <check_fs+0x54>
return 2;
 
if (!memcmp(&fs->win[BS_FilSysType], "FAT", 3)) /* Check FAT signature */
1386: 43 e0 ldi r20, 0x03 ; 3
1388: 50 e0 ldi r21, 0x00 ; 0
138a: 67 e0 ldi r22, 0x07 ; 7
138c: 71 e0 ldi r23, 0x01 ; 1
138e: ce 01 movw r24, r28
1390: 8a 5a subi r24, 0xAA ; 170
1392: 9f 4f sbci r25, 0xFF ; 255
1394: 0e 94 96 11 call 0x232c ; 0x232c <memcmp>
1398: 9c 01 movw r18, r24
139a: 80 e0 ldi r24, 0x00 ; 0
139c: 23 2b or r18, r19
139e: 19 f0 breq .+6 ; 0x13a6 <check_fs+0x56>
13a0: 81 e0 ldi r24, 0x01 ; 1
13a2: 01 c0 rjmp .+2 ; 0x13a6 <check_fs+0x56>
13a4: 82 e0 ldi r24, 0x02 ; 2
#if _FAT32
if (!memcmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80))
return 0;
#endif
return 1;
}
13a6: df 91 pop r29
13a8: cf 91 pop r28
13aa: 0f 91 pop r16
13ac: 08 95 ret
 
000013ae <f_open>:
FRESULT f_open (
FIL *fp, /* Pointer to the blank file object */
const char *path, /* Pointer to the file name */
BYTE mode /* Access mode and file open mode flags */
)
{
13ae: ad e1 ldi r26, 0x1D ; 29
13b0: b0 e0 ldi r27, 0x00 ; 0
13b2: ed ed ldi r30, 0xDD ; 221
13b4: f9 e0 ldi r31, 0x09 ; 9
13b6: 0c 94 c7 14 jmp 0x298e ; 0x298e <__prologue_saves__>
13ba: 9d 8f std Y+29, r25 ; 0x1d
13bc: 8c 8f std Y+28, r24 ; 0x1c
13be: 3b 01 movw r6, r22
FRESULT res;
BYTE *dir;
DIR dirobj;
char fn[8+3+1];
FATFS *fs = FatFs;
13c0: 80 90 10 01 lds r8, 0x0110
13c4: 90 90 11 01 lds r9, 0x0111
 
 
fp->fs = NULL;
13c8: fc 01 movw r30, r24
13ca: 15 82 std Z+5, r1 ; 0x05
13cc: 14 82 std Z+4, r1 ; 0x04
13ce: 03 c0 rjmp .+6 ; 0x13d6 <f_open+0x28>
const char *p = *path;
FATFS *fs = FatFs;
 
 
 
while (*p == ' ') p++; /* Strip leading spaces */
13d0: 08 94 sec
13d2: 61 1c adc r6, r1
13d4: 71 1c adc r7, r1
13d6: f3 01 movw r30, r6
13d8: 80 81 ld r24, Z
13da: 80 32 cpi r24, 0x20 ; 32
13dc: c9 f3 breq .-14 ; 0x13d0 <f_open+0x22>
if (*p == '/') p++; /* Strip heading slash */
13de: 8f 32 cpi r24, 0x2F ; 47
13e0: 19 f4 brne .+6 ; 0x13e8 <f_open+0x3a>
13e2: 08 94 sec
13e4: 61 1c adc r6, r1
13e6: 71 1c adc r7, r1
*path = p; /* Return pointer to the path name */
 
/* Is the file system object registered? */
if (!fs) return FR_NOT_ENABLED;
13e8: 81 14 cp r8, r1
13ea: 91 04 cpc r9, r1
13ec: 09 f4 brne .+2 ; 0x13f0 <f_open+0x42>
13ee: 17 c1 rjmp .+558 ; 0x161e <f_open+0x270>
FATFS *fs = FatFs;
 
 
fp->fs = NULL;
#if !_FS_READONLY
mode &= (FA_READ|FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW);
13f0: f4 2f mov r31, r20
13f2: ff 71 andi r31, 0x1F ; 31
13f4: fb 8f std Y+27, r31 ; 0x1b
res = auto_mount(&path, (BYTE)(mode & (FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)));
13f6: 14 2f mov r17, r20
13f8: 1e 71 andi r17, 0x1E ; 30
 
/* Is the file system object registered? */
if (!fs) return FR_NOT_ENABLED;
 
/* Chekck if the logical drive has been mounted or not */
if (fs->fs_type) {
13fa: f4 01 movw r30, r8
13fc: 84 8d ldd r24, Z+28 ; 0x1c
13fe: 88 23 and r24, r24
1400: 59 f0 breq .+22 ; 0x1418 <f_open+0x6a>
stat = disk_status(0);
1402: 80 e0 ldi r24, 0x00 ; 0
1404: 0e 94 95 0f call 0x1f2a ; 0x1f2a <disk_status>
if (!(stat & STA_NOINIT)) { /* If the physical drive is kept initialized */
1408: 80 fd sbrc r24, 0
140a: 06 c0 rjmp .+12 ; 0x1418 <f_open+0x6a>
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
140c: 11 23 and r17, r17
140e: 09 f4 brne .+2 ; 0x1412 <f_open+0x64>
1410: ab c3 rjmp .+1878 ; 0x1b68 <f_open+0x7ba>
1412: 82 fd sbrc r24, 2
1414: 07 c1 rjmp .+526 ; 0x1624 <f_open+0x276>
1416: a8 c3 rjmp .+1872 ; 0x1b68 <f_open+0x7ba>
}
}
 
/* The logical drive has not been mounted, following code attempts to mount the logical drive */
 
memset(fs, 0, sizeof(FATFS)); /* Clean-up the file system object */
1418: 80 e2 ldi r24, 0x20 ; 32
141a: 92 e0 ldi r25, 0x02 ; 2
141c: f4 01 movw r30, r8
141e: 9c 01 movw r18, r24
1420: 11 92 st Z+, r1
1422: 21 50 subi r18, 0x01 ; 1
1424: 30 40 sbci r19, 0x00 ; 0
1426: e1 f7 brne .-8 ; 0x1420 <f_open+0x72>
stat = disk_initialize(0); /* Initialize low level disk I/O layer */
1428: 80 e0 ldi r24, 0x00 ; 0
142a: 0e 94 b8 0e call 0x1d70 ; 0x1d70 <disk_initialize>
if (stat & STA_NOINIT) /* Check if the drive is ready */
142e: 80 ff sbrs r24, 0
1430: 03 c0 rjmp .+6 ; 0x1438 <f_open+0x8a>
1432: 21 e0 ldi r18, 0x01 ; 1
1434: 30 e0 ldi r19, 0x00 ; 0
1436: 8b c3 rjmp .+1814 ; 0x1b4e <f_open+0x7a0>
return FR_NOT_READY;
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
1438: 11 23 and r17, r17
143a: 11 f0 breq .+4 ; 0x1440 <f_open+0x92>
143c: 82 fd sbrc r24, 2
143e: f2 c0 rjmp .+484 ; 0x1624 <f_open+0x276>
return FR_WRITE_PROTECTED;
#endif
 
/* Search FAT partition on the drive */
fmt = check_fs(bootsect = 0); /* Check sector 0 as an SFD format */
1440: 60 e0 ldi r22, 0x00 ; 0
1442: 70 e0 ldi r23, 0x00 ; 0
1444: 80 e0 ldi r24, 0x00 ; 0
1446: 90 e0 ldi r25, 0x00 ; 0
1448: 0e 94 a8 09 call 0x1350 ; 0x1350 <check_fs>
if (fmt == 1) { /* Not a FAT boot record, it may be patitioned */
144c: 81 30 cpi r24, 0x01 ; 1
144e: 21 f0 breq .+8 ; 0x1458 <f_open+0xaa>
1450: ee 24 eor r14, r14
1452: ff 24 eor r15, r15
1454: 87 01 movw r16, r14
1456: 1e c0 rjmp .+60 ; 0x1494 <f_open+0xe6>
/* Check a partition listed in top of the partition table */
if (fs->win[MBR_Table+4]) { /* Is the 1st partition existing? */
1458: 82 ee ldi r24, 0xE2 ; 226
145a: 91 e0 ldi r25, 0x01 ; 1
145c: 88 0e add r8, r24
145e: 99 1e adc r9, r25
1460: f4 01 movw r30, r8
1462: 80 81 ld r24, Z
1464: 2e e1 ldi r18, 0x1E ; 30
1466: 3e ef ldi r19, 0xFE ; 254
1468: 82 0e add r8, r18
146a: 93 1e adc r9, r19
146c: 88 23 and r24, r24
146e: 09 f4 brne .+2 ; 0x1472 <f_open+0xc4>
1470: dc c0 rjmp .+440 ; 0x162a <f_open+0x27c>
bootsect = LD_DWORD(&fs->win[MBR_Table+8]); /* Partition offset in LBA */
1472: 86 ee ldi r24, 0xE6 ; 230
1474: 91 e0 ldi r25, 0x01 ; 1
1476: 88 0e add r8, r24
1478: 99 1e adc r9, r25
147a: f4 01 movw r30, r8
147c: e0 80 ld r14, Z
147e: f1 80 ldd r15, Z+1 ; 0x01
1480: 02 81 ldd r16, Z+2 ; 0x02
1482: 13 81 ldd r17, Z+3 ; 0x03
1484: 2a e1 ldi r18, 0x1A ; 26
1486: 3e ef ldi r19, 0xFE ; 254
1488: 82 0e add r8, r18
148a: 93 1e adc r9, r19
fmt = check_fs(bootsect); /* Check the partition */
148c: c8 01 movw r24, r16
148e: b7 01 movw r22, r14
1490: 0e 94 a8 09 call 0x1350 ; 0x1350 <check_fs>
}
}
if (fmt || LD_WORD(&fs->win[BPB_BytsPerSec]) != 512) /* No valid FAT patition is found */
1494: 88 23 and r24, r24
1496: 09 f0 breq .+2 ; 0x149a <f_open+0xec>
1498: c8 c0 rjmp .+400 ; 0x162a <f_open+0x27c>
149a: f4 01 movw r30, r8
149c: 83 a5 ldd r24, Z+43 ; 0x2b
149e: 94 a5 ldd r25, Z+44 ; 0x2c
14a0: 80 50 subi r24, 0x00 ; 0
14a2: 92 40 sbci r25, 0x02 ; 2
14a4: 09 f0 breq .+2 ; 0x14a8 <f_open+0xfa>
14a6: c1 c0 rjmp .+386 ; 0x162a <f_open+0x27c>
return FR_NO_FILESYSTEM;
 
/* Initialize the file system object */
fatsize = LD_WORD(&fs->win[BPB_FATSz16]); /* Number of sectors per FAT */
14a8: f4 01 movw r30, r8
14aa: 86 a9 ldd r24, Z+54 ; 0x36
14ac: 97 a9 ldd r25, Z+55 ; 0x37
14ae: bc 01 movw r22, r24
14b0: 80 e0 ldi r24, 0x00 ; 0
14b2: 90 e0 ldi r25, 0x00 ; 0
if (!fatsize) fatsize = LD_DWORD(&fs->win[BPB_FATSz32]);
14b4: 61 15 cp r22, r1
14b6: 71 05 cpc r23, r1
14b8: 81 05 cpc r24, r1
14ba: 91 05 cpc r25, r1
14bc: 69 f4 brne .+26 ; 0x14d8 <f_open+0x12a>
14be: 24 e4 ldi r18, 0x44 ; 68
14c0: 30 e0 ldi r19, 0x00 ; 0
14c2: 82 0e add r8, r18
14c4: 93 1e adc r9, r19
14c6: f4 01 movw r30, r8
14c8: 60 81 ld r22, Z
14ca: 71 81 ldd r23, Z+1 ; 0x01
14cc: 82 81 ldd r24, Z+2 ; 0x02
14ce: 93 81 ldd r25, Z+3 ; 0x03
14d0: 2c eb ldi r18, 0xBC ; 188
14d2: 3f ef ldi r19, 0xFF ; 255
14d4: 82 0e add r8, r18
14d6: 93 1e adc r9, r19
fs->sects_fat = (CLUST)fatsize;
14d8: f4 01 movw r30, r8
14da: 75 8b std Z+21, r23 ; 0x15
14dc: 64 8b std Z+20, r22 ; 0x14
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */
14de: 20 a9 ldd r18, Z+48 ; 0x30
14e0: 26 8f std Z+30, r18 ; 0x1e
fatsize *= fs->n_fats; /* (Number of sectors in FAT area) */
14e2: 30 e0 ldi r19, 0x00 ; 0
14e4: 40 e0 ldi r20, 0x00 ; 0
14e6: 50 e0 ldi r21, 0x00 ; 0
14e8: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
14ec: 5b 01 movw r10, r22
14ee: 6c 01 movw r12, r24
fs->fatbase = bootsect + LD_WORD(&fs->win[BPB_RsvdSecCnt]); /* FAT start sector (lba) */
14f0: f4 01 movw r30, r8
14f2: 86 a5 ldd r24, Z+46 ; 0x2e
14f4: 97 a5 ldd r25, Z+47 ; 0x2f
14f6: a0 e0 ldi r26, 0x00 ; 0
14f8: b0 e0 ldi r27, 0x00 ; 0
14fa: e8 0e add r14, r24
14fc: f9 1e adc r15, r25
14fe: 0a 1f adc r16, r26
1500: 1b 1f adc r17, r27
1502: e0 86 std Z+8, r14 ; 0x08
1504: f1 86 std Z+9, r15 ; 0x09
1506: 02 87 std Z+10, r16 ; 0x0a
1508: 13 87 std Z+11, r17 ; 0x0b
fs->sects_clust = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
150a: 85 a5 ldd r24, Z+45 ; 0x2d
150c: 85 8f std Z+29, r24 ; 0x1d
fs->n_rootdir = LD_WORD(&fs->win[BPB_RootEntCnt]); /* Nmuber of root directory entries */
150e: 21 a9 ldd r18, Z+49 ; 0x31
1510: 32 a9 ldd r19, Z+50 ; 0x32
1512: 33 83 std Z+3, r19 ; 0x03
1514: 22 83 std Z+2, r18 ; 0x02
totalsect = LD_WORD(&fs->win[BPB_TotSec16]); /* Number of sectors on the file system */
1516: 83 a9 ldd r24, Z+51 ; 0x33
1518: 94 a9 ldd r25, Z+52 ; 0x34
151a: 7c 01 movw r14, r24
151c: 00 e0 ldi r16, 0x00 ; 0
151e: 10 e0 ldi r17, 0x00 ; 0
if (!totalsect) totalsect = LD_DWORD(&fs->win[BPB_TotSec32]);
1520: e1 14 cp r14, r1
1522: f1 04 cpc r15, r1
1524: 01 05 cpc r16, r1
1526: 11 05 cpc r17, r1
1528: 69 f4 brne .+26 ; 0x1544 <f_open+0x196>
152a: 80 e4 ldi r24, 0x40 ; 64
152c: 90 e0 ldi r25, 0x00 ; 0
152e: 88 0e add r8, r24
1530: 99 1e adc r9, r25
1532: f4 01 movw r30, r8
1534: e0 80 ld r14, Z
1536: f1 80 ldd r15, Z+1 ; 0x01
1538: 02 81 ldd r16, Z+2 ; 0x02
153a: 13 81 ldd r17, Z+3 ; 0x03
153c: 80 ec ldi r24, 0xC0 ; 192
153e: 9f ef ldi r25, 0xFF ; 255
1540: 88 0e add r8, r24
1542: 99 1e adc r9, r25
fs->max_clust = maxclust = (totalsect /* Last cluster# + 1 */
1544: f4 01 movw r30, r8
1546: 86 a5 ldd r24, Z+46 ; 0x2e
1548: 97 a5 ldd r25, Z+47 ; 0x2f
154a: a0 e0 ldi r26, 0x00 ; 0
154c: b0 e0 ldi r27, 0x00 ; 0
154e: e8 1a sub r14, r24
1550: f9 0a sbc r15, r25
1552: 0a 0b sbc r16, r26
1554: 1b 0b sbc r17, r27
1556: ea 18 sub r14, r10
1558: fb 08 sbc r15, r11
155a: 0c 09 sbc r16, r12
155c: 1d 09 sbc r17, r13
155e: a4 e0 ldi r26, 0x04 ; 4
1560: 36 95 lsr r19
1562: 27 95 ror r18
1564: aa 95 dec r26
1566: e1 f7 brne .-8 ; 0x1560 <f_open+0x1b2>
1568: c9 01 movw r24, r18
156a: a0 e0 ldi r26, 0x00 ; 0
156c: b0 e0 ldi r27, 0x00 ; 0
156e: e8 1a sub r14, r24
1570: f9 0a sbc r15, r25
1572: 0a 0b sbc r16, r26
1574: 1b 0b sbc r17, r27
1576: 25 8d ldd r18, Z+29 ; 0x1d
1578: 30 e0 ldi r19, 0x00 ; 0
157a: 40 e0 ldi r20, 0x00 ; 0
157c: 50 e0 ldi r21, 0x00 ; 0
157e: c8 01 movw r24, r16
1580: b7 01 movw r22, r14
1582: 0e 94 a5 14 call 0x294a ; 0x294a <__udivmodsi4>
1586: 2e 5f subi r18, 0xFE ; 254
1588: 3f 4f sbci r19, 0xFF ; 255
158a: 4f 4f sbci r20, 0xFF ; 255
158c: 5f 4f sbci r21, 0xFF ; 255
158e: f4 01 movw r30, r8
1590: 37 8b std Z+23, r19 ; 0x17
1592: 26 8b std Z+22, r18 ; 0x16
- LD_WORD(&fs->win[BPB_RsvdSecCnt]) - fatsize - fs->n_rootdir / 16
) / fs->sects_clust + 2;
 
fmt = FS_FAT12; /* Determine the FAT sub type */
if (maxclust > 0xFF7) fmt = FS_FAT16;
1594: 28 3f cpi r18, 0xF8 ; 248
1596: ff e0 ldi r31, 0x0F ; 15
1598: 3f 07 cpc r19, r31
159a: f0 e0 ldi r31, 0x00 ; 0
159c: 4f 07 cpc r20, r31
159e: f0 e0 ldi r31, 0x00 ; 0
15a0: 5f 07 cpc r21, r31
15a2: 10 f4 brcc .+4 ; 0x15a8 <f_open+0x1fa>
15a4: 61 e0 ldi r22, 0x01 ; 1
15a6: 06 c0 rjmp .+12 ; 0x15b4 <f_open+0x206>
if (maxclust > 0xFFF7)
15a8: 28 5f subi r18, 0xF8 ; 248
15aa: 3f 4f sbci r19, 0xFF ; 255
15ac: 40 40 sbci r20, 0x00 ; 0
15ae: 50 40 sbci r21, 0x00 ; 0
15b0: e0 f5 brcc .+120 ; 0x162a <f_open+0x27c>
15b2: 62 e0 ldi r22, 0x02 ; 2
fmt = FS_FAT32;
if (fmt == FS_FAT32)
fs->dirbase = LD_DWORD(&fs->win[BPB_RootClus]); /* Root directory start cluster */
else
#endif
fs->dirbase = fs->fatbase + fatsize; /* Root directory start sector (lba) */
15b4: f4 01 movw r30, r8
15b6: 20 85 ldd r18, Z+8 ; 0x08
15b8: 31 85 ldd r19, Z+9 ; 0x09
15ba: 42 85 ldd r20, Z+10 ; 0x0a
15bc: 53 85 ldd r21, Z+11 ; 0x0b
15be: d6 01 movw r26, r12
15c0: c5 01 movw r24, r10
15c2: 82 0f add r24, r18
15c4: 93 1f adc r25, r19
15c6: a4 1f adc r26, r20
15c8: b5 1f adc r27, r21
15ca: 84 87 std Z+12, r24 ; 0x0c
15cc: 95 87 std Z+13, r25 ; 0x0d
15ce: a6 87 std Z+14, r26 ; 0x0e
15d0: b7 87 std Z+15, r27 ; 0x0f
fs->database = fs->fatbase + fatsize + fs->n_rootdir / 16; /* Data start sector (lba) */
15d2: 82 81 ldd r24, Z+2 ; 0x02
15d4: 93 81 ldd r25, Z+3 ; 0x03
15d6: 74 e0 ldi r23, 0x04 ; 4
15d8: 96 95 lsr r25
15da: 87 95 ror r24
15dc: 7a 95 dec r23
15de: e1 f7 brne .-8 ; 0x15d8 <f_open+0x22a>
15e0: a0 e0 ldi r26, 0x00 ; 0
15e2: b0 e0 ldi r27, 0x00 ; 0
15e4: 82 0f add r24, r18
15e6: 93 1f adc r25, r19
15e8: a4 1f adc r26, r20
15ea: b5 1f adc r27, r21
15ec: 8a 0d add r24, r10
15ee: 9b 1d adc r25, r11
15f0: ac 1d adc r26, r12
15f2: bd 1d adc r27, r13
15f4: 80 8b std Z+16, r24 ; 0x10
15f6: 91 8b std Z+17, r25 ; 0x11
15f8: a2 8b std Z+18, r26 ; 0x12
15fa: b3 8b std Z+19, r27 ; 0x13
fs->fs_type = fmt; /* FAT sub-type */
15fc: 64 8f std Z+28, r22 ; 0x1c
 
#if !_FS_READONLY
fs->free_clust = (CLUST)0xFFFFFFFF;
15fe: 8f ef ldi r24, 0xFF ; 255
1600: 9f ef ldi r25, 0xFF ; 255
1602: 93 8f std Z+27, r25 ; 0x1b
1604: 82 8f std Z+26, r24 ; 0x1a
fs->free_clust = LD_DWORD(&fs->win[FSI_Free_Count]);
}
}
#endif
#endif
fs->id = ++fsid; /* File system mount ID */
1606: 80 91 12 01 lds r24, 0x0112
160a: 90 91 13 01 lds r25, 0x0113
160e: 01 96 adiw r24, 0x01 ; 1
1610: 90 93 13 01 sts 0x0113, r25
1614: 80 93 12 01 sts 0x0112, r24
1618: 91 83 std Z+1, r25 ; 0x01
161a: 80 83 st Z, r24
161c: a5 c2 rjmp .+1354 ; 0x1b68 <f_open+0x7ba>
161e: 2a e0 ldi r18, 0x0A ; 10
1620: 30 e0 ldi r19, 0x00 ; 0
1622: 95 c2 rjmp .+1322 ; 0x1b4e <f_open+0x7a0>
1624: 29 e0 ldi r18, 0x09 ; 9
1626: 30 e0 ldi r19, 0x00 ; 0
1628: 92 c2 rjmp .+1316 ; 0x1b4e <f_open+0x7a0>
162a: 2b e0 ldi r18, 0x0B ; 11
162c: 30 e0 ldi r19, 0x00 ; 0
162e: 8f c2 rjmp .+1310 ; 0x1b4e <f_open+0x7a0>
)
{
BYTE n, t, c, a, b;
 
 
memset(dirname, ' ', 8+3); /* Fill buffer with spaces */
1630: 2e 01 movw r4, r28
1632: 08 94 sec
1634: 41 1c adc r4, r1
1636: 51 1c adc r5, r1
((DWORD)LD_WORD(&dptr[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dptr[DIR_FstClusLO]);
dirobj->clust = dirobj->sclust = clust; /* Restart scannig with the new directory */
dirobj->sect = clust2sect(clust);
dirobj->index = 2;
1638: 92 e0 ldi r25, 0x02 ; 2
163a: 29 2e mov r2, r25
163c: 31 2c mov r3, r1
)
{
BYTE n, t, c, a, b;
 
 
memset(dirname, ' ', 8+3); /* Fill buffer with spaces */
163e: 4b e0 ldi r20, 0x0B ; 11
1640: 50 e0 ldi r21, 0x00 ; 0
1642: 60 e2 ldi r22, 0x20 ; 32
1644: 70 e0 ldi r23, 0x00 ; 0
1646: c2 01 movw r24, r4
1648: 0e 94 ac 11 call 0x2358 ; 0x2358 <memset>
164c: 20 e0 ldi r18, 0x00 ; 0
164e: 48 e0 ldi r20, 0x08 ; 8
1650: 90 e0 ldi r25, 0x00 ; 0
1652: 38 e1 ldi r19, 0x18 ; 24
1654: 02 c0 rjmp .+4 ; 0x165a <f_open+0x2ac>
1656: 28 e0 ldi r18, 0x08 ; 8
1658: 4b e0 ldi r20, 0x0B ; 11
a = 0; b = 0x18; /* NT flag */
n = 0; t = 8;
for (;;) {
c = *(*path)++;
165a: f3 01 movw r30, r6
165c: 11 91 ld r17, Z+
165e: 3f 01 movw r6, r30
if (c == '\0' || c == '/') { /* Reached to end of str or directory separator */
1660: 11 23 and r17, r17
1662: 11 f0 breq .+4 ; 0x1668 <f_open+0x2ba>
1664: 1f 32 cpi r17, 0x2F ; 47
1666: 49 f4 brne .+18 ; 0x167a <f_open+0x2cc>
if (n == 0) break;
1668: 22 23 and r18, r18
166a: 09 f4 brne .+2 ; 0x166e <f_open+0x2c0>
166c: c7 c0 rjmp .+398 ; 0x17fc <f_open+0x44e>
dirname[11] = _USE_NTFLAG ? (a & b) : 0;
166e: 39 23 and r19, r25
1670: 3c 87 std Y+12, r19 ; 0x0c
*dir = NULL; return FR_OK;
}
 
for (;;) {
ds = make_dirfile(&path, fn); /* Get a paragraph into fn[] */
if (ds == 1) return FR_INVALID_NAME;
1672: 11 30 cpi r17, 0x01 ; 1
1674: 09 f0 breq .+2 ; 0x1678 <f_open+0x2ca>
1676: 44 c0 rjmp .+136 ; 0x1700 <f_open+0x352>
1678: c1 c0 rjmp .+386 ; 0x17fc <f_open+0x44e>
if (c == '\0' || c == '/') { /* Reached to end of str or directory separator */
if (n == 0) break;
dirname[11] = _USE_NTFLAG ? (a & b) : 0;
return c;
}
if (c <= ' ' || c == 0x7F) break; /* Reject invisible chars */
167a: 11 32 cpi r17, 0x21 ; 33
167c: 08 f4 brcc .+2 ; 0x1680 <f_open+0x2d2>
167e: be c0 rjmp .+380 ; 0x17fc <f_open+0x44e>
1680: 1f 37 cpi r17, 0x7F ; 127
1682: 09 f4 brne .+2 ; 0x1686 <f_open+0x2d8>
1684: bb c0 rjmp .+374 ; 0x17fc <f_open+0x44e>
if (c == '.') {
1686: 1e 32 cpi r17, 0x2E ; 46
1688: 41 f4 brne .+16 ; 0x169a <f_open+0x2ec>
if (!(a & 1) && n >= 1 && n <= 8) { /* Enter extension part */
168a: 90 fd sbrc r25, 0
168c: b7 c0 rjmp .+366 ; 0x17fc <f_open+0x44e>
168e: 22 23 and r18, r18
1690: 09 f4 brne .+2 ; 0x1694 <f_open+0x2e6>
1692: b4 c0 rjmp .+360 ; 0x17fc <f_open+0x44e>
1694: 29 30 cpi r18, 0x09 ; 9
1696: f8 f2 brcs .-66 ; 0x1656 <f_open+0x2a8>
1698: b1 c0 rjmp .+354 ; 0x17fc <f_open+0x44e>
(c >= 0xE0 && c <= 0xFC))) {
if (n == 0 && c == 0xE5) /* Change heading \xE5 to \x05 */
c = 0x05;
a ^= 1; goto md_l2;
}
if (c == '"') break; /* Reject " */
169a: 12 32 cpi r17, 0x22 ; 34
169c: 09 f4 brne .+2 ; 0x16a0 <f_open+0x2f2>
169e: ae c0 rjmp .+348 ; 0x17fc <f_open+0x44e>
if (c <= ')') goto md_l1; /* Accept ! # $ % & ' ( ) */
16a0: 1a 32 cpi r17, 0x2A ; 42
16a2: 20 f1 brcs .+72 ; 0x16ec <f_open+0x33e>
if (c <= ',') break; /* Reject * + , */
16a4: 1d 32 cpi r17, 0x2D ; 45
16a6: 08 f4 brcc .+2 ; 0x16aa <f_open+0x2fc>
16a8: a9 c0 rjmp .+338 ; 0x17fc <f_open+0x44e>
if (c <= '9') goto md_l1; /* Accept - 0-9 */
16aa: 1a 33 cpi r17, 0x3A ; 58
16ac: f8 f0 brcs .+62 ; 0x16ec <f_open+0x33e>
if (c <= '?') break; /* Reject : ; < = > ? */
16ae: 10 34 cpi r17, 0x40 ; 64
16b0: 08 f4 brcc .+2 ; 0x16b4 <f_open+0x306>
16b2: a4 c0 rjmp .+328 ; 0x17fc <f_open+0x44e>
if (!(a & 1)) { /* These checks are not applied to S-JIS 2nd byte */
16b4: 90 fd sbrc r25, 0
16b6: 1a c0 rjmp .+52 ; 0x16ec <f_open+0x33e>
if (c == '|') break; /* Reject | */
16b8: 1c 37 cpi r17, 0x7C ; 124
16ba: 09 f4 brne .+2 ; 0x16be <f_open+0x310>
16bc: 9f c0 rjmp .+318 ; 0x17fc <f_open+0x44e>
if (c >= '[' && c <= ']') break;/* Reject [ \ ] */
16be: 81 2f mov r24, r17
16c0: 8b 55 subi r24, 0x5B ; 91
16c2: 83 30 cpi r24, 0x03 ; 3
16c4: 08 f4 brcc .+2 ; 0x16c8 <f_open+0x31a>
16c6: 9a c0 rjmp .+308 ; 0x17fc <f_open+0x44e>
if (_USE_NTFLAG && c >= 'A' && c <= 'Z')
16c8: 86 5e subi r24, 0xE6 ; 230
16ca: 8a 31 cpi r24, 0x1A ; 26
16cc: 28 f4 brcc .+10 ; 0x16d8 <f_open+0x32a>
(t == 8) ? (b &= ~0x08) : (b &= ~0x10);
16ce: 48 30 cpi r20, 0x08 ; 8
16d0: 11 f4 brne .+4 ; 0x16d6 <f_open+0x328>
16d2: 37 7f andi r19, 0xF7 ; 247
16d4: 01 c0 rjmp .+2 ; 0x16d8 <f_open+0x32a>
16d6: 3f 7e andi r19, 0xEF ; 239
if (c >= 'a' && c <= 'z') { /* Convert to upper case */
16d8: 81 2f mov r24, r17
16da: 81 56 subi r24, 0x61 ; 97
16dc: 8a 31 cpi r24, 0x1A ; 26
16de: 30 f4 brcc .+12 ; 0x16ec <f_open+0x33e>
c -= 0x20;
16e0: 10 52 subi r17, 0x20 ; 32
if (_USE_NTFLAG) (t == 8) ? (a |= 0x08) : (a |= 0x10);
16e2: 48 30 cpi r20, 0x08 ; 8
16e4: 11 f4 brne .+4 ; 0x16ea <f_open+0x33c>
16e6: 98 60 ori r25, 0x08 ; 8
16e8: 01 c0 rjmp .+2 ; 0x16ec <f_open+0x33e>
16ea: 90 61 ori r25, 0x10 ; 16
}
}
md_l1:
a &= ~1;
md_l2:
if (n >= t) break;
16ec: 24 17 cp r18, r20
16ee: 08 f0 brcs .+2 ; 0x16f2 <f_open+0x344>
16f0: 85 c0 rjmp .+266 ; 0x17fc <f_open+0x44e>
c -= 0x20;
if (_USE_NTFLAG) (t == 8) ? (a |= 0x08) : (a |= 0x10);
}
}
md_l1:
a &= ~1;
16f2: 9e 7f andi r25, 0xFE ; 254
md_l2:
if (n >= t) break;
dirname[n++] = c;
16f4: f2 01 movw r30, r4
16f6: e2 0f add r30, r18
16f8: f1 1d adc r31, r1
16fa: 10 83 st Z, r17
16fc: 2f 5f subi r18, 0xFF ; 255
16fe: ad cf rjmp .-166 ; 0x165a <f_open+0x2ac>
 
for (;;) {
ds = make_dirfile(&path, fn); /* Get a paragraph into fn[] */
if (ds == 1) return FR_INVALID_NAME;
for (;;) {
if (!move_window(dirobj->sect)) return FR_RW_ERROR;
1700: 6f 89 ldd r22, Y+23 ; 0x17
1702: 78 8d ldd r23, Y+24 ; 0x18
1704: 89 8d ldd r24, Y+25 ; 0x19
1706: 9a 8d ldd r25, Y+26 ; 0x1a
1708: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
170c: 88 23 and r24, r24
170e: 31 f4 brne .+12 ; 0x171c <f_open+0x36e>
1710: 90 e0 ldi r25, 0x00 ; 0
1712: 9c 01 movw r18, r24
1714: 59 01 movw r10, r18
1716: 28 e0 ldi r18, 0x08 ; 8
1718: 30 e0 ldi r19, 0x00 ; 0
171a: 84 c0 rjmp .+264 ; 0x1824 <f_open+0x476>
dptr = &fs->win[(dirobj->index & 15) * 32]; /* Pointer to the directory entry */
171c: 2f 85 ldd r18, Y+15 ; 0x0f
171e: 38 89 ldd r19, Y+16 ; 0x10
1720: 2f 70 andi r18, 0x0F ; 15
1722: 30 70 andi r19, 0x00 ; 0
1724: 85 e0 ldi r24, 0x05 ; 5
1726: 22 0f add r18, r18
1728: 33 1f adc r19, r19
172a: 8a 95 dec r24
172c: e1 f7 brne .-8 ; 0x1726 <f_open+0x378>
if (dptr[DIR_Name] == 0) /* Has it reached to end of dir? */
172e: f6 01 movw r30, r12
1730: e2 0f add r30, r18
1732: f3 1f adc r31, r19
1734: 80 a1 ldd r24, Z+32 ; 0x20
1736: 88 23 and r24, r24
1738: e1 f0 breq .+56 ; 0x1772 <f_open+0x3c4>
return !ds ? FR_NO_FILE : FR_NO_PATH;
if (dptr[DIR_Name] != 0xE5 /* Matched? */
173a: 85 3e cpi r24, 0xE5 ; 229
173c: a1 f0 breq .+40 ; 0x1766 <f_open+0x3b8>
for (;;) {
ds = make_dirfile(&path, fn); /* Get a paragraph into fn[] */
if (ds == 1) return FR_INVALID_NAME;
for (;;) {
if (!move_window(dirobj->sect)) return FR_RW_ERROR;
dptr = &fs->win[(dirobj->index & 15) * 32]; /* Pointer to the directory entry */
173e: 00 e2 ldi r16, 0x20 ; 32
1740: a0 2e mov r10, r16
1742: b1 2c mov r11, r1
1744: a2 0e add r10, r18
1746: b3 1e adc r11, r19
1748: ac 0c add r10, r12
174a: bd 1c adc r11, r13
if (dptr[DIR_Name] == 0) /* Has it reached to end of dir? */
return !ds ? FR_NO_FILE : FR_NO_PATH;
if (dptr[DIR_Name] != 0xE5 /* Matched? */
174c: f5 01 movw r30, r10
174e: 83 85 ldd r24, Z+11 ; 0x0b
1750: 08 2f mov r16, r24
1752: 83 fd sbrc r24, 3
1754: 08 c0 rjmp .+16 ; 0x1766 <f_open+0x3b8>
1756: 4b e0 ldi r20, 0x0B ; 11
1758: 50 e0 ldi r21, 0x00 ; 0
175a: b2 01 movw r22, r4
175c: c5 01 movw r24, r10
175e: 0e 94 96 11 call 0x232c ; 0x232c <memcmp>
1762: 00 97 sbiw r24, 0x00 ; 0
1764: 51 f0 breq .+20 ; 0x177a <f_open+0x3cc>
&& !(dptr[DIR_Attr] & AM_VOL)
&& !memcmp(&dptr[DIR_Name], fn, 8+3) ) break;
if (!next_dir_entry(dirobj)) /* Next directory pointer */
1766: ce 01 movw r24, r28
1768: 0d 96 adiw r24, 0x0d ; 13
176a: 0e 94 2c 06 call 0xc58 ; 0xc58 <next_dir_entry>
176e: 88 23 and r24, r24
1770: 39 f6 brne .-114 ; 0x1700 <f_open+0x352>
return !ds ? FR_NO_FILE : FR_NO_PATH;
1772: 11 23 and r17, r17
1774: 09 f0 breq .+2 ; 0x1778 <f_open+0x3ca>
1776: 49 c0 rjmp .+146 ; 0x180a <f_open+0x45c>
1778: 4f c0 rjmp .+158 ; 0x1818 <f_open+0x46a>
}
if (!ds) { *dir = dptr; return FR_OK; } /* Matched with end of path */
177a: 11 23 and r17, r17
177c: 19 f4 brne .+6 ; 0x1784 <f_open+0x3d6>
177e: 20 e0 ldi r18, 0x00 ; 0
1780: 30 e0 ldi r19, 0x00 ; 0
1782: 50 c0 rjmp .+160 ; 0x1824 <f_open+0x476>
if (!(dptr[DIR_Attr] & AM_DIR)) return FR_NO_PATH; /* Cannot trace because it is a file */
1784: 04 ff sbrs r16, 4
1786: 41 c0 rjmp .+130 ; 0x180a <f_open+0x45c>
clust = /* Get cluster# of the directory */
1788: f5 01 movw r30, r10
178a: e2 8c ldd r14, Z+26 ; 0x1a
178c: f3 8c ldd r15, Z+27 ; 0x1b
#if _FAT32
((DWORD)LD_WORD(&dptr[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dptr[DIR_FstClusLO]);
dirobj->clust = dirobj->sclust = clust; /* Restart scannig with the new directory */
178e: fe 8a std Y+22, r15 ; 0x16
1790: ed 8a std Y+21, r14 ; 0x15
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
CLUST clust /* Cluster# to be converted */
)
{
FATFS *fs = FatFs;
1792: 00 91 10 01 lds r16, 0x0110
1796: 10 91 11 01 lds r17, 0x0111
 
 
clust -= 2;
179a: b7 01 movw r22, r14
179c: 62 50 subi r22, 0x02 ; 2
179e: 70 40 sbci r23, 0x00 ; 0
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
17a0: f8 01 movw r30, r16
17a2: 86 89 ldd r24, Z+22 ; 0x16
17a4: 97 89 ldd r25, Z+23 ; 0x17
17a6: 02 97 sbiw r24, 0x02 ; 2
17a8: 68 17 cp r22, r24
17aa: 79 07 cpc r23, r25
17ac: 28 f0 brcs .+10 ; 0x17b8 <f_open+0x40a>
17ae: 20 e0 ldi r18, 0x00 ; 0
17b0: 30 e0 ldi r19, 0x00 ; 0
17b2: 40 e0 ldi r20, 0x00 ; 0
17b4: 50 e0 ldi r21, 0x00 ; 0
17b6: 14 c0 rjmp .+40 ; 0x17e0 <f_open+0x432>
return (DWORD)clust * fs->sects_clust + fs->database;
17b8: 80 e0 ldi r24, 0x00 ; 0
17ba: 90 e0 ldi r25, 0x00 ; 0
17bc: f8 01 movw r30, r16
17be: 25 8d ldd r18, Z+29 ; 0x1d
17c0: 30 e0 ldi r19, 0x00 ; 0
17c2: 40 e0 ldi r20, 0x00 ; 0
17c4: 50 e0 ldi r21, 0x00 ; 0
17c6: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
17ca: 9b 01 movw r18, r22
17cc: ac 01 movw r20, r24
17ce: f8 01 movw r30, r16
17d0: 80 89 ldd r24, Z+16 ; 0x10
17d2: 91 89 ldd r25, Z+17 ; 0x11
17d4: a2 89 ldd r26, Z+18 ; 0x12
17d6: b3 89 ldd r27, Z+19 ; 0x13
17d8: 28 0f add r18, r24
17da: 39 1f adc r19, r25
17dc: 4a 1f adc r20, r26
17de: 5b 1f adc r21, r27
clust = /* Get cluster# of the directory */
#if _FAT32
((DWORD)LD_WORD(&dptr[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dptr[DIR_FstClusLO]);
dirobj->clust = dirobj->sclust = clust; /* Restart scannig with the new directory */
17e0: fc 8a std Y+20, r15 ; 0x14
17e2: eb 8a std Y+19, r14 ; 0x13
dirobj->sect = clust2sect(clust);
17e4: 2f 8b std Y+23, r18 ; 0x17
17e6: 38 8f std Y+24, r19 ; 0x18
17e8: 49 8f std Y+25, r20 ; 0x19
17ea: 5a 8f std Y+26, r21 ; 0x1a
dirobj->index = 2;
17ec: 38 8a std Y+16, r3 ; 0x10
17ee: 2f 86 std Y+15, r2 ; 0x0f
17f0: 26 cf rjmp .-436 ; 0x163e <f_open+0x290>
17f2: 20 e0 ldi r18, 0x00 ; 0
17f4: 30 e0 ldi r19, 0x00 ; 0
17f6: aa 24 eor r10, r10
17f8: bb 24 eor r11, r11
17fa: 14 c0 rjmp .+40 ; 0x1824 <f_open+0x476>
17fc: 80 e0 ldi r24, 0x00 ; 0
17fe: 90 e0 ldi r25, 0x00 ; 0
1800: 9c 01 movw r18, r24
1802: 59 01 movw r10, r18
1804: 24 e0 ldi r18, 0x04 ; 4
1806: 30 e0 ldi r19, 0x00 ; 0
1808: 0d c0 rjmp .+26 ; 0x1824 <f_open+0x476>
180a: 80 e0 ldi r24, 0x00 ; 0
180c: 90 e0 ldi r25, 0x00 ; 0
180e: 9c 01 movw r18, r24
1810: 59 01 movw r10, r18
1812: 23 e0 ldi r18, 0x03 ; 3
1814: 30 e0 ldi r19, 0x00 ; 0
1816: 06 c0 rjmp .+12 ; 0x1824 <f_open+0x476>
1818: 80 e0 ldi r24, 0x00 ; 0
181a: 90 e0 ldi r25, 0x00 ; 0
181c: 9c 01 movw r18, r24
181e: 59 01 movw r10, r18
1820: 22 e0 ldi r18, 0x02 ; 2
1822: 30 e0 ldi r19, 0x00 ; 0
/* Trace the file path */
res = trace_path(&dirobj, fn, path, &dir); /* Trace the file path */
 
#if !_FS_READONLY
/* Create or Open a File */
if (mode & (FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)) {
1824: fb 8d ldd r31, Y+27 ; 0x1b
1826: 4f 2f mov r20, r31
1828: 50 e0 ldi r21, 0x00 ; 0
182a: ca 01 movw r24, r20
182c: 8c 71 andi r24, 0x1C ; 28
182e: 90 70 andi r25, 0x00 ; 0
1830: 89 2b or r24, r25
1832: 09 f4 brne .+2 ; 0x1836 <f_open+0x488>
1834: 41 c1 rjmp .+642 ; 0x1ab8 <f_open+0x70a>
CLUST rs;
DWORD dw;
if (res != FR_OK) { /* No file, create new */
1836: 21 15 cp r18, r1
1838: 31 05 cpc r19, r1
183a: 09 f4 brne .+2 ; 0x183e <f_open+0x490>
183c: d6 c0 rjmp .+428 ; 0x19ea <f_open+0x63c>
if (res != FR_NO_FILE) return res;
183e: 22 30 cpi r18, 0x02 ; 2
1840: 31 05 cpc r19, r1
1842: 09 f0 breq .+2 ; 0x1846 <f_open+0x498>
1844: 84 c1 rjmp .+776 ; 0x1b4e <f_open+0x7a0>
)
{
CLUST clust;
DWORD sector;
BYTE c, n, *dptr;
FATFS *fs = FatFs;
1846: 60 90 10 01 lds r6, 0x0110
184a: 70 90 11 01 lds r7, 0x0111
 
 
/* Re-initialize directory object */
clust = dirobj->sclust;
184e: 0b 89 ldd r16, Y+19 ; 0x13
1850: 1c 89 ldd r17, Y+20 ; 0x14
if (clust) { /* Dyanmic directory table */
1852: 01 15 cp r16, r1
1854: 11 05 cpc r17, r1
1856: 51 f1 breq .+84 ; 0x18ac <f_open+0x4fe>
dirobj->clust = clust;
1858: 1e 8b std Y+22, r17 ; 0x16
185a: 0d 8b std Y+21, r16 ; 0x15
)
{
FATFS *fs = FatFs;
 
 
clust -= 2;
185c: b8 01 movw r22, r16
185e: 62 50 subi r22, 0x02 ; 2
1860: 70 40 sbci r23, 0x00 ; 0
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
1862: f3 01 movw r30, r6
1864: 86 89 ldd r24, Z+22 ; 0x16
1866: 97 89 ldd r25, Z+23 ; 0x17
1868: 02 97 sbiw r24, 0x02 ; 2
186a: 68 17 cp r22, r24
186c: 79 07 cpc r23, r25
186e: 28 f0 brcs .+10 ; 0x187a <f_open+0x4cc>
1870: 20 e0 ldi r18, 0x00 ; 0
1872: 30 e0 ldi r19, 0x00 ; 0
1874: 40 e0 ldi r20, 0x00 ; 0
1876: 50 e0 ldi r21, 0x00 ; 0
1878: 14 c0 rjmp .+40 ; 0x18a2 <f_open+0x4f4>
return (DWORD)clust * fs->sects_clust + fs->database;
187a: 80 e0 ldi r24, 0x00 ; 0
187c: 90 e0 ldi r25, 0x00 ; 0
187e: f3 01 movw r30, r6
1880: 25 8d ldd r18, Z+29 ; 0x1d
1882: 30 e0 ldi r19, 0x00 ; 0
1884: 40 e0 ldi r20, 0x00 ; 0
1886: 50 e0 ldi r21, 0x00 ; 0
1888: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
188c: 9b 01 movw r18, r22
188e: ac 01 movw r20, r24
1890: f3 01 movw r30, r6
1892: 80 89 ldd r24, Z+16 ; 0x10
1894: 91 89 ldd r25, Z+17 ; 0x11
1896: a2 89 ldd r26, Z+18 ; 0x12
1898: b3 89 ldd r27, Z+19 ; 0x13
189a: 28 0f add r18, r24
189c: 39 1f adc r19, r25
189e: 4a 1f adc r20, r26
18a0: 5b 1f adc r21, r27
 
/* Re-initialize directory object */
clust = dirobj->sclust;
if (clust) { /* Dyanmic directory table */
dirobj->clust = clust;
dirobj->sect = clust2sect(clust);
18a2: 2f 8b std Y+23, r18 ; 0x17
18a4: 38 8f std Y+24, r19 ; 0x18
18a6: 49 8f std Y+25, r20 ; 0x19
18a8: 5a 8f std Y+26, r21 ; 0x1a
18aa: 09 c0 rjmp .+18 ; 0x18be <f_open+0x510>
} else { /* Static directory table */
dirobj->sect = fs->dirbase;
18ac: f3 01 movw r30, r6
18ae: 84 85 ldd r24, Z+12 ; 0x0c
18b0: 95 85 ldd r25, Z+13 ; 0x0d
18b2: a6 85 ldd r26, Z+14 ; 0x0e
18b4: b7 85 ldd r27, Z+15 ; 0x0f
18b6: 8f 8b std Y+23, r24 ; 0x17
18b8: 98 8f std Y+24, r25 ; 0x18
18ba: a9 8f std Y+25, r26 ; 0x19
18bc: ba 8f std Y+26, r27 ; 0x1a
}
dirobj->index = 0;
18be: 18 8a std Y+16, r1 ; 0x10
18c0: 1f 86 std Y+15, r1 ; 0x0f
dptr = &fs->win[(dirobj->index & 15) * 32]; /* Pointer to the directory entry */
c = dptr[DIR_Name];
if (c == 0 || c == 0xE5) { /* Found an empty entry! */
*dir = dptr; return FR_OK;
}
} while (next_dir_entry(dirobj)); /* Next directory pointer */
18c2: bd e0 ldi r27, 0x0D ; 13
18c4: eb 2e mov r14, r27
18c6: f1 2c mov r15, r1
18c8: ec 0e add r14, r28
18ca: fd 1e adc r15, r29
dirobj->sect = fs->dirbase;
}
dirobj->index = 0;
 
do {
if (!move_window(dirobj->sect)) return FR_RW_ERROR;
18cc: 6f 89 ldd r22, Y+23 ; 0x17
18ce: 78 8d ldd r23, Y+24 ; 0x18
18d0: 89 8d ldd r24, Y+25 ; 0x19
18d2: 9a 8d ldd r25, Y+26 ; 0x1a
18d4: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
18d8: 88 23 and r24, r24
18da: 09 f4 brne .+2 ; 0x18de <f_open+0x530>
18dc: 33 c1 rjmp .+614 ; 0x1b44 <f_open+0x796>
dptr = &fs->win[(dirobj->index & 15) * 32]; /* Pointer to the directory entry */
18de: ef 85 ldd r30, Y+15 ; 0x0f
18e0: f8 89 ldd r31, Y+16 ; 0x10
18e2: ef 70 andi r30, 0x0F ; 15
18e4: f0 70 andi r31, 0x00 ; 0
18e6: a5 e0 ldi r26, 0x05 ; 5
18e8: ee 0f add r30, r30
18ea: ff 1f adc r31, r31
18ec: aa 95 dec r26
18ee: e1 f7 brne .-8 ; 0x18e8 <f_open+0x53a>
18f0: b0 96 adiw r30, 0x20 ; 32
18f2: 53 01 movw r10, r6
18f4: ae 0e add r10, r30
18f6: bf 1e adc r11, r31
18f8: b0 97 sbiw r30, 0x20 ; 32
c = dptr[DIR_Name];
18fa: e6 0d add r30, r6
18fc: f7 1d adc r31, r7
18fe: 80 a1 ldd r24, Z+32 ; 0x20
if (c == 0 || c == 0xE5) { /* Found an empty entry! */
1900: 88 23 and r24, r24
1902: 09 f4 brne .+2 ; 0x1906 <f_open+0x558>
1904: 4c c1 rjmp .+664 ; 0x1b9e <f_open+0x7f0>
1906: 85 3e cpi r24, 0xE5 ; 229
1908: 09 f4 brne .+2 ; 0x190c <f_open+0x55e>
190a: 49 c1 rjmp .+658 ; 0x1b9e <f_open+0x7f0>
*dir = dptr; return FR_OK;
}
} while (next_dir_entry(dirobj)); /* Next directory pointer */
190c: c7 01 movw r24, r14
190e: 0e 94 2c 06 call 0xc58 ; 0xc58 <next_dir_entry>
1912: 88 23 and r24, r24
1914: d9 f6 brne .-74 ; 0x18cc <f_open+0x51e>
/* Reached to end of the directory table */
 
/* Abort when static table or could not stretch dynamic table */
if (!clust || !(clust = create_chain(dirobj->clust))) return FR_DENIED;
1916: 01 15 cp r16, r1
1918: 11 05 cpc r17, r1
191a: 09 f4 brne .+2 ; 0x191e <f_open+0x570>
191c: 10 c1 rjmp .+544 ; 0x1b3e <f_open+0x790>
191e: 8d 89 ldd r24, Y+21 ; 0x15
1920: 9e 89 ldd r25, Y+22 ; 0x16
1922: 0e 94 d1 04 call 0x9a2 ; 0x9a2 <create_chain>
1926: 8c 01 movw r16, r24
1928: 00 97 sbiw r24, 0x00 ; 0
192a: 09 f4 brne .+2 ; 0x192e <f_open+0x580>
192c: 08 c1 rjmp .+528 ; 0x1b3e <f_open+0x790>
if (clust == 1 || !move_window(0)) return FR_RW_ERROR;
192e: 81 30 cpi r24, 0x01 ; 1
1930: 91 05 cpc r25, r1
1932: 09 f4 brne .+2 ; 0x1936 <f_open+0x588>
1934: 07 c1 rjmp .+526 ; 0x1b44 <f_open+0x796>
1936: 60 e0 ldi r22, 0x00 ; 0
1938: 70 e0 ldi r23, 0x00 ; 0
193a: 80 e0 ldi r24, 0x00 ; 0
193c: 90 e0 ldi r25, 0x00 ; 0
193e: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
1942: 88 23 and r24, r24
1944: 09 f4 brne .+2 ; 0x1948 <f_open+0x59a>
1946: fe c0 rjmp .+508 ; 0x1b44 <f_open+0x796>
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
CLUST clust /* Cluster# to be converted */
)
{
FATFS *fs = FatFs;
1948: a0 90 10 01 lds r10, 0x0110
194c: b0 90 11 01 lds r11, 0x0111
 
 
clust -= 2;
1950: b8 01 movw r22, r16
1952: 62 50 subi r22, 0x02 ; 2
1954: 70 40 sbci r23, 0x00 ; 0
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
1956: f5 01 movw r30, r10
1958: 86 89 ldd r24, Z+22 ; 0x16
195a: 97 89 ldd r25, Z+23 ; 0x17
195c: 02 97 sbiw r24, 0x02 ; 2
195e: 68 17 cp r22, r24
1960: 79 07 cpc r23, r25
1962: 20 f0 brcs .+8 ; 0x196c <f_open+0x5be>
1964: cc 24 eor r12, r12
1966: dd 24 eor r13, r13
1968: 76 01 movw r14, r12
196a: 14 c0 rjmp .+40 ; 0x1994 <f_open+0x5e6>
return (DWORD)clust * fs->sects_clust + fs->database;
196c: 80 e0 ldi r24, 0x00 ; 0
196e: 90 e0 ldi r25, 0x00 ; 0
1970: f5 01 movw r30, r10
1972: 25 8d ldd r18, Z+29 ; 0x1d
1974: 30 e0 ldi r19, 0x00 ; 0
1976: 40 e0 ldi r20, 0x00 ; 0
1978: 50 e0 ldi r21, 0x00 ; 0
197a: 0e 94 86 14 call 0x290c ; 0x290c <__mulsi3>
197e: 6b 01 movw r12, r22
1980: 7c 01 movw r14, r24
1982: f5 01 movw r30, r10
1984: 80 89 ldd r24, Z+16 ; 0x10
1986: 91 89 ldd r25, Z+17 ; 0x11
1988: a2 89 ldd r26, Z+18 ; 0x12
198a: b3 89 ldd r27, Z+19 ; 0x13
198c: c8 0e add r12, r24
198e: d9 1e adc r13, r25
1990: ea 1e adc r14, r26
1992: fb 1e adc r15, r27
 
/* Abort when static table or could not stretch dynamic table */
if (!clust || !(clust = create_chain(dirobj->clust))) return FR_DENIED;
if (clust == 1 || !move_window(0)) return FR_RW_ERROR;
 
fs->winsect = sector = clust2sect(clust); /* Cleanup the expanded table */
1994: f3 01 movw r30, r6
1996: c4 82 std Z+4, r12 ; 0x04
1998: d5 82 std Z+5, r13 ; 0x05
199a: e6 82 std Z+6, r14 ; 0x06
199c: f7 82 std Z+7, r15 ; 0x07
memset(fs->win, 0, 512);
199e: e0 e2 ldi r30, 0x20 ; 32
19a0: ae 2e mov r10, r30
19a2: b1 2c mov r11, r1
19a4: a6 0c add r10, r6
19a6: b7 1c adc r11, r7
19a8: 80 e0 ldi r24, 0x00 ; 0
19aa: 92 e0 ldi r25, 0x02 ; 2
19ac: f5 01 movw r30, r10
19ae: 9c 01 movw r18, r24
19b0: 11 92 st Z+, r1
19b2: 21 50 subi r18, 0x01 ; 1
19b4: 30 40 sbci r19, 0x00 ; 0
19b6: e1 f7 brne .-8 ; 0x19b0 <f_open+0x602>
for (n = fs->sects_clust; n; n--) {
19b8: f3 01 movw r30, r6
19ba: 15 8d ldd r17, Z+29 ; 0x1d
19bc: 10 c0 rjmp .+32 ; 0x19de <f_open+0x630>
if (disk_write(0, fs->win, sector, 1) != RES_OK)
19be: 01 e0 ldi r16, 0x01 ; 1
19c0: a7 01 movw r20, r14
19c2: 96 01 movw r18, r12
19c4: b5 01 movw r22, r10
19c6: 80 e0 ldi r24, 0x00 ; 0
19c8: 0e 94 fb 0f call 0x1ff6 ; 0x1ff6 <disk_write>
19cc: 89 2b or r24, r25
19ce: 09 f0 breq .+2 ; 0x19d2 <f_open+0x624>
19d0: b9 c0 rjmp .+370 ; 0x1b44 <f_open+0x796>
return FR_RW_ERROR;
sector++;
19d2: 08 94 sec
19d4: c1 1c adc r12, r1
19d6: d1 1c adc r13, r1
19d8: e1 1c adc r14, r1
19da: f1 1c adc r15, r1
if (!clust || !(clust = create_chain(dirobj->clust))) return FR_DENIED;
if (clust == 1 || !move_window(0)) return FR_RW_ERROR;
 
fs->winsect = sector = clust2sect(clust); /* Cleanup the expanded table */
memset(fs->win, 0, 512);
for (n = fs->sects_clust; n; n--) {
19dc: 11 50 subi r17, 0x01 ; 1
19de: 11 23 and r17, r17
19e0: 71 f7 brne .-36 ; 0x19be <f_open+0x610>
if (disk_write(0, fs->win, sector, 1) != RES_OK)
return FR_RW_ERROR;
sector++;
}
fs->winflag = 1;
19e2: 81 e0 ldi r24, 0x01 ; 1
19e4: f3 01 movw r30, r6
19e6: 87 8f std Z+31, r24 ; 0x1f
19e8: da c0 rjmp .+436 ; 0x1b9e <f_open+0x7f0>
memset(dir, 0, 32); /* Initialize the new entry */
memcpy(&dir[DIR_Name], fn, 8+3);
dir[DIR_NTres] = fn[11];
mode |= FA_CREATE_ALWAYS;
} else { /* Any object is already existing */
if (mode & FA_CREATE_NEW) /* Cannot create new */
19ea: f2 ff sbrs r31, 2
19ec: 03 c0 rjmp .+6 ; 0x19f4 <f_open+0x646>
19ee: 27 e0 ldi r18, 0x07 ; 7
19f0: 30 e0 ldi r19, 0x00 ; 0
19f2: ad c0 rjmp .+346 ; 0x1b4e <f_open+0x7a0>
return FR_EXIST;
if (dir == NULL || (dir[DIR_Attr] & (AM_RDO|AM_DIR))) /* Cannot overwrite (R/O or DIR) */
19f4: a1 14 cp r10, r1
19f6: b1 04 cpc r11, r1
19f8: 09 f4 brne .+2 ; 0x19fc <f_open+0x64e>
19fa: a1 c0 rjmp .+322 ; 0x1b3e <f_open+0x790>
19fc: f5 01 movw r30, r10
19fe: 83 85 ldd r24, Z+11 ; 0x0b
1a00: 81 71 andi r24, 0x11 ; 17
1a02: 09 f0 breq .+2 ; 0x1a06 <f_open+0x658>
1a04: 9c c0 rjmp .+312 ; 0x1b3e <f_open+0x790>
return FR_DENIED;
if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero */
1a06: 43 ff sbrs r20, 3
1a08: 42 c0 rjmp .+132 ; 0x1a8e <f_open+0x6e0>
#if _FAT32
rs = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]);
ST_WORD(&dir[DIR_FstClusHI], 0);
#else
rs = LD_WORD(&dir[DIR_FstClusLO]);
1a0a: c2 8c ldd r12, Z+26 ; 0x1a
1a0c: d3 8c ldd r13, Z+27 ; 0x1b
#endif
ST_WORD(&dir[DIR_FstClusLO], 0); /* cluster = 0 */
1a0e: 13 8e std Z+27, r1 ; 0x1b
1a10: 12 8e std Z+26, r1 ; 0x1a
ST_DWORD(&dir[DIR_FileSize], 0); /* size = 0 */
1a12: 14 8e std Z+28, r1 ; 0x1c
1a14: 15 8e std Z+29, r1 ; 0x1d
1a16: 16 8e std Z+30, r1 ; 0x1e
1a18: 17 8e std Z+31, r1 ; 0x1f
fs->winflag = 1;
1a1a: 81 e0 ldi r24, 0x01 ; 1
1a1c: f4 01 movw r30, r8
1a1e: 87 8f std Z+31, r24 ; 0x1f
dw = fs->winsect; /* Remove the cluster chain */
1a20: 24 80 ldd r2, Z+4 ; 0x04
1a22: 35 80 ldd r3, Z+5 ; 0x05
1a24: 46 80 ldd r4, Z+6 ; 0x06
1a26: 57 80 ldd r5, Z+7 ; 0x07
BOOL remove_chain ( /* TRUE: successful, FALSE: failed */
CLUST clust /* Cluster# to remove chain from */
)
{
CLUST nxt;
FATFS *fs = FatFs;
1a28: e0 90 10 01 lds r14, 0x0110
1a2c: f0 90 11 01 lds r15, 0x0111
1a30: 86 01 movw r16, r12
1a32: 1c c0 rjmp .+56 ; 0x1a6c <f_open+0x6be>
 
 
while (clust >= 2 && clust < fs->max_clust) {
nxt = get_cluster(clust);
1a34: c8 01 movw r24, r16
1a36: 0e 94 53 04 call 0x8a6 ; 0x8a6 <get_cluster>
1a3a: 3c 01 movw r6, r24
if (nxt == 1) return FALSE;
1a3c: 81 30 cpi r24, 0x01 ; 1
1a3e: 91 05 cpc r25, r1
1a40: 09 f4 brne .+2 ; 0x1a44 <f_open+0x696>
1a42: 80 c0 rjmp .+256 ; 0x1b44 <f_open+0x796>
if (!put_cluster(clust, 0)) return FALSE;
1a44: 60 e0 ldi r22, 0x00 ; 0
1a46: 70 e0 ldi r23, 0x00 ; 0
1a48: c8 01 movw r24, r16
1a4a: 0e 94 c4 03 call 0x788 ; 0x788 <put_cluster>
1a4e: 88 23 and r24, r24
1a50: 09 f4 brne .+2 ; 0x1a54 <f_open+0x6a6>
1a52: 78 c0 rjmp .+240 ; 0x1b44 <f_open+0x796>
if (fs->free_clust != (CLUST)0xFFFFFFFF) {
1a54: f7 01 movw r30, r14
1a56: 82 8d ldd r24, Z+26 ; 0x1a
1a58: 93 8d ldd r25, Z+27 ; 0x1b
1a5a: ff ef ldi r31, 0xFF ; 255
1a5c: 8f 3f cpi r24, 0xFF ; 255
1a5e: 9f 07 cpc r25, r31
1a60: 21 f0 breq .+8 ; 0x1a6a <f_open+0x6bc>
fs->free_clust++;
1a62: 01 96 adiw r24, 0x01 ; 1
1a64: f7 01 movw r30, r14
1a66: 93 8f std Z+27, r25 ; 0x1b
1a68: 82 8f std Z+26, r24 ; 0x1a
1a6a: 83 01 movw r16, r6
{
CLUST nxt;
FATFS *fs = FatFs;
 
 
while (clust >= 2 && clust < fs->max_clust) {
1a6c: 02 30 cpi r16, 0x02 ; 2
1a6e: 11 05 cpc r17, r1
1a70: 08 f4 brcc .+2 ; 0x1a74 <f_open+0x6c6>
1a72: 72 c0 rjmp .+228 ; 0x1b58 <f_open+0x7aa>
1a74: f7 01 movw r30, r14
1a76: 86 89 ldd r24, Z+22 ; 0x16
1a78: 97 89 ldd r25, Z+23 ; 0x17
1a7a: 08 17 cp r16, r24
1a7c: 19 07 cpc r17, r25
1a7e: d0 f2 brcs .-76 ; 0x1a34 <f_open+0x686>
1a80: 6b c0 rjmp .+214 ; 0x1b58 <f_open+0x7aa>
ST_DWORD(&dir[DIR_FileSize], 0); /* size = 0 */
fs->winflag = 1;
dw = fs->winsect; /* Remove the cluster chain */
if (!remove_chain(rs) || !move_window(dw))
return FR_RW_ERROR;
fs->last_clust = rs - 1; /* Reuse the cluster hole */
1a82: 08 94 sec
1a84: c1 08 sbc r12, r1
1a86: d1 08 sbc r13, r1
1a88: f4 01 movw r30, r8
1a8a: d1 8e std Z+25, r13 ; 0x19
1a8c: c0 8e std Z+24, r12 ; 0x18
}
}
if (mode & FA_CREATE_ALWAYS) {
1a8e: fb 8d ldd r31, Y+27 ; 0x1b
1a90: f3 ff sbrs r31, 3
1a92: 22 c0 rjmp .+68 ; 0x1ad8 <f_open+0x72a>
dir[DIR_Attr] = AM_ARC; /* New attribute */
1a94: 80 e2 ldi r24, 0x20 ; 32
1a96: f5 01 movw r30, r10
1a98: 83 87 std Z+11, r24 ; 0x0b
dw = get_fattime();
1a9a: 0e 94 b0 00 call 0x160 ; 0x160 <get_fattime>
ST_DWORD(&dir[DIR_WrtTime], dw); /* Updated time */
1a9e: f5 01 movw r30, r10
1aa0: 66 8b std Z+22, r22 ; 0x16
1aa2: 77 8b std Z+23, r23 ; 0x17
1aa4: 80 8f std Z+24, r24 ; 0x18
1aa6: 91 8f std Z+25, r25 ; 0x19
ST_DWORD(&dir[DIR_CrtTime], dw); /* Created time */
1aa8: 66 87 std Z+14, r22 ; 0x0e
1aaa: 77 87 std Z+15, r23 ; 0x0f
1aac: 80 8b std Z+16, r24 ; 0x10
1aae: 91 8b std Z+17, r25 ; 0x11
fs->winflag = 1;
1ab0: 81 e0 ldi r24, 0x01 ; 1
1ab2: f4 01 movw r30, r8
1ab4: 87 8f std Z+31, r24 ; 0x1f
1ab6: 10 c0 rjmp .+32 ; 0x1ad8 <f_open+0x72a>
}
}
/* Open a File */
else {
#endif /* !_FS_READONLY */
if (res != FR_OK) return res; /* Trace failed */
1ab8: 21 15 cp r18, r1
1aba: 31 05 cpc r19, r1
1abc: 09 f0 breq .+2 ; 0x1ac0 <f_open+0x712>
1abe: 47 c0 rjmp .+142 ; 0x1b4e <f_open+0x7a0>
if (dir == NULL || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */
1ac0: a1 14 cp r10, r1
1ac2: b1 04 cpc r11, r1
1ac4: 09 f4 brne .+2 ; 0x1ac8 <f_open+0x71a>
1ac6: 41 c0 rjmp .+130 ; 0x1b4a <f_open+0x79c>
1ac8: f5 01 movw r30, r10
1aca: 83 85 ldd r24, Z+11 ; 0x0b
1acc: 84 fd sbrc r24, 4
1ace: 3d c0 rjmp .+122 ; 0x1b4a <f_open+0x79c>
return FR_NO_FILE;
#if !_FS_READONLY
if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
1ad0: 41 ff sbrs r20, 1
1ad2: 02 c0 rjmp .+4 ; 0x1ad8 <f_open+0x72a>
1ad4: 80 fd sbrc r24, 0
1ad6: 33 c0 rjmp .+102 ; 0x1b3e <f_open+0x790>
return FR_DENIED;
}
 
fp->dir_sect = fs->winsect; /* Pointer to the directory entry */
1ad8: f4 01 movw r30, r8
1ada: 84 81 ldd r24, Z+4 ; 0x04
1adc: 95 81 ldd r25, Z+5 ; 0x05
1ade: a6 81 ldd r26, Z+6 ; 0x06
1ae0: b7 81 ldd r27, Z+7 ; 0x07
1ae2: ec 8d ldd r30, Y+28 ; 0x1c
1ae4: fd 8d ldd r31, Y+29 ; 0x1d
1ae6: 86 8b std Z+22, r24 ; 0x16
1ae8: 97 8b std Z+23, r25 ; 0x17
1aea: a0 8f std Z+24, r26 ; 0x18
1aec: b1 8f std Z+25, r27 ; 0x19
fp->dir_ptr = dir;
1aee: b3 8e std Z+27, r11 ; 0x1b
1af0: a2 8e std Z+26, r10 ; 0x1a
#endif
fp->flag = mode; /* File access mode */
1af2: 2b 8d ldd r18, Y+27 ; 0x1b
1af4: 22 83 std Z+2, r18 ; 0x02
fp->org_clust = /* File start cluster */
1af6: f5 01 movw r30, r10
1af8: 82 8d ldd r24, Z+26 ; 0x1a
1afa: 93 8d ldd r25, Z+27 ; 0x1b
1afc: ec 8d ldd r30, Y+28 ; 0x1c
1afe: fd 8d ldd r31, Y+29 ; 0x1d
1b00: 97 87 std Z+15, r25 ; 0x0f
1b02: 86 87 std Z+14, r24 ; 0x0e
#if _FAT32
((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dir[DIR_FstClusLO]);
fp->fsize = LD_DWORD(&dir[DIR_FileSize]); /* File size */
1b04: f5 01 movw r30, r10
1b06: 84 8d ldd r24, Z+28 ; 0x1c
1b08: 95 8d ldd r25, Z+29 ; 0x1d
1b0a: a6 8d ldd r26, Z+30 ; 0x1e
1b0c: b7 8d ldd r27, Z+31 ; 0x1f
1b0e: ec 8d ldd r30, Y+28 ; 0x1c
1b10: fd 8d ldd r31, Y+29 ; 0x1d
1b12: 82 87 std Z+10, r24 ; 0x0a
1b14: 93 87 std Z+11, r25 ; 0x0b
1b16: a4 87 std Z+12, r26 ; 0x0c
1b18: b5 87 std Z+13, r27 ; 0x0d
fp->fptr = 0; /* File ptr */
1b1a: 16 82 std Z+6, r1 ; 0x06
1b1c: 17 82 std Z+7, r1 ; 0x07
1b1e: 10 86 std Z+8, r1 ; 0x08
1b20: 11 86 std Z+9, r1 ; 0x09
fp->sect_clust = 1; /* Sector counter */
1b22: 81 e0 ldi r24, 0x01 ; 1
1b24: 83 83 std Z+3, r24 ; 0x03
fp->fs = fs; fp->id = fs->id; /* Owner file system object of the file */
1b26: 95 82 std Z+5, r9 ; 0x05
1b28: 84 82 std Z+4, r8 ; 0x04
1b2a: f4 01 movw r30, r8
1b2c: 80 81 ld r24, Z
1b2e: 91 81 ldd r25, Z+1 ; 0x01
1b30: ec 8d ldd r30, Y+28 ; 0x1c
1b32: fd 8d ldd r31, Y+29 ; 0x1d
1b34: 91 83 std Z+1, r25 ; 0x01
1b36: 80 83 st Z, r24
1b38: 20 e0 ldi r18, 0x00 ; 0
1b3a: 30 e0 ldi r19, 0x00 ; 0
1b3c: 08 c0 rjmp .+16 ; 0x1b4e <f_open+0x7a0>
 
return FR_OK;
1b3e: 26 e0 ldi r18, 0x06 ; 6
1b40: 30 e0 ldi r19, 0x00 ; 0
1b42: 05 c0 rjmp .+10 ; 0x1b4e <f_open+0x7a0>
1b44: 28 e0 ldi r18, 0x08 ; 8
1b46: 30 e0 ldi r19, 0x00 ; 0
1b48: 02 c0 rjmp .+4 ; 0x1b4e <f_open+0x7a0>
1b4a: 22 e0 ldi r18, 0x02 ; 2
1b4c: 30 e0 ldi r19, 0x00 ; 0
}
1b4e: c9 01 movw r24, r18
1b50: 6d 96 adiw r28, 0x1d ; 29
1b52: e2 e1 ldi r30, 0x12 ; 18
1b54: 0c 94 e3 14 jmp 0x29c6 ; 0x29c6 <__epilogue_restores__>
#endif
ST_WORD(&dir[DIR_FstClusLO], 0); /* cluster = 0 */
ST_DWORD(&dir[DIR_FileSize], 0); /* size = 0 */
fs->winflag = 1;
dw = fs->winsect; /* Remove the cluster chain */
if (!remove_chain(rs) || !move_window(dw))
1b58: c2 01 movw r24, r4
1b5a: b1 01 movw r22, r2
1b5c: 0e 94 5a 03 call 0x6b4 ; 0x6b4 <move_window>
1b60: 88 23 and r24, r24
1b62: 09 f0 breq .+2 ; 0x1b66 <f_open+0x7b8>
1b64: 8e cf rjmp .-228 ; 0x1a82 <f_open+0x6d4>
1b66: ee cf rjmp .-36 ; 0x1b44 <f_open+0x796>
)
{
CLUST clust;
char ds;
BYTE *dptr = NULL;
FATFS *fs = FatFs;
1b68: c0 90 10 01 lds r12, 0x0110
1b6c: d0 90 11 01 lds r13, 0x0111
 
/* Initialize directory object */
clust = fs->dirbase;
1b70: f6 01 movw r30, r12
1b72: 84 85 ldd r24, Z+12 ; 0x0c
1b74: 95 85 ldd r25, Z+13 ; 0x0d
dirobj->clust = dirobj->sclust = clust;
dirobj->sect = clust2sect(clust);
} else
#endif
{
dirobj->clust = dirobj->sclust = 0;
1b76: 1c 8a std Y+20, r1 ; 0x14
1b78: 1b 8a std Y+19, r1 ; 0x13
1b7a: 1e 8a std Y+22, r1 ; 0x16
1b7c: 1d 8a std Y+21, r1 ; 0x15
dirobj->sect = clust;
1b7e: a0 e0 ldi r26, 0x00 ; 0
1b80: b0 e0 ldi r27, 0x00 ; 0
1b82: 8f 8b std Y+23, r24 ; 0x17
1b84: 98 8f std Y+24, r25 ; 0x18
1b86: a9 8f std Y+25, r26 ; 0x19
1b88: ba 8f std Y+26, r27 ; 0x1a
}
dirobj->index = 0;
1b8a: 18 8a std Y+16, r1 ; 0x10
1b8c: 1f 86 std Y+15, r1 ; 0x0f
dirobj->fs = fs;
1b8e: da 8a std Y+18, r13 ; 0x12
1b90: c9 8a std Y+17, r12 ; 0x11
 
if (*path == '\0') { /* Null path means the root directory */
1b92: f3 01 movw r30, r6
1b94: 80 81 ld r24, Z
1b96: 88 23 and r24, r24
1b98: 09 f0 breq .+2 ; 0x1b9c <f_open+0x7ee>
1b9a: 4a cd rjmp .-1388 ; 0x1630 <f_open+0x282>
1b9c: 2a ce rjmp .-940 ; 0x17f2 <f_open+0x444>
DWORD dw;
if (res != FR_OK) { /* No file, create new */
if (res != FR_NO_FILE) return res;
res = reserve_direntry(&dirobj, &dir);
if (res != FR_OK) return res;
memset(dir, 0, 32); /* Initialize the new entry */
1b9e: 80 e2 ldi r24, 0x20 ; 32
1ba0: f5 01 movw r30, r10
1ba2: 11 92 st Z+, r1
1ba4: 8a 95 dec r24
1ba6: e9 f7 brne .-6 ; 0x1ba2 <f_open+0x7f4>
memcpy(&dir[DIR_Name], fn, 8+3);
1ba8: d5 01 movw r26, r10
1baa: fe 01 movw r30, r28
1bac: 31 96 adiw r30, 0x01 ; 1
1bae: 8b e0 ldi r24, 0x0B ; 11
1bb0: 01 90 ld r0, Z+
1bb2: 0d 92 st X+, r0
1bb4: 81 50 subi r24, 0x01 ; 1
1bb6: e1 f7 brne .-8 ; 0x1bb0 <f_open+0x802>
dir[DIR_NTres] = fn[11];
1bb8: 8c 85 ldd r24, Y+12 ; 0x0c
1bba: f5 01 movw r30, r10
1bbc: 84 87 std Z+12, r24 ; 0x0c
mode |= FA_CREATE_ALWAYS;
1bbe: fb 8d ldd r31, Y+27 ; 0x1b
1bc0: f8 60 ori r31, 0x08 ; 8
1bc2: fb 8f std Y+27, r31 ; 0x1b
1bc4: 64 cf rjmp .-312 ; 0x1a8e <f_open+0x6e0>
 
00001bc6 <rcvr_datablock>:
static
BOOL rcvr_datablock (
BYTE *buff, /* Data buffer to store received data */
UINT btr /* Byte count (must be even number) */
)
{
1bc6: fc 01 movw r30, r24
BYTE token;
 
 
Timer1 = 10;
1bc8: 8a e0 ldi r24, 0x0A ; 10
1bca: 80 93 15 01 sts 0x0115, r24
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1bce: 9f ef ldi r25, 0xFF ; 255
1bd0: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1bd2: 0d b4 in r0, 0x2d ; 45
1bd4: 07 fe sbrs r0, 7
1bd6: fd cf rjmp .-6 ; 0x1bd2 <rcvr_datablock+0xc>
return SPDR;
1bd8: 8e b5 in r24, 0x2e ; 46
 
 
Timer1 = 10;
do { /* Wait for data packet in timeout of 100ms */
token = rcvr_spi();
} while ((token == 0xFF) && Timer1);
1bda: 8f 3f cpi r24, 0xFF ; 255
1bdc: 29 f4 brne .+10 ; 0x1be8 <rcvr_datablock+0x22>
1bde: 80 91 15 01 lds r24, 0x0115
1be2: 88 23 and r24, r24
1be4: a9 f7 brne .-22 ; 0x1bd0 <rcvr_datablock+0xa>
1be6: 22 c0 rjmp .+68 ; 0x1c2c <rcvr_datablock+0x66>
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
1be8: 8e 3f cpi r24, 0xFE ; 254
1bea: 01 f5 brne .+64 ; 0x1c2c <rcvr_datablock+0x66>
 
do { /* Receive the data block into buffer */
rcvr_spi_m(buff++);
1bec: 9f ef ldi r25, 0xFF ; 255
1bee: 9e bd out 0x2e, r25 ; 46
1bf0: 0d b4 in r0, 0x2d ; 45
1bf2: 07 fe sbrs r0, 7
1bf4: fd cf rjmp .-6 ; 0x1bf0 <rcvr_datablock+0x2a>
1bf6: 8e b5 in r24, 0x2e ; 46
1bf8: 80 83 st Z, r24
rcvr_spi_m(buff++);
1bfa: 9e bd out 0x2e, r25 ; 46
1bfc: 0d b4 in r0, 0x2d ; 45
1bfe: 07 fe sbrs r0, 7
1c00: fd cf rjmp .-6 ; 0x1bfc <rcvr_datablock+0x36>
1c02: 8e b5 in r24, 0x2e ; 46
1c04: 81 83 std Z+1, r24 ; 0x01
} while (btr -= 2);
1c06: 62 50 subi r22, 0x02 ; 2
1c08: 70 40 sbci r23, 0x00 ; 0
1c0a: 11 f0 breq .+4 ; 0x1c10 <rcvr_datablock+0x4a>
static
BOOL rcvr_datablock (
BYTE *buff, /* Data buffer to store received data */
UINT btr /* Byte count (must be even number) */
)
{
1c0c: 32 96 adiw r30, 0x02 ; 2
1c0e: ef cf rjmp .-34 ; 0x1bee <rcvr_datablock+0x28>
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1c10: 8f ef ldi r24, 0xFF ; 255
1c12: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1c14: 0d b4 in r0, 0x2d ; 45
1c16: 07 fe sbrs r0, 7
1c18: fd cf rjmp .-6 ; 0x1c14 <rcvr_datablock+0x4e>
return SPDR;
1c1a: 8e b5 in r24, 0x2e ; 46
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1c1c: 8f ef ldi r24, 0xFF ; 255
1c1e: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1c20: 0d b4 in r0, 0x2d ; 45
1c22: 07 fe sbrs r0, 7
1c24: fd cf rjmp .-6 ; 0x1c20 <rcvr_datablock+0x5a>
return SPDR;
1c26: 8e b5 in r24, 0x2e ; 46
1c28: 81 e0 ldi r24, 0x01 ; 1
1c2a: 08 95 ret
rcvr_spi_m(buff++);
} while (btr -= 2);
rcvr_spi(); /* Discard CRC */
rcvr_spi();
 
return TRUE; /* Return with success */
1c2c: 80 e0 ldi r24, 0x00 ; 0
}
1c2e: 08 95 ret
 
00001c30 <xmit_datablock>:
static
BOOL xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
1c30: fc 01 movw r30, r24
BYTE wait_ready (void)
{
BYTE res;
 
 
Timer2 = 50; /* Wait for ready in timeout of 500ms */
1c32: 82 e3 ldi r24, 0x32 ; 50
1c34: 80 93 16 01 sts 0x0116, r24
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1c38: 8f ef ldi r24, 0xFF ; 255
1c3a: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1c3c: 0d b4 in r0, 0x2d ; 45
1c3e: 07 fe sbrs r0, 7
1c40: fd cf rjmp .-6 ; 0x1c3c <xmit_datablock+0xc>
return SPDR;
1c42: 8e b5 in r24, 0x2e ; 46
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1c44: 9f ef ldi r25, 0xFF ; 255
1c46: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1c48: 0d b4 in r0, 0x2d ; 45
1c4a: 07 fe sbrs r0, 7
1c4c: fd cf rjmp .-6 ; 0x1c48 <xmit_datablock+0x18>
return SPDR;
1c4e: 8e b5 in r24, 0x2e ; 46
 
Timer2 = 50; /* Wait for ready in timeout of 500ms */
rcvr_spi();
do
res = rcvr_spi();
while ((res != 0xFF) && Timer2);
1c50: 8f 3f cpi r24, 0xFF ; 255
1c52: 31 f0 breq .+12 ; 0x1c60 <xmit_datablock+0x30>
1c54: 80 91 16 01 lds r24, 0x0116
1c58: 88 23 and r24, r24
1c5a: a9 f7 brne .-22 ; 0x1c46 <xmit_datablock+0x16>
1c5c: 90 e0 ldi r25, 0x00 ; 0
1c5e: 2e c0 rjmp .+92 ; 0x1cbc <xmit_datablock+0x8c>
BYTE resp, wc;
 
 
if (wait_ready() != 0xFF) return FALSE;
 
xmit_spi(token); /* Xmit data token */
1c60: 6e bd out 0x2e, r22 ; 46
1c62: 0d b4 in r0, 0x2d ; 45
1c64: 07 fe sbrs r0, 7
1c66: fd cf rjmp .-6 ; 0x1c62 <xmit_datablock+0x32>
if (token != 0xFD) { /* Is data token */
1c68: 6d 3f cpi r22, 0xFD ; 253
1c6a: 11 f4 brne .+4 ; 0x1c70 <xmit_datablock+0x40>
1c6c: 91 e0 ldi r25, 0x01 ; 1
1c6e: 26 c0 rjmp .+76 ; 0x1cbc <xmit_datablock+0x8c>
1c70: 90 e0 ldi r25, 0x00 ; 0
wc = 0;
do { /* Xmit the 512 byte data block to MMC */
xmit_spi(*buff++);
1c72: 80 81 ld r24, Z
1c74: 8e bd out 0x2e, r24 ; 46
1c76: 0d b4 in r0, 0x2d ; 45
1c78: 07 fe sbrs r0, 7
1c7a: fd cf rjmp .-6 ; 0x1c76 <xmit_datablock+0x46>
xmit_spi(*buff++);
1c7c: 81 81 ldd r24, Z+1 ; 0x01
1c7e: 8e bd out 0x2e, r24 ; 46
1c80: 0d b4 in r0, 0x2d ; 45
1c82: 07 fe sbrs r0, 7
1c84: fd cf rjmp .-6 ; 0x1c80 <xmit_datablock+0x50>
} while (--wc);
1c86: 91 50 subi r25, 0x01 ; 1
1c88: 11 f0 breq .+4 ; 0x1c8e <xmit_datablock+0x5e>
static
BOOL xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
1c8a: 32 96 adiw r30, 0x02 ; 2
1c8c: f2 cf rjmp .-28 ; 0x1c72 <xmit_datablock+0x42>
wc = 0;
do { /* Xmit the 512 byte data block to MMC */
xmit_spi(*buff++);
xmit_spi(*buff++);
} while (--wc);
xmit_spi(0xFF); /* CRC (Dummy) */
1c8e: 8f ef ldi r24, 0xFF ; 255
1c90: 8e bd out 0x2e, r24 ; 46
1c92: 0d b4 in r0, 0x2d ; 45
1c94: 07 fe sbrs r0, 7
1c96: fd cf rjmp .-6 ; 0x1c92 <xmit_datablock+0x62>
xmit_spi(0xFF);
1c98: 8f ef ldi r24, 0xFF ; 255
1c9a: 8e bd out 0x2e, r24 ; 46
1c9c: 0d b4 in r0, 0x2d ; 45
1c9e: 07 fe sbrs r0, 7
1ca0: fd cf rjmp .-6 ; 0x1c9c <xmit_datablock+0x6c>
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1ca2: 8f ef ldi r24, 0xFF ; 255
1ca4: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1ca6: 0d b4 in r0, 0x2d ; 45
1ca8: 07 fe sbrs r0, 7
1caa: fd cf rjmp .-6 ; 0x1ca6 <xmit_datablock+0x76>
return SPDR;
1cac: 8e b5 in r24, 0x2e ; 46
1cae: 90 e0 ldi r25, 0x00 ; 0
1cb0: 8f 71 andi r24, 0x1F ; 31
1cb2: 85 30 cpi r24, 0x05 ; 5
1cb4: 09 f0 breq .+2 ; 0x1cb8 <xmit_datablock+0x88>
1cb6: 91 e0 ldi r25, 0x01 ; 1
1cb8: 81 e0 ldi r24, 0x01 ; 1
1cba: 98 27 eor r25, r24
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
return FALSE;
}
 
return TRUE;
}
1cbc: 89 2f mov r24, r25
1cbe: 08 95 ret
 
00001cc0 <send_cmd>:
static
BYTE send_cmd (
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
1cc0: 28 2f mov r18, r24
BYTE wait_ready (void)
{
BYTE res;
 
 
Timer2 = 50; /* Wait for ready in timeout of 500ms */
1cc2: 82 e3 ldi r24, 0x32 ; 50
1cc4: 80 93 16 01 sts 0x0116, r24
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1cc8: 8f ef ldi r24, 0xFF ; 255
1cca: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1ccc: 0d b4 in r0, 0x2d ; 45
1cce: 07 fe sbrs r0, 7
1cd0: fd cf rjmp .-6 ; 0x1ccc <send_cmd+0xc>
return SPDR;
1cd2: 8e b5 in r24, 0x2e ; 46
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1cd4: 9f ef ldi r25, 0xFF ; 255
1cd6: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1cd8: 0d b4 in r0, 0x2d ; 45
1cda: 07 fe sbrs r0, 7
1cdc: fd cf rjmp .-6 ; 0x1cd8 <send_cmd+0x18>
return SPDR;
1cde: 8e b5 in r24, 0x2e ; 46
 
Timer2 = 50; /* Wait for ready in timeout of 500ms */
rcvr_spi();
do
res = rcvr_spi();
while ((res != 0xFF) && Timer2);
1ce0: 8f 3f cpi r24, 0xFF ; 255
1ce2: 31 f0 breq .+12 ; 0x1cf0 <send_cmd+0x30>
1ce4: 80 91 16 01 lds r24, 0x0116
1ce8: 88 23 and r24, r24
1cea: a9 f7 brne .-22 ; 0x1cd6 <send_cmd+0x16>
1cec: 8f ef ldi r24, 0xFF ; 255
1cee: 08 95 ret
 
 
if (wait_ready() != 0xFF) return 0xFF;
 
/* Send command packet */
xmit_spi(cmd); /* Command */
1cf0: 2e bd out 0x2e, r18 ; 46
1cf2: 0d b4 in r0, 0x2d ; 45
1cf4: 07 fe sbrs r0, 7
1cf6: fd cf rjmp .-6 ; 0x1cf2 <send_cmd+0x32>
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
1cf8: 87 2f mov r24, r23
1cfa: 99 27 eor r25, r25
1cfc: aa 27 eor r26, r26
1cfe: bb 27 eor r27, r27
1d00: 8e bd out 0x2e, r24 ; 46
1d02: 0d b4 in r0, 0x2d ; 45
1d04: 07 fe sbrs r0, 7
1d06: fd cf rjmp .-6 ; 0x1d02 <send_cmd+0x42>
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
1d08: cb 01 movw r24, r22
1d0a: aa 27 eor r26, r26
1d0c: bb 27 eor r27, r27
1d0e: 8e bd out 0x2e, r24 ; 46
1d10: 0d b4 in r0, 0x2d ; 45
1d12: 07 fe sbrs r0, 7
1d14: fd cf rjmp .-6 ; 0x1d10 <send_cmd+0x50>
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
1d16: bb 27 eor r27, r27
1d18: a7 2f mov r26, r23
1d1a: 96 2f mov r25, r22
1d1c: 85 2f mov r24, r21
1d1e: 8e bd out 0x2e, r24 ; 46
1d20: 0d b4 in r0, 0x2d ; 45
1d22: 07 fe sbrs r0, 7
1d24: fd cf rjmp .-6 ; 0x1d20 <send_cmd+0x60>
xmit_spi((BYTE)arg); /* Argument[7..0] */
1d26: 4e bd out 0x2e, r20 ; 46
1d28: 0d b4 in r0, 0x2d ; 45
1d2a: 07 fe sbrs r0, 7
1d2c: fd cf rjmp .-6 ; 0x1d28 <send_cmd+0x68>
n = 0;
if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
1d2e: 20 34 cpi r18, 0x40 ; 64
1d30: 11 f4 brne .+4 ; 0x1d36 <send_cmd+0x76>
1d32: 85 e9 ldi r24, 0x95 ; 149
1d34: 05 c0 rjmp .+10 ; 0x1d40 <send_cmd+0x80>
if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
1d36: 28 34 cpi r18, 0x48 ; 72
1d38: 11 f4 brne .+4 ; 0x1d3e <send_cmd+0x7e>
1d3a: 87 e8 ldi r24, 0x87 ; 135
1d3c: 01 c0 rjmp .+2 ; 0x1d40 <send_cmd+0x80>
1d3e: 80 e0 ldi r24, 0x00 ; 0
xmit_spi(n);
1d40: 8e bd out 0x2e, r24 ; 46
1d42: 0d b4 in r0, 0x2d ; 45
1d44: 07 fe sbrs r0, 7
1d46: fd cf rjmp .-6 ; 0x1d42 <send_cmd+0x82>
 
/* Receive command response */
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
1d48: 2c 34 cpi r18, 0x4C ; 76
1d4a: 31 f4 brne .+12 ; 0x1d58 <send_cmd+0x98>
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1d4c: 8f ef ldi r24, 0xFF ; 255
1d4e: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1d50: 0d b4 in r0, 0x2d ; 45
1d52: 07 fe sbrs r0, 7
1d54: fd cf rjmp .-6 ; 0x1d50 <send_cmd+0x90>
return SPDR;
1d56: 8e b5 in r24, 0x2e ; 46
1d58: 9a e0 ldi r25, 0x0A ; 10
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1d5a: 2f ef ldi r18, 0xFF ; 255
1d5c: 2e bd out 0x2e, r18 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1d5e: 0d b4 in r0, 0x2d ; 45
1d60: 07 fe sbrs r0, 7
1d62: fd cf rjmp .-6 ; 0x1d5e <send_cmd+0x9e>
return SPDR;
1d64: 8e b5 in r24, 0x2e ; 46
/* Receive command response */
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
res = rcvr_spi();
while ((res & 0x80) && --n);
1d66: 87 ff sbrs r24, 7
1d68: 02 c0 rjmp .+4 ; 0x1d6e <send_cmd+0xae>
1d6a: 91 50 subi r25, 0x01 ; 1
1d6c: b9 f7 brne .-18 ; 0x1d5c <send_cmd+0x9c>
 
return res; /* Return with the response value */
}
1d6e: 08 95 ret
 
00001d70 <disk_initialize>:
/*-----------------------------------------------------------------------*/
 
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0) */
)
{
1d70: a4 e0 ldi r26, 0x04 ; 4
1d72: b0 e0 ldi r27, 0x00 ; 0
1d74: ee eb ldi r30, 0xBE ; 190
1d76: fe e0 ldi r31, 0x0E ; 14
1d78: 0c 94 d3 14 jmp 0x29a6 ; 0x29a6 <__prologue_saves__+0x18>
BYTE n, ty, ocr[4];
 
 
if (drv) return STA_NOINIT; /* Supports only single drive */
1d7c: 88 23 and r24, r24
1d7e: 11 f0 breq .+4 ; 0x1d84 <disk_initialize+0x14>
1d80: 81 e0 ldi r24, 0x01 ; 1
1d82: cf c0 rjmp .+414 ; 0x1f22 <disk_initialize+0x1b2>
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
1d84: 80 91 0b 01 lds r24, 0x010B
1d88: 81 fd sbrc r24, 1
1d8a: c9 c0 rjmp .+402 ; 0x1f1e <disk_initialize+0x1ae>
1d8c: 8a e0 ldi r24, 0x0A ; 10
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1d8e: 9f ef ldi r25, 0xFF ; 255
1d90: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1d92: 0d b4 in r0, 0x2d ; 45
1d94: 07 fe sbrs r0, 7
1d96: fd cf rjmp .-6 ; 0x1d92 <disk_initialize+0x22>
return SPDR;
1d98: 2e b5 in r18, 0x2e ; 46
 
 
if (drv) return STA_NOINIT; /* Supports only single drive */
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
 
for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */
1d9a: 81 50 subi r24, 0x01 ; 1
1d9c: c9 f7 brne .-14 ; 0x1d90 <disk_initialize+0x20>
 
SELECT(); /* CS = L */
1d9e: 2a 98 cbi 0x05, 2 ; 5
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
1da0: 40 e0 ldi r20, 0x00 ; 0
1da2: 50 e0 ldi r21, 0x00 ; 0
1da4: 60 e0 ldi r22, 0x00 ; 0
1da6: 70 e0 ldi r23, 0x00 ; 0
1da8: 80 e4 ldi r24, 0x40 ; 64
1daa: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1dae: 81 30 cpi r24, 0x01 ; 1
1db0: 09 f0 breq .+2 ; 0x1db4 <disk_initialize+0x44>
1db2: a0 c0 rjmp .+320 ; 0x1ef4 <disk_initialize+0x184>
Timer1 = 100; /* Initialization timeout of 1000 msec */
1db4: 84 e6 ldi r24, 0x64 ; 100
1db6: 80 93 15 01 sts 0x0115, r24
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
1dba: 4a ea ldi r20, 0xAA ; 170
1dbc: 51 e0 ldi r21, 0x01 ; 1
1dbe: 60 e0 ldi r22, 0x00 ; 0
1dc0: 70 e0 ldi r23, 0x00 ; 0
1dc2: 88 e4 ldi r24, 0x48 ; 72
1dc4: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1dc8: 81 30 cpi r24, 0x01 ; 1
1dca: 09 f0 breq .+2 ; 0x1dce <disk_initialize+0x5e>
1dcc: 54 c0 rjmp .+168 ; 0x1e76 <disk_initialize+0x106>
1dce: 7e 01 movw r14, r28
1dd0: 08 94 sec
1dd2: e1 1c adc r14, r1
1dd4: f1 1c adc r15, r1
1dd6: 87 01 movw r16, r14
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1dd8: 9f ef ldi r25, 0xFF ; 255
SELECT(); /* CS = L */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = 100; /* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
1dda: 9e 01 movw r18, r28
1ddc: 2b 5f subi r18, 0xFB ; 251
1dde: 3f 4f sbci r19, 0xFF ; 255
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1de0: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1de2: 0d b4 in r0, 0x2d ; 45
1de4: 07 fe sbrs r0, 7
1de6: fd cf rjmp .-6 ; 0x1de2 <disk_initialize+0x72>
return SPDR;
1de8: 8e b5 in r24, 0x2e ; 46
SELECT(); /* CS = L */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = 100; /* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
1dea: f8 01 movw r30, r16
1dec: 81 93 st Z+, r24
1dee: 8f 01 movw r16, r30
1df0: e2 17 cp r30, r18
1df2: f3 07 cpc r31, r19
1df4: a9 f7 brne .-22 ; 0x1de0 <disk_initialize+0x70>
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
1df6: 8b 81 ldd r24, Y+3 ; 0x03
1df8: 81 30 cpi r24, 0x01 ; 1
1dfa: 09 f0 breq .+2 ; 0x1dfe <disk_initialize+0x8e>
1dfc: 7b c0 rjmp .+246 ; 0x1ef4 <disk_initialize+0x184>
1dfe: 8c 81 ldd r24, Y+4 ; 0x04
1e00: 8a 3a cpi r24, 0xAA ; 170
1e02: 09 f0 breq .+2 ; 0x1e06 <disk_initialize+0x96>
1e04: 77 c0 rjmp .+238 ; 0x1ef4 <disk_initialize+0x184>
do {
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
1e06: 40 e0 ldi r20, 0x00 ; 0
1e08: 50 e0 ldi r21, 0x00 ; 0
1e0a: 60 e0 ldi r22, 0x00 ; 0
1e0c: 70 e0 ldi r23, 0x00 ; 0
1e0e: 87 e7 ldi r24, 0x77 ; 119
1e10: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1e14: 82 30 cpi r24, 0x02 ; 2
1e16: 48 f4 brcc .+18 ; 0x1e2a <disk_initialize+0xba>
1e18: 40 e0 ldi r20, 0x00 ; 0
1e1a: 50 e0 ldi r21, 0x00 ; 0
1e1c: 60 e0 ldi r22, 0x00 ; 0
1e1e: 70 e4 ldi r23, 0x40 ; 64
1e20: 89 e6 ldi r24, 0x69 ; 105
1e22: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1e26: 88 23 and r24, r24
1e28: 21 f0 breq .+8 ; 0x1e32 <disk_initialize+0xc2>
} while (Timer1);
1e2a: 80 91 15 01 lds r24, 0x0115
1e2e: 88 23 and r24, r24
1e30: 51 f7 brne .-44 ; 0x1e06 <disk_initialize+0x96>
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
1e32: 80 91 15 01 lds r24, 0x0115
1e36: 88 23 and r24, r24
1e38: 09 f4 brne .+2 ; 0x1e3c <disk_initialize+0xcc>
1e3a: 5c c0 rjmp .+184 ; 0x1ef4 <disk_initialize+0x184>
1e3c: 40 e0 ldi r20, 0x00 ; 0
1e3e: 50 e0 ldi r21, 0x00 ; 0
1e40: 60 e0 ldi r22, 0x00 ; 0
1e42: 70 e0 ldi r23, 0x00 ; 0
1e44: 8a e7 ldi r24, 0x7A ; 122
1e46: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1e4a: 88 23 and r24, r24
1e4c: 09 f0 breq .+2 ; 0x1e50 <disk_initialize+0xe0>
1e4e: 52 c0 rjmp .+164 ; 0x1ef4 <disk_initialize+0x184>
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1e50: 9f ef ldi r25, 0xFF ; 255
1e52: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1e54: 0d b4 in r0, 0x2d ; 45
1e56: 07 fe sbrs r0, 7
1e58: fd cf rjmp .-6 ; 0x1e54 <disk_initialize+0xe4>
return SPDR;
1e5a: 8e b5 in r24, 0x2e ; 46
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
do {
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
} while (Timer1);
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
1e5c: f7 01 movw r30, r14
1e5e: 81 93 st Z+, r24
1e60: 7f 01 movw r14, r30
1e62: e0 17 cp r30, r16
1e64: f1 07 cpc r31, r17
1e66: a9 f7 brne .-22 ; 0x1e52 <disk_initialize+0xe2>
ty = (ocr[0] & 0x40) ? 6 : 2;
1e68: 89 81 ldd r24, Y+1 ; 0x01
1e6a: 86 fd sbrc r24, 6
1e6c: 02 c0 rjmp .+4 ; 0x1e72 <disk_initialize+0x102>
1e6e: 12 e0 ldi r17, 0x02 ; 2
1e70: 42 c0 rjmp .+132 ; 0x1ef6 <disk_initialize+0x186>
1e72: 16 e0 ldi r17, 0x06 ; 6
1e74: 40 c0 rjmp .+128 ; 0x1ef6 <disk_initialize+0x186>
}
}
} else { /* SDC Ver1 or MMC */
ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
1e76: 40 e0 ldi r20, 0x00 ; 0
1e78: 50 e0 ldi r21, 0x00 ; 0
1e7a: 60 e0 ldi r22, 0x00 ; 0
1e7c: 70 e0 ldi r23, 0x00 ; 0
1e7e: 87 e7 ldi r24, 0x77 ; 119
1e80: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1e84: 82 30 cpi r24, 0x02 ; 2
1e86: 58 f4 brcc .+22 ; 0x1e9e <disk_initialize+0x12e>
1e88: 40 e0 ldi r20, 0x00 ; 0
1e8a: 50 e0 ldi r21, 0x00 ; 0
1e8c: 60 e0 ldi r22, 0x00 ; 0
1e8e: 70 e0 ldi r23, 0x00 ; 0
1e90: 89 e6 ldi r24, 0x69 ; 105
1e92: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1e96: 82 30 cpi r24, 0x02 ; 2
1e98: 10 f4 brcc .+4 ; 0x1e9e <disk_initialize+0x12e>
1e9a: 12 e0 ldi r17, 0x02 ; 2
1e9c: 01 c0 rjmp .+2 ; 0x1ea0 <disk_initialize+0x130>
1e9e: 11 e0 ldi r17, 0x01 ; 1
do {
if (ty == 2) {
1ea0: 12 30 cpi r17, 0x02 ; 2
1ea2: 79 f4 brne .+30 ; 0x1ec2 <disk_initialize+0x152>
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
1ea4: 40 e0 ldi r20, 0x00 ; 0
1ea6: 50 e0 ldi r21, 0x00 ; 0
1ea8: 60 e0 ldi r22, 0x00 ; 0
1eaa: 70 e0 ldi r23, 0x00 ; 0
1eac: 87 e7 ldi r24, 0x77 ; 119
1eae: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1eb2: 82 30 cpi r24, 0x02 ; 2
1eb4: 78 f4 brcc .+30 ; 0x1ed4 <disk_initialize+0x164>
1eb6: 40 e0 ldi r20, 0x00 ; 0
1eb8: 50 e0 ldi r21, 0x00 ; 0
1eba: 60 e0 ldi r22, 0x00 ; 0
1ebc: 70 e0 ldi r23, 0x00 ; 0
1ebe: 89 e6 ldi r24, 0x69 ; 105
1ec0: 05 c0 rjmp .+10 ; 0x1ecc <disk_initialize+0x15c>
} else {
if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
1ec2: 40 e0 ldi r20, 0x00 ; 0
1ec4: 50 e0 ldi r21, 0x00 ; 0
1ec6: 60 e0 ldi r22, 0x00 ; 0
1ec8: 70 e0 ldi r23, 0x00 ; 0
1eca: 81 e4 ldi r24, 0x41 ; 65
1ecc: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1ed0: 88 23 and r24, r24
1ed2: 21 f0 breq .+8 ; 0x1edc <disk_initialize+0x16c>
}
} while (Timer1);
1ed4: 80 91 15 01 lds r24, 0x0115
1ed8: 88 23 and r24, r24
1eda: 11 f7 brne .-60 ; 0x1ea0 <disk_initialize+0x130>
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
1edc: 80 91 15 01 lds r24, 0x0115
1ee0: 88 23 and r24, r24
1ee2: 41 f0 breq .+16 ; 0x1ef4 <disk_initialize+0x184>
1ee4: 40 e0 ldi r20, 0x00 ; 0
1ee6: 52 e0 ldi r21, 0x02 ; 2
1ee8: 60 e0 ldi r22, 0x00 ; 0
1eea: 70 e0 ldi r23, 0x00 ; 0
1eec: 80 e5 ldi r24, 0x50 ; 80
1eee: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1ef2: 81 11 cpse r24, r1
1ef4: 10 e0 ldi r17, 0x00 ; 0
ty = 0;
}
}
CardType = ty;
1ef6: 10 93 17 01 sts 0x0117, r17
DESELECT(); /* CS = H */
1efa: 2a 9a sbi 0x05, 2 ; 5
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1efc: 8f ef ldi r24, 0xFF ; 255
1efe: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1f00: 0d b4 in r0, 0x2d ; 45
1f02: 07 fe sbrs r0, 7
1f04: fd cf rjmp .-6 ; 0x1f00 <disk_initialize+0x190>
return SPDR;
1f06: 8e b5 in r24, 0x2e ; 46
}
CardType = ty;
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
if (ty) { /* Initialization succeded */
1f08: 11 23 and r17, r17
1f0a: 21 f0 breq .+8 ; 0x1f14 <disk_initialize+0x1a4>
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
1f0c: 80 91 0b 01 lds r24, 0x010B
1f10: 8e 7f andi r24, 0xFE ; 254
1f12: 03 c0 rjmp .+6 ; 0x1f1a <disk_initialize+0x1aa>
} else { /* Initialization failed */
Stat |= STA_NOINIT; /* Set STA_NOINIT */
1f14: 80 91 0b 01 lds r24, 0x010B
1f18: 81 60 ori r24, 0x01 ; 1
1f1a: 80 93 0b 01 sts 0x010B, r24
}
 
return Stat;
1f1e: 80 91 0b 01 lds r24, 0x010B
}
1f22: 24 96 adiw r28, 0x04 ; 4
1f24: e6 e0 ldi r30, 0x06 ; 6
1f26: 0c 94 ef 14 jmp 0x29de ; 0x29de <__epilogue_restores__+0x18>
 
00001f2a <disk_status>:
/*-----------------------------------------------------------------------*/
 
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0) */
)
{
1f2a: 88 23 and r24, r24
1f2c: 11 f0 breq .+4 ; 0x1f32 <disk_status+0x8>
1f2e: 81 e0 ldi r24, 0x01 ; 1
1f30: 08 95 ret
if (drv) return STA_NOINIT; /* Supports only single drive */
return Stat;
1f32: 80 91 0b 01 lds r24, 0x010B
}
1f36: 08 95 ret
 
00001f38 <disk_read>:
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
1f38: 0f 93 push r16
1f3a: cf 93 push r28
1f3c: df 93 push r29
1f3e: eb 01 movw r28, r22
if (drv || !count) return RES_PARERR;
1f40: 88 23 and r24, r24
1f42: 09 f0 breq .+2 ; 0x1f46 <disk_read+0xe>
1f44: 51 c0 rjmp .+162 ; 0x1fe8 <disk_read+0xb0>
1f46: 00 23 and r16, r16
1f48: 09 f4 brne .+2 ; 0x1f4c <disk_read+0x14>
1f4a: 4e c0 rjmp .+156 ; 0x1fe8 <disk_read+0xb0>
if (Stat & STA_NOINIT) return RES_NOTRDY;
1f4c: 80 91 0b 01 lds r24, 0x010B
1f50: 80 ff sbrs r24, 0
1f52: 03 c0 rjmp .+6 ; 0x1f5a <disk_read+0x22>
1f54: 23 e0 ldi r18, 0x03 ; 3
1f56: 30 e0 ldi r19, 0x00 ; 0
1f58: 49 c0 rjmp .+146 ; 0x1fec <disk_read+0xb4>
 
if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
1f5a: 80 91 17 01 lds r24, 0x0117
1f5e: 82 fd sbrc r24, 2
1f60: 07 c0 rjmp .+14 ; 0x1f70 <disk_read+0x38>
1f62: 69 e0 ldi r22, 0x09 ; 9
1f64: 22 0f add r18, r18
1f66: 33 1f adc r19, r19
1f68: 44 1f adc r20, r20
1f6a: 55 1f adc r21, r21
1f6c: 6a 95 dec r22
1f6e: d1 f7 brne .-12 ; 0x1f64 <disk_read+0x2c>
 
SELECT(); /* CS = L */
1f70: 2a 98 cbi 0x05, 2 ; 5
 
if (count == 1) { /* Single block read */
1f72: 01 30 cpi r16, 0x01 ; 1
1f74: 89 f4 brne .+34 ; 0x1f98 <disk_read+0x60>
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
1f76: ba 01 movw r22, r20
1f78: a9 01 movw r20, r18
1f7a: 81 e5 ldi r24, 0x51 ; 81
1f7c: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1f80: 88 23 and r24, r24
1f82: 21 f5 brne .+72 ; 0x1fcc <disk_read+0x94>
1f84: 60 e0 ldi r22, 0x00 ; 0
1f86: 72 e0 ldi r23, 0x02 ; 2
1f88: ce 01 movw r24, r28
1f8a: 0e 94 e3 0d call 0x1bc6 ; 0x1bc6 <rcvr_datablock>
1f8e: 00 e0 ldi r16, 0x00 ; 0
1f90: 88 23 and r24, r24
1f92: e1 f4 brne .+56 ; 0x1fcc <disk_read+0x94>
1f94: 01 e0 ldi r16, 0x01 ; 1
1f96: 1a c0 rjmp .+52 ; 0x1fcc <disk_read+0x94>
&& rcvr_datablock(buff, 512))
count = 0;
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
1f98: ba 01 movw r22, r20
1f9a: a9 01 movw r20, r18
1f9c: 82 e5 ldi r24, 0x52 ; 82
1f9e: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
1fa2: 88 23 and r24, r24
1fa4: 99 f4 brne .+38 ; 0x1fcc <disk_read+0x94>
do {
if (!rcvr_datablock(buff, 512)) break;
1fa6: 60 e0 ldi r22, 0x00 ; 0
1fa8: 72 e0 ldi r23, 0x02 ; 2
1faa: ce 01 movw r24, r28
1fac: 0e 94 e3 0d call 0x1bc6 ; 0x1bc6 <rcvr_datablock>
1fb0: 88 23 and r24, r24
1fb2: 29 f0 breq .+10 ; 0x1fbe <disk_read+0x86>
buff += 512;
} while (--count);
1fb4: 01 50 subi r16, 0x01 ; 1
1fb6: 19 f0 breq .+6 ; 0x1fbe <disk_read+0x86>
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
1fb8: c0 50 subi r28, 0x00 ; 0
1fba: de 4f sbci r29, 0xFE ; 254
1fbc: f4 cf rjmp .-24 ; 0x1fa6 <disk_read+0x6e>
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
1fbe: 40 e0 ldi r20, 0x00 ; 0
1fc0: 50 e0 ldi r21, 0x00 ; 0
1fc2: 60 e0 ldi r22, 0x00 ; 0
1fc4: 70 e0 ldi r23, 0x00 ; 0
1fc6: 8c e4 ldi r24, 0x4C ; 76
1fc8: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
}
}
 
DESELECT(); /* CS = H */
1fcc: 2a 9a sbi 0x05, 2 ; 5
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
1fce: 8f ef ldi r24, 0xFF ; 255
1fd0: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
1fd2: 0d b4 in r0, 0x2d ; 45
1fd4: 07 fe sbrs r0, 7
1fd6: fd cf rjmp .-6 ; 0x1fd2 <disk_read+0x9a>
return SPDR;
1fd8: 8e b5 in r24, 0x2e ; 46
}
 
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
return count ? RES_ERROR : RES_OK;
1fda: 20 e0 ldi r18, 0x00 ; 0
1fdc: 30 e0 ldi r19, 0x00 ; 0
1fde: 00 23 and r16, r16
1fe0: 29 f0 breq .+10 ; 0x1fec <disk_read+0xb4>
1fe2: 21 e0 ldi r18, 0x01 ; 1
1fe4: 30 e0 ldi r19, 0x00 ; 0
1fe6: 02 c0 rjmp .+4 ; 0x1fec <disk_read+0xb4>
1fe8: 24 e0 ldi r18, 0x04 ; 4
1fea: 30 e0 ldi r19, 0x00 ; 0
}
1fec: c9 01 movw r24, r18
1fee: df 91 pop r29
1ff0: cf 91 pop r28
1ff2: 0f 91 pop r16
1ff4: 08 95 ret
 
00001ff6 <disk_write>:
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
1ff6: cf 92 push r12
1ff8: df 92 push r13
1ffa: ef 92 push r14
1ffc: ff 92 push r15
1ffe: 0f 93 push r16
2000: cf 93 push r28
2002: df 93 push r29
2004: eb 01 movw r28, r22
2006: 69 01 movw r12, r18
2008: 7a 01 movw r14, r20
if (drv || !count) return RES_PARERR;
200a: 88 23 and r24, r24
200c: 09 f0 breq .+2 ; 0x2010 <disk_write+0x1a>
200e: 64 c0 rjmp .+200 ; 0x20d8 <disk_write+0xe2>
2010: 00 23 and r16, r16
2012: 09 f4 brne .+2 ; 0x2016 <disk_write+0x20>
2014: 61 c0 rjmp .+194 ; 0x20d8 <disk_write+0xe2>
if (Stat & STA_NOINIT) return RES_NOTRDY;
2016: 80 91 0b 01 lds r24, 0x010B
201a: 80 ff sbrs r24, 0
201c: 03 c0 rjmp .+6 ; 0x2024 <disk_write+0x2e>
201e: 23 e0 ldi r18, 0x03 ; 3
2020: 30 e0 ldi r19, 0x00 ; 0
2022: 5c c0 rjmp .+184 ; 0x20dc <disk_write+0xe6>
if (Stat & STA_PROTECT) return RES_WRPRT;
2024: 80 91 0b 01 lds r24, 0x010B
2028: 82 ff sbrs r24, 2
202a: 03 c0 rjmp .+6 ; 0x2032 <disk_write+0x3c>
202c: 22 e0 ldi r18, 0x02 ; 2
202e: 30 e0 ldi r19, 0x00 ; 0
2030: 55 c0 rjmp .+170 ; 0x20dc <disk_write+0xe6>
 
if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
2032: 80 91 17 01 lds r24, 0x0117
2036: 82 fd sbrc r24, 2
2038: 07 c0 rjmp .+14 ; 0x2048 <disk_write+0x52>
203a: 79 e0 ldi r23, 0x09 ; 9
203c: cc 0c add r12, r12
203e: dd 1c adc r13, r13
2040: ee 1c adc r14, r14
2042: ff 1c adc r15, r15
2044: 7a 95 dec r23
2046: d1 f7 brne .-12 ; 0x203c <disk_write+0x46>
 
SELECT(); /* CS = L */
2048: 2a 98 cbi 0x05, 2 ; 5
 
if (count == 1) { /* Single block write */
204a: 01 30 cpi r16, 0x01 ; 1
204c: 69 f4 brne .+26 ; 0x2068 <disk_write+0x72>
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
204e: b7 01 movw r22, r14
2050: a6 01 movw r20, r12
2052: 88 e5 ldi r24, 0x58 ; 88
2054: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
2058: 88 23 and r24, r24
205a: 81 f5 brne .+96 ; 0x20bc <disk_write+0xc6>
205c: 6e ef ldi r22, 0xFE ; 254
205e: ce 01 movw r24, r28
2060: 0e 94 18 0e call 0x1c30 ; 0x1c30 <xmit_datablock>
2064: 00 e0 ldi r16, 0x00 ; 0
2066: 27 c0 rjmp .+78 ; 0x20b6 <disk_write+0xc0>
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple block write */
if (CardType & 2) {
2068: 81 ff sbrs r24, 1
206a: 0e c0 rjmp .+28 ; 0x2088 <disk_write+0x92>
send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */
206c: 40 e0 ldi r20, 0x00 ; 0
206e: 50 e0 ldi r21, 0x00 ; 0
2070: 60 e0 ldi r22, 0x00 ; 0
2072: 70 e0 ldi r23, 0x00 ; 0
2074: 87 e7 ldi r24, 0x77 ; 119
2076: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
207a: 40 2f mov r20, r16
207c: 50 e0 ldi r21, 0x00 ; 0
207e: 60 e0 ldi r22, 0x00 ; 0
2080: 70 e0 ldi r23, 0x00 ; 0
2082: 87 e5 ldi r24, 0x57 ; 87
2084: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
}
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
2088: b7 01 movw r22, r14
208a: a6 01 movw r20, r12
208c: 89 e5 ldi r24, 0x59 ; 89
208e: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
2092: 88 23 and r24, r24
2094: 99 f4 brne .+38 ; 0x20bc <disk_write+0xc6>
do {
if (!xmit_datablock(buff, 0xFC)) break;
2096: 6c ef ldi r22, 0xFC ; 252
2098: ce 01 movw r24, r28
209a: 0e 94 18 0e call 0x1c30 ; 0x1c30 <xmit_datablock>
209e: 88 23 and r24, r24
20a0: 29 f0 breq .+10 ; 0x20ac <disk_write+0xb6>
buff += 512;
} while (--count);
20a2: 01 50 subi r16, 0x01 ; 1
20a4: 19 f0 breq .+6 ; 0x20ac <disk_write+0xb6>
send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */
}
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
20a6: c0 50 subi r28, 0x00 ; 0
20a8: de 4f sbci r29, 0xFE ; 254
20aa: f5 cf rjmp .-22 ; 0x2096 <disk_write+0xa0>
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
20ac: 6d ef ldi r22, 0xFD ; 253
20ae: 80 e0 ldi r24, 0x00 ; 0
20b0: 90 e0 ldi r25, 0x00 ; 0
20b2: 0e 94 18 0e call 0x1c30 ; 0x1c30 <xmit_datablock>
20b6: 88 23 and r24, r24
20b8: 09 f4 brne .+2 ; 0x20bc <disk_write+0xc6>
20ba: 01 e0 ldi r16, 0x01 ; 1
count = 1;
}
}
 
DESELECT(); /* CS = H */
20bc: 2a 9a sbi 0x05, 2 ; 5
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
20be: 8f ef ldi r24, 0xFF ; 255
20c0: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
20c2: 0d b4 in r0, 0x2d ; 45
20c4: 07 fe sbrs r0, 7
20c6: fd cf rjmp .-6 ; 0x20c2 <disk_write+0xcc>
return SPDR;
20c8: 8e b5 in r24, 0x2e ; 46
}
 
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
return count ? RES_ERROR : RES_OK;
20ca: 20 e0 ldi r18, 0x00 ; 0
20cc: 30 e0 ldi r19, 0x00 ; 0
20ce: 00 23 and r16, r16
20d0: 29 f0 breq .+10 ; 0x20dc <disk_write+0xe6>
20d2: 21 e0 ldi r18, 0x01 ; 1
20d4: 30 e0 ldi r19, 0x00 ; 0
20d6: 02 c0 rjmp .+4 ; 0x20dc <disk_write+0xe6>
20d8: 24 e0 ldi r18, 0x04 ; 4
20da: 30 e0 ldi r19, 0x00 ; 0
}
20dc: c9 01 movw r24, r18
20de: df 91 pop r29
20e0: cf 91 pop r28
20e2: 0f 91 pop r16
20e4: ff 90 pop r15
20e6: ef 90 pop r14
20e8: df 90 pop r13
20ea: cf 90 pop r12
20ec: 08 95 ret
 
000020ee <disk_ioctl>:
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive data block */
)
{
20ee: a0 e1 ldi r26, 0x10 ; 16
20f0: b0 e0 ldi r27, 0x00 ; 0
20f2: ed e7 ldi r30, 0x7D ; 125
20f4: f0 e1 ldi r31, 0x10 ; 16
20f6: 0c 94 d5 14 jmp 0x29aa ; 0x29aa <__prologue_saves__+0x1c>
20fa: 8a 01 movw r16, r20
DRESULT res;
BYTE n, csd[16], *ptr = buff;
WORD csize;
 
 
if (drv) return RES_PARERR;
20fc: 88 23 and r24, r24
20fe: 19 f0 breq .+6 ; 0x2106 <disk_ioctl+0x18>
2100: 24 e0 ldi r18, 0x04 ; 4
2102: 30 e0 ldi r19, 0x00 ; 0
2104: e7 c0 rjmp .+462 ; 0x22d4 <disk_ioctl+0x1e6>
 
SELECT(); /* CS = L */
2106: 2a 98 cbi 0x05, 2 ; 5
 
res = RES_ERROR;
switch (ctrl) {
2108: 63 30 cpi r22, 0x03 ; 3
210a: 09 f4 brne .+2 ; 0x210e <disk_ioctl+0x20>
210c: 7f c0 rjmp .+254 ; 0x220c <disk_ioctl+0x11e>
210e: 64 30 cpi r22, 0x04 ; 4
2110: 28 f4 brcc .+10 ; 0x211c <disk_ioctl+0x2e>
2112: 61 30 cpi r22, 0x01 ; 1
2114: 79 f0 breq .+30 ; 0x2134 <disk_ioctl+0x46>
2116: 62 30 cpi r22, 0x02 ; 2
2118: 51 f4 brne .+20 ; 0x212e <disk_ioctl+0x40>
211a: 72 c0 rjmp .+228 ; 0x2200 <disk_ioctl+0x112>
211c: 6b 30 cpi r22, 0x0B ; 11
211e: 09 f4 brne .+2 ; 0x2122 <disk_ioctl+0x34>
2120: 96 c0 rjmp .+300 ; 0x224e <disk_ioctl+0x160>
2122: 6c 30 cpi r22, 0x0C ; 12
2124: 09 f4 brne .+2 ; 0x2128 <disk_ioctl+0x3a>
2126: aa c0 rjmp .+340 ; 0x227c <disk_ioctl+0x18e>
2128: 6a 30 cpi r22, 0x0A ; 10
212a: 09 f4 brne .+2 ; 0x212e <disk_ioctl+0x40>
212c: 86 c0 rjmp .+268 ; 0x223a <disk_ioctl+0x14c>
212e: 24 e0 ldi r18, 0x04 ; 4
2130: 30 e0 ldi r19, 0x00 ; 0
2132: c6 c0 rjmp .+396 ; 0x22c0 <disk_ioctl+0x1d2>
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
2134: 40 e0 ldi r20, 0x00 ; 0
2136: 50 e0 ldi r21, 0x00 ; 0
2138: 60 e0 ldi r22, 0x00 ; 0
213a: 70 e0 ldi r23, 0x00 ; 0
213c: 89 e4 ldi r24, 0x49 ; 73
213e: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
2142: 88 23 and r24, r24
2144: 09 f0 breq .+2 ; 0x2148 <disk_ioctl+0x5a>
2146: b7 c0 rjmp .+366 ; 0x22b6 <disk_ioctl+0x1c8>
2148: 60 e1 ldi r22, 0x10 ; 16
214a: 70 e0 ldi r23, 0x00 ; 0
214c: ce 01 movw r24, r28
214e: 01 96 adiw r24, 0x01 ; 1
2150: 0e 94 e3 0d call 0x1bc6 ; 0x1bc6 <rcvr_datablock>
2154: 88 23 and r24, r24
2156: 09 f4 brne .+2 ; 0x215a <disk_ioctl+0x6c>
2158: ae c0 rjmp .+348 ; 0x22b6 <disk_ioctl+0x1c8>
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
215a: 89 81 ldd r24, Y+1 ; 0x01
215c: 82 95 swap r24
215e: 86 95 lsr r24
2160: 86 95 lsr r24
2162: 83 70 andi r24, 0x03 ; 3
2164: 7a 85 ldd r23, Y+10 ; 0x0a
2166: 49 85 ldd r20, Y+9 ; 0x09
2168: 81 30 cpi r24, 0x01 ; 1
216a: b1 f4 brne .+44 ; 0x2198 <disk_ioctl+0xaa>
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
*(DWORD*)buff = (DWORD)csize << 10;
216c: 87 2f mov r24, r23
216e: 90 e0 ldi r25, 0x00 ; 0
2170: 01 96 adiw r24, 0x01 ; 1
2172: 34 2f mov r19, r20
2174: 20 e0 ldi r18, 0x00 ; 0
2176: 82 0f add r24, r18
2178: 93 1f adc r25, r19
217a: a0 e0 ldi r26, 0x00 ; 0
217c: b0 e0 ldi r27, 0x00 ; 0
217e: 2a e0 ldi r18, 0x0A ; 10
2180: 88 0f add r24, r24
2182: 99 1f adc r25, r25
2184: aa 1f adc r26, r26
2186: bb 1f adc r27, r27
2188: 2a 95 dec r18
218a: d1 f7 brne .-12 ; 0x2180 <disk_ioctl+0x92>
218c: f8 01 movw r30, r16
218e: 80 83 st Z, r24
2190: 91 83 std Z+1, r25 ; 0x01
2192: a2 83 std Z+2, r26 ; 0x02
2194: b3 83 std Z+3, r27 ; 0x03
2196: 92 c0 rjmp .+292 ; 0x22bc <disk_ioctl+0x1ce>
} else { /* MMC or SDC ver 1.XX */
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = (DWORD)csize << (n - 9);
2198: 42 95 swap r20
219a: 46 95 lsr r20
219c: 46 95 lsr r20
219e: 43 70 andi r20, 0x03 ; 3
21a0: 28 85 ldd r18, Y+8 ; 0x08
21a2: 30 e0 ldi r19, 0x00 ; 0
21a4: 22 0f add r18, r18
21a6: 33 1f adc r19, r19
21a8: 22 0f add r18, r18
21aa: 33 1f adc r19, r19
21ac: 24 0f add r18, r20
21ae: 31 1d adc r19, r1
21b0: 2f 5f subi r18, 0xFF ; 255
21b2: 3f 4f sbci r19, 0xFF ; 255
21b4: 8f 81 ldd r24, Y+7 ; 0x07
21b6: 90 e0 ldi r25, 0x00 ; 0
21b8: 83 70 andi r24, 0x03 ; 3
21ba: 90 70 andi r25, 0x00 ; 0
21bc: 98 2f mov r25, r24
21be: 88 27 eor r24, r24
21c0: 99 0f add r25, r25
21c2: 99 0f add r25, r25
21c4: 28 0f add r18, r24
21c6: 39 1f adc r19, r25
21c8: 40 e0 ldi r20, 0x00 ; 0
21ca: 50 e0 ldi r21, 0x00 ; 0
21cc: 8e 81 ldd r24, Y+6 ; 0x06
21ce: 8f 70 andi r24, 0x0F ; 15
21d0: 6b 85 ldd r22, Y+11 ; 0x0b
21d2: 66 1f adc r22, r22
21d4: 66 27 eor r22, r22
21d6: 66 1f adc r22, r22
21d8: 86 0f add r24, r22
21da: 8e 5f subi r24, 0xFE ; 254
21dc: 73 70 andi r23, 0x03 ; 3
21de: 77 0f add r23, r23
21e0: 87 0f add r24, r23
21e2: 90 e0 ldi r25, 0x00 ; 0
21e4: 09 97 sbiw r24, 0x09 ; 9
21e6: 04 c0 rjmp .+8 ; 0x21f0 <disk_ioctl+0x102>
21e8: 22 0f add r18, r18
21ea: 33 1f adc r19, r19
21ec: 44 1f adc r20, r20
21ee: 55 1f adc r21, r21
21f0: 8a 95 dec r24
21f2: d2 f7 brpl .-12 ; 0x21e8 <disk_ioctl+0xfa>
21f4: f8 01 movw r30, r16
21f6: 20 83 st Z, r18
21f8: 31 83 std Z+1, r19 ; 0x01
21fa: 42 83 std Z+2, r20 ; 0x02
21fc: 53 83 std Z+3, r21 ; 0x03
21fe: 5e c0 rjmp .+188 ; 0x22bc <disk_ioctl+0x1ce>
res = RES_OK;
}
break;
 
case GET_SECTOR_SIZE : /* Get sectors on the disk (WORD) */
*(WORD*)buff = 512;
2200: 80 e0 ldi r24, 0x00 ; 0
2202: 92 e0 ldi r25, 0x02 ; 2
2204: fa 01 movw r30, r20
2206: 91 83 std Z+1, r25 ; 0x01
2208: 80 83 st Z, r24
220a: 58 c0 rjmp .+176 ; 0x22bc <disk_ioctl+0x1ce>
BYTE wait_ready (void)
{
BYTE res;
 
 
Timer2 = 50; /* Wait for ready in timeout of 500ms */
220c: 82 e3 ldi r24, 0x32 ; 50
220e: 80 93 16 01 sts 0x0116, r24
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
2212: 8f ef ldi r24, 0xFF ; 255
2214: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
2216: 0d b4 in r0, 0x2d ; 45
2218: 07 fe sbrs r0, 7
221a: fd cf rjmp .-6 ; 0x2216 <disk_ioctl+0x128>
return SPDR;
221c: 8e b5 in r24, 0x2e ; 46
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
221e: 9f ef ldi r25, 0xFF ; 255
2220: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
2222: 0d b4 in r0, 0x2d ; 45
2224: 07 fe sbrs r0, 7
2226: fd cf rjmp .-6 ; 0x2222 <disk_ioctl+0x134>
return SPDR;
2228: 8e b5 in r24, 0x2e ; 46
 
Timer2 = 50; /* Wait for ready in timeout of 500ms */
rcvr_spi();
do
res = rcvr_spi();
while ((res != 0xFF) && Timer2);
222a: 8f 3f cpi r24, 0xFF ; 255
222c: 09 f4 brne .+2 ; 0x2230 <disk_ioctl+0x142>
222e: 46 c0 rjmp .+140 ; 0x22bc <disk_ioctl+0x1ce>
2230: 80 91 16 01 lds r24, 0x0116
2234: 88 23 and r24, r24
2236: a1 f7 brne .-24 ; 0x2220 <disk_ioctl+0x132>
2238: 3e c0 rjmp .+124 ; 0x22b6 <disk_ioctl+0x1c8>
if (wait_ready() == 0xFF)
res = RES_OK;
break;
 
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
223a: 80 91 0b 01 lds r24, 0x010B
223e: 80 fd sbrc r24, 0
2240: 47 c0 rjmp .+142 ; 0x22d0 <disk_ioctl+0x1e2>
if ((send_cmd(CMD9, 0) == 0) /* READ_CSD */
2242: 40 e0 ldi r20, 0x00 ; 0
2244: 50 e0 ldi r21, 0x00 ; 0
2246: 60 e0 ldi r22, 0x00 ; 0
2248: 70 e0 ldi r23, 0x00 ; 0
224a: 89 e4 ldi r24, 0x49 ; 73
224c: 09 c0 rjmp .+18 ; 0x2260 <disk_ioctl+0x172>
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
 
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
224e: 80 91 0b 01 lds r24, 0x010B
2252: 80 fd sbrc r24, 0
2254: 3d c0 rjmp .+122 ; 0x22d0 <disk_ioctl+0x1e2>
if ((send_cmd(CMD10, 0) == 0) /* READ_CID */
2256: 40 e0 ldi r20, 0x00 ; 0
2258: 50 e0 ldi r21, 0x00 ; 0
225a: 60 e0 ldi r22, 0x00 ; 0
225c: 70 e0 ldi r23, 0x00 ; 0
225e: 8a e4 ldi r24, 0x4A ; 74
2260: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
2264: 88 23 and r24, r24
2266: 39 f5 brne .+78 ; 0x22b6 <disk_ioctl+0x1c8>
2268: 60 e1 ldi r22, 0x10 ; 16
226a: 70 e0 ldi r23, 0x00 ; 0
226c: c8 01 movw r24, r16
226e: 0e 94 e3 0d call 0x1bc6 ; 0x1bc6 <rcvr_datablock>
2272: 20 e0 ldi r18, 0x00 ; 0
2274: 30 e0 ldi r19, 0x00 ; 0
2276: 88 23 and r24, r24
2278: 19 f5 brne .+70 ; 0x22c0 <disk_ioctl+0x1d2>
227a: 1d c0 rjmp .+58 ; 0x22b6 <disk_ioctl+0x1c8>
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
 
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
227c: 80 91 0b 01 lds r24, 0x010B
2280: 80 fd sbrc r24, 0
2282: 26 c0 rjmp .+76 ; 0x22d0 <disk_ioctl+0x1e2>
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
2284: 40 e0 ldi r20, 0x00 ; 0
2286: 50 e0 ldi r21, 0x00 ; 0
2288: 60 e0 ldi r22, 0x00 ; 0
228a: 70 e0 ldi r23, 0x00 ; 0
228c: 8a e7 ldi r24, 0x7A ; 122
228e: 0e 94 60 0e call 0x1cc0 ; 0x1cc0 <send_cmd>
2292: 88 23 and r24, r24
2294: 81 f4 brne .+32 ; 0x22b6 <disk_ioctl+0x1c8>
2296: f8 01 movw r30, r16
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
2298: 9f ef ldi r25, 0xFF ; 255
break;
 
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 0; n < 4; n++)
229a: 98 01 movw r18, r16
229c: 2d 5f subi r18, 0xFD ; 253
229e: 3f 4f sbci r19, 0xFF ; 255
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
22a0: 9e bd out 0x2e, r25 ; 46
loop_until_bit_is_set(SPSR, SPIF);
22a2: 0d b4 in r0, 0x2d ; 45
22a4: 07 fe sbrs r0, 7
22a6: fd cf rjmp .-6 ; 0x22a2 <disk_ioctl+0x1b4>
return SPDR;
22a8: 8e b5 in r24, 0x2e ; 46
 
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 0; n < 4; n++)
*ptr++ = rcvr_spi();
22aa: 80 83 st Z, r24
break;
 
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 0; n < 4; n++)
22ac: e2 17 cp r30, r18
22ae: f3 07 cpc r31, r19
22b0: 29 f0 breq .+10 ; 0x22bc <disk_ioctl+0x1ce>
*ptr++ = rcvr_spi();
22b2: 31 96 adiw r30, 0x01 ; 1
22b4: f5 cf rjmp .-22 ; 0x22a0 <disk_ioctl+0x1b2>
22b6: 21 e0 ldi r18, 0x01 ; 1
22b8: 30 e0 ldi r19, 0x00 ; 0
22ba: 02 c0 rjmp .+4 ; 0x22c0 <disk_ioctl+0x1d2>
22bc: 20 e0 ldi r18, 0x00 ; 0
22be: 30 e0 ldi r19, 0x00 ; 0
 
default:
res = RES_PARERR;
}
 
DESELECT(); /* CS = H */
22c0: 2a 9a sbi 0x05, 2 ; 5
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
22c2: 8f ef ldi r24, 0xFF ; 255
22c4: 8e bd out 0x2e, r24 ; 46
loop_until_bit_is_set(SPSR, SPIF);
22c6: 0d b4 in r0, 0x2d ; 45
22c8: 07 fe sbrs r0, 7
22ca: fd cf rjmp .-6 ; 0x22c6 <disk_ioctl+0x1d8>
return SPDR;
22cc: 8e b5 in r24, 0x2e ; 46
22ce: 02 c0 rjmp .+4 ; 0x22d4 <disk_ioctl+0x1e6>
}
 
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
return res;
22d0: 23 e0 ldi r18, 0x03 ; 3
22d2: 30 e0 ldi r19, 0x00 ; 0
}
22d4: c9 01 movw r24, r18
22d6: 60 96 adiw r28, 0x10 ; 16
22d8: e4 e0 ldi r30, 0x04 ; 4
22da: 0c 94 f1 14 jmp 0x29e2 ; 0x29e2 <__epilogue_restores__+0x1c>
 
000022de <disk_timerproc>:
/* Device timer interrupt procedure */
/* This must be called in period of 10ms */
/* (Platform dependent) */
 
void disk_timerproc (void)
{
22de: 80 91 15 01 lds r24, 0x0115
static BYTE pv;
BYTE n, s;
 
 
n = Timer1; /* 100Hz decrement timer */
if (n) Timer1 = --n;
22e2: 88 23 and r24, r24
22e4: 19 f0 breq .+6 ; 0x22ec <disk_timerproc+0xe>
22e6: 81 50 subi r24, 0x01 ; 1
22e8: 80 93 15 01 sts 0x0115, r24
n = Timer2;
22ec: 80 91 16 01 lds r24, 0x0116
if (n) Timer2 = --n;
22f0: 88 23 and r24, r24
22f2: 19 f0 breq .+6 ; 0x22fa <disk_timerproc+0x1c>
22f4: 81 50 subi r24, 0x01 ; 1
22f6: 80 93 16 01 sts 0x0116, r24
 
n = pv;
22fa: 90 91 14 01 lds r25, 0x0114
pv = SOCKPORT & (SOCKINS); /* Sample socket switch */
22fe: 83 b1 in r24, 0x03 ; 3
2300: 81 70 andi r24, 0x01 ; 1
2302: 80 93 14 01 sts 0x0114, r24
 
if (n == pv) { /* Have contacts stabled? */
2306: 98 17 cp r25, r24
2308: 49 f4 brne .+18 ; 0x231c <disk_timerproc+0x3e>
s = Stat;
230a: 80 91 0b 01 lds r24, 0x010B
if (pv & SOCKINS) /* INS = H (Socket empty) */
230e: 90 ff sbrs r25, 0
2310: 02 c0 rjmp .+4 ; 0x2316 <disk_timerproc+0x38>
s |= (STA_NODISK | STA_NOINIT);
2312: 83 60 ori r24, 0x03 ; 3
2314: 01 c0 rjmp .+2 ; 0x2318 <disk_timerproc+0x3a>
else /* INS = L (Card inserted) */
s &= ~STA_NODISK;
2316: 8d 7f andi r24, 0xFD ; 253
 
Stat = s;
2318: 80 93 0b 01 sts 0x010B, r24
231c: 08 95 ret
 
0000231e <strcpy_P>:
231e: fb 01 movw r30, r22
2320: dc 01 movw r26, r24
2322: 05 90 lpm r0, Z+
2324: 0d 92 st X+, r0
2326: 00 20 and r0, r0
2328: e1 f7 brne .-8 ; 0x2322 <strcpy_P+0x4>
232a: 08 95 ret
 
0000232c <memcmp>:
232c: fb 01 movw r30, r22
232e: dc 01 movw r26, r24
2330: 04 c0 rjmp .+8 ; 0x233a <memcmp+0xe>
2332: 8d 91 ld r24, X+
2334: 01 90 ld r0, Z+
2336: 80 19 sub r24, r0
2338: 21 f4 brne .+8 ; 0x2342 <memcmp+0x16>
233a: 41 50 subi r20, 0x01 ; 1
233c: 50 40 sbci r21, 0x00 ; 0
233e: c8 f7 brcc .-14 ; 0x2332 <memcmp+0x6>
2340: 88 1b sub r24, r24
2342: 99 0b sbc r25, r25
2344: 08 95 ret
 
00002346 <memcpy>:
2346: fb 01 movw r30, r22
2348: dc 01 movw r26, r24
234a: 02 c0 rjmp .+4 ; 0x2350 <memcpy+0xa>
234c: 01 90 ld r0, Z+
234e: 0d 92 st X+, r0
2350: 41 50 subi r20, 0x01 ; 1
2352: 50 40 sbci r21, 0x00 ; 0
2354: d8 f7 brcc .-10 ; 0x234c <memcpy+0x6>
2356: 08 95 ret
 
00002358 <memset>:
2358: dc 01 movw r26, r24
235a: 01 c0 rjmp .+2 ; 0x235e <memset+0x6>
235c: 6d 93 st X+, r22
235e: 41 50 subi r20, 0x01 ; 1
2360: 50 40 sbci r21, 0x00 ; 0
2362: e0 f7 brcc .-8 ; 0x235c <memset+0x4>
2364: 08 95 ret
 
00002366 <itoa>:
2366: fb 01 movw r30, r22
2368: 9f 01 movw r18, r30
236a: e8 94 clt
236c: 42 30 cpi r20, 0x02 ; 2
236e: c4 f0 brlt .+48 ; 0x23a0 <itoa+0x3a>
2370: 45 32 cpi r20, 0x25 ; 37
2372: b4 f4 brge .+44 ; 0x23a0 <itoa+0x3a>
2374: 4a 30 cpi r20, 0x0A ; 10
2376: 29 f4 brne .+10 ; 0x2382 <itoa+0x1c>
2378: 97 fb bst r25, 7
237a: 1e f4 brtc .+6 ; 0x2382 <itoa+0x1c>
237c: 90 95 com r25
237e: 81 95 neg r24
2380: 9f 4f sbci r25, 0xFF ; 255
2382: 64 2f mov r22, r20
2384: 77 27 eor r23, r23
2386: 0e 94 fe 14 call 0x29fc ; 0x29fc <__udivmodhi4>
238a: 80 5d subi r24, 0xD0 ; 208
238c: 8a 33 cpi r24, 0x3A ; 58
238e: 0c f0 brlt .+2 ; 0x2392 <itoa+0x2c>
2390: 89 5d subi r24, 0xD9 ; 217
2392: 81 93 st Z+, r24
2394: cb 01 movw r24, r22
2396: 00 97 sbiw r24, 0x00 ; 0
2398: a1 f7 brne .-24 ; 0x2382 <itoa+0x1c>
239a: 16 f4 brtc .+4 ; 0x23a0 <itoa+0x3a>
239c: 5d e2 ldi r21, 0x2D ; 45
239e: 51 93 st Z+, r21
23a0: 10 82 st Z, r1
23a2: c9 01 movw r24, r18
23a4: 0c 94 ec 13 jmp 0x27d8 ; 0x27d8 <strrev>
 
000023a8 <sprintf>:
23a8: ae e0 ldi r26, 0x0E ; 14
23aa: b0 e0 ldi r27, 0x00 ; 0
23ac: ea ed ldi r30, 0xDA ; 218
23ae: f1 e1 ldi r31, 0x11 ; 17
23b0: 0c 94 d5 14 jmp 0x29aa ; 0x29aa <__prologue_saves__+0x1c>
23b4: 0d 89 ldd r16, Y+21 ; 0x15
23b6: 1e 89 ldd r17, Y+22 ; 0x16
23b8: 86 e0 ldi r24, 0x06 ; 6
23ba: 8c 83 std Y+4, r24 ; 0x04
23bc: 1a 83 std Y+2, r17 ; 0x02
23be: 09 83 std Y+1, r16 ; 0x01
23c0: 8f ef ldi r24, 0xFF ; 255
23c2: 9f e7 ldi r25, 0x7F ; 127
23c4: 9e 83 std Y+6, r25 ; 0x06
23c6: 8d 83 std Y+5, r24 ; 0x05
23c8: ce 01 movw r24, r28
23ca: 49 96 adiw r24, 0x19 ; 25
23cc: ac 01 movw r20, r24
23ce: 6f 89 ldd r22, Y+23 ; 0x17
23d0: 78 8d ldd r23, Y+24 ; 0x18
23d2: ce 01 movw r24, r28
23d4: 01 96 adiw r24, 0x01 ; 1
23d6: 0e 94 f7 11 call 0x23ee ; 0x23ee <vfprintf>
23da: 2f 81 ldd r18, Y+7 ; 0x07
23dc: 38 85 ldd r19, Y+8 ; 0x08
23de: 02 0f add r16, r18
23e0: 13 1f adc r17, r19
23e2: f8 01 movw r30, r16
23e4: 10 82 st Z, r1
23e6: 2e 96 adiw r28, 0x0e ; 14
23e8: e4 e0 ldi r30, 0x04 ; 4
23ea: 0c 94 f1 14 jmp 0x29e2 ; 0x29e2 <__epilogue_restores__+0x1c>
 
000023ee <vfprintf>:
23ee: ab e0 ldi r26, 0x0B ; 11
23f0: b0 e0 ldi r27, 0x00 ; 0
23f2: ed ef ldi r30, 0xFD ; 253
23f4: f1 e1 ldi r31, 0x11 ; 17
23f6: 0c 94 c7 14 jmp 0x298e ; 0x298e <__prologue_saves__>
23fa: 3c 01 movw r6, r24
23fc: 2b 01 movw r4, r22
23fe: 5a 01 movw r10, r20
2400: fc 01 movw r30, r24
2402: 17 82 std Z+7, r1 ; 0x07
2404: 16 82 std Z+6, r1 ; 0x06
2406: 83 81 ldd r24, Z+3 ; 0x03
2408: 81 fd sbrc r24, 1
240a: 03 c0 rjmp .+6 ; 0x2412 <vfprintf+0x24>
240c: 6f ef ldi r22, 0xFF ; 255
240e: 7f ef ldi r23, 0xFF ; 255
2410: c8 c1 rjmp .+912 ; 0x27a2 <vfprintf+0x3b4>
2412: 9a e0 ldi r25, 0x0A ; 10
2414: 89 2e mov r8, r25
2416: 1e 01 movw r2, r28
2418: 08 94 sec
241a: 21 1c adc r2, r1
241c: 31 1c adc r3, r1
241e: f3 01 movw r30, r6
2420: 23 81 ldd r18, Z+3 ; 0x03
2422: f2 01 movw r30, r4
2424: 23 fd sbrc r18, 3
2426: 85 91 lpm r24, Z+
2428: 23 ff sbrs r18, 3
242a: 81 91 ld r24, Z+
242c: 2f 01 movw r4, r30
242e: 88 23 and r24, r24
2430: 09 f4 brne .+2 ; 0x2434 <vfprintf+0x46>
2432: b4 c1 rjmp .+872 ; 0x279c <vfprintf+0x3ae>
2434: 85 32 cpi r24, 0x25 ; 37
2436: 39 f4 brne .+14 ; 0x2446 <vfprintf+0x58>
2438: 23 fd sbrc r18, 3
243a: 85 91 lpm r24, Z+
243c: 23 ff sbrs r18, 3
243e: 81 91 ld r24, Z+
2440: 2f 01 movw r4, r30
2442: 85 32 cpi r24, 0x25 ; 37
2444: 29 f4 brne .+10 ; 0x2450 <vfprintf+0x62>
2446: b3 01 movw r22, r6
2448: 90 e0 ldi r25, 0x00 ; 0
244a: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
244e: e7 cf rjmp .-50 ; 0x241e <vfprintf+0x30>
2450: 98 2f mov r25, r24
2452: dd 24 eor r13, r13
2454: cc 24 eor r12, r12
2456: 99 24 eor r9, r9
2458: ff e1 ldi r31, 0x1F ; 31
245a: fd 15 cp r31, r13
245c: d0 f0 brcs .+52 ; 0x2492 <vfprintf+0xa4>
245e: 9b 32 cpi r25, 0x2B ; 43
2460: 69 f0 breq .+26 ; 0x247c <vfprintf+0x8e>
2462: 9c 32 cpi r25, 0x2C ; 44
2464: 28 f4 brcc .+10 ; 0x2470 <vfprintf+0x82>
2466: 90 32 cpi r25, 0x20 ; 32
2468: 59 f0 breq .+22 ; 0x2480 <vfprintf+0x92>
246a: 93 32 cpi r25, 0x23 ; 35
246c: 91 f4 brne .+36 ; 0x2492 <vfprintf+0xa4>
246e: 0e c0 rjmp .+28 ; 0x248c <vfprintf+0x9e>
2470: 9d 32 cpi r25, 0x2D ; 45
2472: 49 f0 breq .+18 ; 0x2486 <vfprintf+0x98>
2474: 90 33 cpi r25, 0x30 ; 48
2476: 69 f4 brne .+26 ; 0x2492 <vfprintf+0xa4>
2478: 41 e0 ldi r20, 0x01 ; 1
247a: 24 c0 rjmp .+72 ; 0x24c4 <vfprintf+0xd6>
247c: 52 e0 ldi r21, 0x02 ; 2
247e: d5 2a or r13, r21
2480: 84 e0 ldi r24, 0x04 ; 4
2482: d8 2a or r13, r24
2484: 28 c0 rjmp .+80 ; 0x24d6 <vfprintf+0xe8>
2486: 98 e0 ldi r25, 0x08 ; 8
2488: d9 2a or r13, r25
248a: 25 c0 rjmp .+74 ; 0x24d6 <vfprintf+0xe8>
248c: e0 e1 ldi r30, 0x10 ; 16
248e: de 2a or r13, r30
2490: 22 c0 rjmp .+68 ; 0x24d6 <vfprintf+0xe8>
2492: d7 fc sbrc r13, 7
2494: 29 c0 rjmp .+82 ; 0x24e8 <vfprintf+0xfa>
2496: 89 2f mov r24, r25
2498: 80 53 subi r24, 0x30 ; 48
249a: 8a 30 cpi r24, 0x0A ; 10
249c: 70 f4 brcc .+28 ; 0x24ba <vfprintf+0xcc>
249e: d6 fe sbrs r13, 6
24a0: 05 c0 rjmp .+10 ; 0x24ac <vfprintf+0xbe>
24a2: 98 9c mul r9, r8
24a4: 90 2c mov r9, r0
24a6: 11 24 eor r1, r1
24a8: 98 0e add r9, r24
24aa: 15 c0 rjmp .+42 ; 0x24d6 <vfprintf+0xe8>
24ac: c8 9c mul r12, r8
24ae: c0 2c mov r12, r0
24b0: 11 24 eor r1, r1
24b2: c8 0e add r12, r24
24b4: f0 e2 ldi r31, 0x20 ; 32
24b6: df 2a or r13, r31
24b8: 0e c0 rjmp .+28 ; 0x24d6 <vfprintf+0xe8>
24ba: 9e 32 cpi r25, 0x2E ; 46
24bc: 29 f4 brne .+10 ; 0x24c8 <vfprintf+0xda>
24be: d6 fc sbrc r13, 6
24c0: 6d c1 rjmp .+730 ; 0x279c <vfprintf+0x3ae>
24c2: 40 e4 ldi r20, 0x40 ; 64
24c4: d4 2a or r13, r20
24c6: 07 c0 rjmp .+14 ; 0x24d6 <vfprintf+0xe8>
24c8: 9c 36 cpi r25, 0x6C ; 108
24ca: 19 f4 brne .+6 ; 0x24d2 <vfprintf+0xe4>
24cc: 50 e8 ldi r21, 0x80 ; 128
24ce: d5 2a or r13, r21
24d0: 02 c0 rjmp .+4 ; 0x24d6 <vfprintf+0xe8>
24d2: 98 36 cpi r25, 0x68 ; 104
24d4: 49 f4 brne .+18 ; 0x24e8 <vfprintf+0xfa>
24d6: f2 01 movw r30, r4
24d8: 23 fd sbrc r18, 3
24da: 95 91 lpm r25, Z+
24dc: 23 ff sbrs r18, 3
24de: 91 91 ld r25, Z+
24e0: 2f 01 movw r4, r30
24e2: 99 23 and r25, r25
24e4: 09 f0 breq .+2 ; 0x24e8 <vfprintf+0xfa>
24e6: b8 cf rjmp .-144 ; 0x2458 <vfprintf+0x6a>
24e8: 89 2f mov r24, r25
24ea: 85 54 subi r24, 0x45 ; 69
24ec: 83 30 cpi r24, 0x03 ; 3
24ee: 18 f0 brcs .+6 ; 0x24f6 <vfprintf+0x108>
24f0: 80 52 subi r24, 0x20 ; 32
24f2: 83 30 cpi r24, 0x03 ; 3
24f4: 38 f4 brcc .+14 ; 0x2504 <vfprintf+0x116>
24f6: 44 e0 ldi r20, 0x04 ; 4
24f8: 50 e0 ldi r21, 0x00 ; 0
24fa: a4 0e add r10, r20
24fc: b5 1e adc r11, r21
24fe: 5f e3 ldi r21, 0x3F ; 63
2500: 59 83 std Y+1, r21 ; 0x01
2502: 0f c0 rjmp .+30 ; 0x2522 <vfprintf+0x134>
2504: 93 36 cpi r25, 0x63 ; 99
2506: 31 f0 breq .+12 ; 0x2514 <vfprintf+0x126>
2508: 93 37 cpi r25, 0x73 ; 115
250a: 79 f0 breq .+30 ; 0x252a <vfprintf+0x13c>
250c: 93 35 cpi r25, 0x53 ; 83
250e: 09 f0 breq .+2 ; 0x2512 <vfprintf+0x124>
2510: 56 c0 rjmp .+172 ; 0x25be <vfprintf+0x1d0>
2512: 20 c0 rjmp .+64 ; 0x2554 <vfprintf+0x166>
2514: f5 01 movw r30, r10
2516: 80 81 ld r24, Z
2518: 89 83 std Y+1, r24 ; 0x01
251a: 42 e0 ldi r20, 0x02 ; 2
251c: 50 e0 ldi r21, 0x00 ; 0
251e: a4 0e add r10, r20
2520: b5 1e adc r11, r21
2522: 71 01 movw r14, r2
2524: 01 e0 ldi r16, 0x01 ; 1
2526: 10 e0 ldi r17, 0x00 ; 0
2528: 12 c0 rjmp .+36 ; 0x254e <vfprintf+0x160>
252a: f5 01 movw r30, r10
252c: e0 80 ld r14, Z
252e: f1 80 ldd r15, Z+1 ; 0x01
2530: d6 fc sbrc r13, 6
2532: 03 c0 rjmp .+6 ; 0x253a <vfprintf+0x14c>
2534: 6f ef ldi r22, 0xFF ; 255
2536: 7f ef ldi r23, 0xFF ; 255
2538: 02 c0 rjmp .+4 ; 0x253e <vfprintf+0x150>
253a: 69 2d mov r22, r9
253c: 70 e0 ldi r23, 0x00 ; 0
253e: 42 e0 ldi r20, 0x02 ; 2
2540: 50 e0 ldi r21, 0x00 ; 0
2542: a4 0e add r10, r20
2544: b5 1e adc r11, r21
2546: c7 01 movw r24, r14
2548: 0e 94 e1 13 call 0x27c2 ; 0x27c2 <strnlen>
254c: 8c 01 movw r16, r24
254e: 5f e7 ldi r21, 0x7F ; 127
2550: d5 22 and r13, r21
2552: 14 c0 rjmp .+40 ; 0x257c <vfprintf+0x18e>
2554: f5 01 movw r30, r10
2556: e0 80 ld r14, Z
2558: f1 80 ldd r15, Z+1 ; 0x01
255a: d6 fc sbrc r13, 6
255c: 03 c0 rjmp .+6 ; 0x2564 <vfprintf+0x176>
255e: 6f ef ldi r22, 0xFF ; 255
2560: 7f ef ldi r23, 0xFF ; 255
2562: 02 c0 rjmp .+4 ; 0x2568 <vfprintf+0x17a>
2564: 69 2d mov r22, r9
2566: 70 e0 ldi r23, 0x00 ; 0
2568: 42 e0 ldi r20, 0x02 ; 2
256a: 50 e0 ldi r21, 0x00 ; 0
256c: a4 0e add r10, r20
256e: b5 1e adc r11, r21
2570: c7 01 movw r24, r14
2572: 0e 94 d6 13 call 0x27ac ; 0x27ac <strnlen_P>
2576: 8c 01 movw r16, r24
2578: 50 e8 ldi r21, 0x80 ; 128
257a: d5 2a or r13, r21
257c: d3 fe sbrs r13, 3
257e: 07 c0 rjmp .+14 ; 0x258e <vfprintf+0x1a0>
2580: 1a c0 rjmp .+52 ; 0x25b6 <vfprintf+0x1c8>
2582: b3 01 movw r22, r6
2584: 80 e2 ldi r24, 0x20 ; 32
2586: 90 e0 ldi r25, 0x00 ; 0
2588: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
258c: ca 94 dec r12
258e: 8c 2d mov r24, r12
2590: 90 e0 ldi r25, 0x00 ; 0
2592: 08 17 cp r16, r24
2594: 19 07 cpc r17, r25
2596: a8 f3 brcs .-22 ; 0x2582 <vfprintf+0x194>
2598: 0e c0 rjmp .+28 ; 0x25b6 <vfprintf+0x1c8>
259a: f7 01 movw r30, r14
259c: d7 fc sbrc r13, 7
259e: 85 91 lpm r24, Z+
25a0: d7 fe sbrs r13, 7
25a2: 81 91 ld r24, Z+
25a4: 7f 01 movw r14, r30
25a6: b3 01 movw r22, r6
25a8: 90 e0 ldi r25, 0x00 ; 0
25aa: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
25ae: c1 10 cpse r12, r1
25b0: ca 94 dec r12
25b2: 01 50 subi r16, 0x01 ; 1
25b4: 10 40 sbci r17, 0x00 ; 0
25b6: 01 15 cp r16, r1
25b8: 11 05 cpc r17, r1
25ba: 79 f7 brne .-34 ; 0x259a <vfprintf+0x1ac>
25bc: ec c0 rjmp .+472 ; 0x2796 <vfprintf+0x3a8>
25be: 94 36 cpi r25, 0x64 ; 100
25c0: 11 f0 breq .+4 ; 0x25c6 <vfprintf+0x1d8>
25c2: 99 36 cpi r25, 0x69 ; 105
25c4: 71 f5 brne .+92 ; 0x2622 <vfprintf+0x234>
25c6: d7 fe sbrs r13, 7
25c8: 08 c0 rjmp .+16 ; 0x25da <vfprintf+0x1ec>
25ca: f5 01 movw r30, r10
25cc: e0 80 ld r14, Z
25ce: f1 80 ldd r15, Z+1 ; 0x01
25d0: 02 81 ldd r16, Z+2 ; 0x02
25d2: 13 81 ldd r17, Z+3 ; 0x03
25d4: 44 e0 ldi r20, 0x04 ; 4
25d6: 50 e0 ldi r21, 0x00 ; 0
25d8: 0a c0 rjmp .+20 ; 0x25ee <vfprintf+0x200>
25da: f5 01 movw r30, r10
25dc: 80 81 ld r24, Z
25de: 91 81 ldd r25, Z+1 ; 0x01
25e0: 7c 01 movw r14, r24
25e2: 00 27 eor r16, r16
25e4: f7 fc sbrc r15, 7
25e6: 00 95 com r16
25e8: 10 2f mov r17, r16
25ea: 42 e0 ldi r20, 0x02 ; 2
25ec: 50 e0 ldi r21, 0x00 ; 0
25ee: a4 0e add r10, r20
25f0: b5 1e adc r11, r21
25f2: 5f e6 ldi r21, 0x6F ; 111
25f4: d5 22 and r13, r21
25f6: 17 ff sbrs r17, 7
25f8: 0a c0 rjmp .+20 ; 0x260e <vfprintf+0x220>
25fa: 10 95 com r17
25fc: 00 95 com r16
25fe: f0 94 com r15
2600: e0 94 com r14
2602: e1 1c adc r14, r1
2604: f1 1c adc r15, r1
2606: 01 1d adc r16, r1
2608: 11 1d adc r17, r1
260a: 80 e8 ldi r24, 0x80 ; 128
260c: d8 2a or r13, r24
260e: 2a e0 ldi r18, 0x0A ; 10
2610: 30 e0 ldi r19, 0x00 ; 0
2612: a1 01 movw r20, r2
2614: c8 01 movw r24, r16
2616: b7 01 movw r22, r14
2618: 0e 94 28 14 call 0x2850 ; 0x2850 <__ultoa_invert>
261c: f8 2e mov r15, r24
261e: f2 18 sub r15, r2
2620: 40 c0 rjmp .+128 ; 0x26a2 <vfprintf+0x2b4>
2622: 95 37 cpi r25, 0x75 ; 117
2624: 29 f4 brne .+10 ; 0x2630 <vfprintf+0x242>
2626: 1d 2d mov r17, r13
2628: 1f 7e andi r17, 0xEF ; 239
262a: 2a e0 ldi r18, 0x0A ; 10
262c: 30 e0 ldi r19, 0x00 ; 0
262e: 1d c0 rjmp .+58 ; 0x266a <vfprintf+0x27c>
2630: 1d 2d mov r17, r13
2632: 19 7f andi r17, 0xF9 ; 249
2634: 9f 36 cpi r25, 0x6F ; 111
2636: 61 f0 breq .+24 ; 0x2650 <vfprintf+0x262>
2638: 90 37 cpi r25, 0x70 ; 112
263a: 20 f4 brcc .+8 ; 0x2644 <vfprintf+0x256>
263c: 98 35 cpi r25, 0x58 ; 88
263e: 09 f0 breq .+2 ; 0x2642 <vfprintf+0x254>
2640: ad c0 rjmp .+346 ; 0x279c <vfprintf+0x3ae>
2642: 0f c0 rjmp .+30 ; 0x2662 <vfprintf+0x274>
2644: 90 37 cpi r25, 0x70 ; 112
2646: 39 f0 breq .+14 ; 0x2656 <vfprintf+0x268>
2648: 98 37 cpi r25, 0x78 ; 120
264a: 09 f0 breq .+2 ; 0x264e <vfprintf+0x260>
264c: a7 c0 rjmp .+334 ; 0x279c <vfprintf+0x3ae>
264e: 04 c0 rjmp .+8 ; 0x2658 <vfprintf+0x26a>
2650: 28 e0 ldi r18, 0x08 ; 8
2652: 30 e0 ldi r19, 0x00 ; 0
2654: 0a c0 rjmp .+20 ; 0x266a <vfprintf+0x27c>
2656: 10 61 ori r17, 0x10 ; 16
2658: 14 fd sbrc r17, 4
265a: 14 60 ori r17, 0x04 ; 4
265c: 20 e1 ldi r18, 0x10 ; 16
265e: 30 e0 ldi r19, 0x00 ; 0
2660: 04 c0 rjmp .+8 ; 0x266a <vfprintf+0x27c>
2662: 14 fd sbrc r17, 4
2664: 16 60 ori r17, 0x06 ; 6
2666: 20 e1 ldi r18, 0x10 ; 16
2668: 32 e0 ldi r19, 0x02 ; 2
266a: 17 ff sbrs r17, 7
266c: 08 c0 rjmp .+16 ; 0x267e <vfprintf+0x290>
266e: f5 01 movw r30, r10
2670: 60 81 ld r22, Z
2672: 71 81 ldd r23, Z+1 ; 0x01
2674: 82 81 ldd r24, Z+2 ; 0x02
2676: 93 81 ldd r25, Z+3 ; 0x03
2678: 44 e0 ldi r20, 0x04 ; 4
267a: 50 e0 ldi r21, 0x00 ; 0
267c: 08 c0 rjmp .+16 ; 0x268e <vfprintf+0x2a0>
267e: f5 01 movw r30, r10
2680: 80 81 ld r24, Z
2682: 91 81 ldd r25, Z+1 ; 0x01
2684: bc 01 movw r22, r24
2686: 80 e0 ldi r24, 0x00 ; 0
2688: 90 e0 ldi r25, 0x00 ; 0
268a: 42 e0 ldi r20, 0x02 ; 2
268c: 50 e0 ldi r21, 0x00 ; 0
268e: a4 0e add r10, r20
2690: b5 1e adc r11, r21
2692: a1 01 movw r20, r2
2694: 0e 94 28 14 call 0x2850 ; 0x2850 <__ultoa_invert>
2698: f8 2e mov r15, r24
269a: f2 18 sub r15, r2
269c: 8f e7 ldi r24, 0x7F ; 127
269e: d8 2e mov r13, r24
26a0: d1 22 and r13, r17
26a2: d6 fe sbrs r13, 6
26a4: 0b c0 rjmp .+22 ; 0x26bc <vfprintf+0x2ce>
26a6: 5e ef ldi r21, 0xFE ; 254
26a8: d5 22 and r13, r21
26aa: f9 14 cp r15, r9
26ac: 38 f4 brcc .+14 ; 0x26bc <vfprintf+0x2ce>
26ae: d4 fe sbrs r13, 4
26b0: 07 c0 rjmp .+14 ; 0x26c0 <vfprintf+0x2d2>
26b2: d2 fc sbrc r13, 2
26b4: 05 c0 rjmp .+10 ; 0x26c0 <vfprintf+0x2d2>
26b6: 8f ee ldi r24, 0xEF ; 239
26b8: d8 22 and r13, r24
26ba: 02 c0 rjmp .+4 ; 0x26c0 <vfprintf+0x2d2>
26bc: 1f 2d mov r17, r15
26be: 01 c0 rjmp .+2 ; 0x26c2 <vfprintf+0x2d4>
26c0: 19 2d mov r17, r9
26c2: d4 fe sbrs r13, 4
26c4: 0d c0 rjmp .+26 ; 0x26e0 <vfprintf+0x2f2>
26c6: fe 01 movw r30, r28
26c8: ef 0d add r30, r15
26ca: f1 1d adc r31, r1
26cc: 80 81 ld r24, Z
26ce: 80 33 cpi r24, 0x30 ; 48
26d0: 19 f4 brne .+6 ; 0x26d8 <vfprintf+0x2ea>
26d2: 99 ee ldi r25, 0xE9 ; 233
26d4: d9 22 and r13, r25
26d6: 08 c0 rjmp .+16 ; 0x26e8 <vfprintf+0x2fa>
26d8: 1f 5f subi r17, 0xFF ; 255
26da: d2 fe sbrs r13, 2
26dc: 05 c0 rjmp .+10 ; 0x26e8 <vfprintf+0x2fa>
26de: 03 c0 rjmp .+6 ; 0x26e6 <vfprintf+0x2f8>
26e0: 8d 2d mov r24, r13
26e2: 86 78 andi r24, 0x86 ; 134
26e4: 09 f0 breq .+2 ; 0x26e8 <vfprintf+0x2fa>
26e6: 1f 5f subi r17, 0xFF ; 255
26e8: 0d 2d mov r16, r13
26ea: d3 fc sbrc r13, 3
26ec: 14 c0 rjmp .+40 ; 0x2716 <vfprintf+0x328>
26ee: d0 fe sbrs r13, 0
26f0: 0f c0 rjmp .+30 ; 0x2710 <vfprintf+0x322>
26f2: 1c 15 cp r17, r12
26f4: 10 f0 brcs .+4 ; 0x26fa <vfprintf+0x30c>
26f6: 9f 2c mov r9, r15
26f8: 0b c0 rjmp .+22 ; 0x2710 <vfprintf+0x322>
26fa: 9f 2c mov r9, r15
26fc: 9c 0c add r9, r12
26fe: 91 1a sub r9, r17
2700: 1c 2d mov r17, r12
2702: 06 c0 rjmp .+12 ; 0x2710 <vfprintf+0x322>
2704: b3 01 movw r22, r6
2706: 80 e2 ldi r24, 0x20 ; 32
2708: 90 e0 ldi r25, 0x00 ; 0
270a: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
270e: 1f 5f subi r17, 0xFF ; 255
2710: 1c 15 cp r17, r12
2712: c0 f3 brcs .-16 ; 0x2704 <vfprintf+0x316>
2714: 04 c0 rjmp .+8 ; 0x271e <vfprintf+0x330>
2716: 1c 15 cp r17, r12
2718: 10 f4 brcc .+4 ; 0x271e <vfprintf+0x330>
271a: c1 1a sub r12, r17
271c: 01 c0 rjmp .+2 ; 0x2720 <vfprintf+0x332>
271e: cc 24 eor r12, r12
2720: 04 ff sbrs r16, 4
2722: 10 c0 rjmp .+32 ; 0x2744 <vfprintf+0x356>
2724: b3 01 movw r22, r6
2726: 80 e3 ldi r24, 0x30 ; 48
2728: 90 e0 ldi r25, 0x00 ; 0
272a: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
272e: 02 ff sbrs r16, 2
2730: 1e c0 rjmp .+60 ; 0x276e <vfprintf+0x380>
2732: 01 fd sbrc r16, 1
2734: 03 c0 rjmp .+6 ; 0x273c <vfprintf+0x34e>
2736: 88 e7 ldi r24, 0x78 ; 120
2738: 90 e0 ldi r25, 0x00 ; 0
273a: 02 c0 rjmp .+4 ; 0x2740 <vfprintf+0x352>
273c: 88 e5 ldi r24, 0x58 ; 88
273e: 90 e0 ldi r25, 0x00 ; 0
2740: b3 01 movw r22, r6
2742: 0c c0 rjmp .+24 ; 0x275c <vfprintf+0x36e>
2744: 80 2f mov r24, r16
2746: 86 78 andi r24, 0x86 ; 134
2748: 91 f0 breq .+36 ; 0x276e <vfprintf+0x380>
274a: 01 ff sbrs r16, 1
274c: 02 c0 rjmp .+4 ; 0x2752 <vfprintf+0x364>
274e: 8b e2 ldi r24, 0x2B ; 43
2750: 01 c0 rjmp .+2 ; 0x2754 <vfprintf+0x366>
2752: 80 e2 ldi r24, 0x20 ; 32
2754: d7 fc sbrc r13, 7
2756: 8d e2 ldi r24, 0x2D ; 45
2758: b3 01 movw r22, r6
275a: 90 e0 ldi r25, 0x00 ; 0
275c: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
2760: 06 c0 rjmp .+12 ; 0x276e <vfprintf+0x380>
2762: b3 01 movw r22, r6
2764: 80 e3 ldi r24, 0x30 ; 48
2766: 90 e0 ldi r25, 0x00 ; 0
2768: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
276c: 9a 94 dec r9
276e: f9 14 cp r15, r9
2770: c0 f3 brcs .-16 ; 0x2762 <vfprintf+0x374>
2772: fa 94 dec r15
2774: f1 01 movw r30, r2
2776: ef 0d add r30, r15
2778: f1 1d adc r31, r1
277a: b3 01 movw r22, r6
277c: 80 81 ld r24, Z
277e: 90 e0 ldi r25, 0x00 ; 0
2780: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
2784: ff 20 and r15, r15
2786: a9 f7 brne .-22 ; 0x2772 <vfprintf+0x384>
2788: 06 c0 rjmp .+12 ; 0x2796 <vfprintf+0x3a8>
278a: b3 01 movw r22, r6
278c: 80 e2 ldi r24, 0x20 ; 32
278e: 90 e0 ldi r25, 0x00 ; 0
2790: 0e 94 fc 13 call 0x27f8 ; 0x27f8 <fputc>
2794: ca 94 dec r12
2796: cc 20 and r12, r12
2798: c1 f7 brne .-16 ; 0x278a <vfprintf+0x39c>
279a: 41 ce rjmp .-894 ; 0x241e <vfprintf+0x30>
279c: f3 01 movw r30, r6
279e: 66 81 ldd r22, Z+6 ; 0x06
27a0: 77 81 ldd r23, Z+7 ; 0x07
27a2: cb 01 movw r24, r22
27a4: 2b 96 adiw r28, 0x0b ; 11
27a6: e2 e1 ldi r30, 0x12 ; 18
27a8: 0c 94 e3 14 jmp 0x29c6 ; 0x29c6 <__epilogue_restores__>
 
000027ac <strnlen_P>:
27ac: fc 01 movw r30, r24
27ae: 05 90 lpm r0, Z+
27b0: 61 50 subi r22, 0x01 ; 1
27b2: 70 40 sbci r23, 0x00 ; 0
27b4: 01 10 cpse r0, r1
27b6: d8 f7 brcc .-10 ; 0x27ae <strnlen_P+0x2>
27b8: 80 95 com r24
27ba: 90 95 com r25
27bc: 8e 0f add r24, r30
27be: 9f 1f adc r25, r31
27c0: 08 95 ret
 
000027c2 <strnlen>:
27c2: fc 01 movw r30, r24
27c4: 61 50 subi r22, 0x01 ; 1
27c6: 70 40 sbci r23, 0x00 ; 0
27c8: 01 90 ld r0, Z+
27ca: 01 10 cpse r0, r1
27cc: d8 f7 brcc .-10 ; 0x27c4 <strnlen+0x2>
27ce: 80 95 com r24
27d0: 90 95 com r25
27d2: 8e 0f add r24, r30
27d4: 9f 1f adc r25, r31
27d6: 08 95 ret
 
000027d8 <strrev>:
27d8: dc 01 movw r26, r24
27da: fc 01 movw r30, r24
27dc: 67 2f mov r22, r23
27de: 71 91 ld r23, Z+
27e0: 77 23 and r23, r23
27e2: e1 f7 brne .-8 ; 0x27dc <strrev+0x4>
27e4: 32 97 sbiw r30, 0x02 ; 2
27e6: 04 c0 rjmp .+8 ; 0x27f0 <strrev+0x18>
27e8: 7c 91 ld r23, X
27ea: 6d 93 st X+, r22
27ec: 70 83 st Z, r23
27ee: 62 91 ld r22, -Z
27f0: ae 17 cp r26, r30
27f2: bf 07 cpc r27, r31
27f4: c8 f3 brcs .-14 ; 0x27e8 <strrev+0x10>
27f6: 08 95 ret
 
000027f8 <fputc>:
27f8: 0f 93 push r16
27fa: 1f 93 push r17
27fc: cf 93 push r28
27fe: df 93 push r29
2800: 8c 01 movw r16, r24
2802: eb 01 movw r28, r22
2804: 8b 81 ldd r24, Y+3 ; 0x03
2806: 81 ff sbrs r24, 1
2808: 1b c0 rjmp .+54 ; 0x2840 <fputc+0x48>
280a: 82 ff sbrs r24, 2
280c: 0d c0 rjmp .+26 ; 0x2828 <fputc+0x30>
280e: 2e 81 ldd r18, Y+6 ; 0x06
2810: 3f 81 ldd r19, Y+7 ; 0x07
2812: 8c 81 ldd r24, Y+4 ; 0x04
2814: 9d 81 ldd r25, Y+5 ; 0x05
2816: 28 17 cp r18, r24
2818: 39 07 cpc r19, r25
281a: 64 f4 brge .+24 ; 0x2834 <fputc+0x3c>
281c: e8 81 ld r30, Y
281e: f9 81 ldd r31, Y+1 ; 0x01
2820: 01 93 st Z+, r16
2822: f9 83 std Y+1, r31 ; 0x01
2824: e8 83 st Y, r30
2826: 06 c0 rjmp .+12 ; 0x2834 <fputc+0x3c>
2828: e8 85 ldd r30, Y+8 ; 0x08
282a: f9 85 ldd r31, Y+9 ; 0x09
282c: 80 2f mov r24, r16
282e: 09 95 icall
2830: 89 2b or r24, r25
2832: 31 f4 brne .+12 ; 0x2840 <fputc+0x48>
2834: 8e 81 ldd r24, Y+6 ; 0x06
2836: 9f 81 ldd r25, Y+7 ; 0x07
2838: 01 96 adiw r24, 0x01 ; 1
283a: 9f 83 std Y+7, r25 ; 0x07
283c: 8e 83 std Y+6, r24 ; 0x06
283e: 02 c0 rjmp .+4 ; 0x2844 <fputc+0x4c>
2840: 0f ef ldi r16, 0xFF ; 255
2842: 1f ef ldi r17, 0xFF ; 255
2844: c8 01 movw r24, r16
2846: df 91 pop r29
2848: cf 91 pop r28
284a: 1f 91 pop r17
284c: 0f 91 pop r16
284e: 08 95 ret
 
00002850 <__ultoa_invert>:
2850: fa 01 movw r30, r20
2852: aa 27 eor r26, r26
2854: 28 30 cpi r18, 0x08 ; 8
2856: 51 f1 breq .+84 ; 0x28ac <__ultoa_invert+0x5c>
2858: 20 31 cpi r18, 0x10 ; 16
285a: 81 f1 breq .+96 ; 0x28bc <__ultoa_invert+0x6c>
285c: e8 94 clt
285e: 6f 93 push r22
2860: 6e 7f andi r22, 0xFE ; 254
2862: 6e 5f subi r22, 0xFE ; 254
2864: 7f 4f sbci r23, 0xFF ; 255
2866: 8f 4f sbci r24, 0xFF ; 255
2868: 9f 4f sbci r25, 0xFF ; 255
286a: af 4f sbci r26, 0xFF ; 255
286c: b1 e0 ldi r27, 0x01 ; 1
286e: 3e d0 rcall .+124 ; 0x28ec <__ultoa_invert+0x9c>
2870: b4 e0 ldi r27, 0x04 ; 4
2872: 3c d0 rcall .+120 ; 0x28ec <__ultoa_invert+0x9c>
2874: 67 0f add r22, r23
2876: 78 1f adc r23, r24
2878: 89 1f adc r24, r25
287a: 9a 1f adc r25, r26
287c: a1 1d adc r26, r1
287e: 68 0f add r22, r24
2880: 79 1f adc r23, r25
2882: 8a 1f adc r24, r26
2884: 91 1d adc r25, r1
2886: a1 1d adc r26, r1
2888: 6a 0f add r22, r26
288a: 71 1d adc r23, r1
288c: 81 1d adc r24, r1
288e: 91 1d adc r25, r1
2890: a1 1d adc r26, r1
2892: 20 d0 rcall .+64 ; 0x28d4 <__ultoa_invert+0x84>
2894: 09 f4 brne .+2 ; 0x2898 <__ultoa_invert+0x48>
2896: 68 94 set
2898: 3f 91 pop r19
289a: 2a e0 ldi r18, 0x0A ; 10
289c: 26 9f mul r18, r22
289e: 11 24 eor r1, r1
28a0: 30 19 sub r19, r0
28a2: 30 5d subi r19, 0xD0 ; 208
28a4: 31 93 st Z+, r19
28a6: de f6 brtc .-74 ; 0x285e <__ultoa_invert+0xe>
28a8: cf 01 movw r24, r30
28aa: 08 95 ret
28ac: 46 2f mov r20, r22
28ae: 47 70 andi r20, 0x07 ; 7
28b0: 40 5d subi r20, 0xD0 ; 208
28b2: 41 93 st Z+, r20
28b4: b3 e0 ldi r27, 0x03 ; 3
28b6: 0f d0 rcall .+30 ; 0x28d6 <__ultoa_invert+0x86>
28b8: c9 f7 brne .-14 ; 0x28ac <__ultoa_invert+0x5c>
28ba: f6 cf rjmp .-20 ; 0x28a8 <__ultoa_invert+0x58>
28bc: 46 2f mov r20, r22
28be: 4f 70 andi r20, 0x0F ; 15
28c0: 40 5d subi r20, 0xD0 ; 208
28c2: 4a 33 cpi r20, 0x3A ; 58
28c4: 18 f0 brcs .+6 ; 0x28cc <__ultoa_invert+0x7c>
28c6: 49 5d subi r20, 0xD9 ; 217
28c8: 31 fd sbrc r19, 1
28ca: 40 52 subi r20, 0x20 ; 32
28cc: 41 93 st Z+, r20
28ce: 02 d0 rcall .+4 ; 0x28d4 <__ultoa_invert+0x84>
28d0: a9 f7 brne .-22 ; 0x28bc <__ultoa_invert+0x6c>
28d2: ea cf rjmp .-44 ; 0x28a8 <__ultoa_invert+0x58>
28d4: b4 e0 ldi r27, 0x04 ; 4
28d6: a6 95 lsr r26
28d8: 97 95 ror r25
28da: 87 95 ror r24
28dc: 77 95 ror r23
28de: 67 95 ror r22
28e0: ba 95 dec r27
28e2: c9 f7 brne .-14 ; 0x28d6 <__ultoa_invert+0x86>
28e4: 00 97 sbiw r24, 0x00 ; 0
28e6: 61 05 cpc r22, r1
28e8: 71 05 cpc r23, r1
28ea: 08 95 ret
28ec: 9b 01 movw r18, r22
28ee: ac 01 movw r20, r24
28f0: 0a 2e mov r0, r26
28f2: 06 94 lsr r0
28f4: 57 95 ror r21
28f6: 47 95 ror r20
28f8: 37 95 ror r19
28fa: 27 95 ror r18
28fc: ba 95 dec r27
28fe: c9 f7 brne .-14 ; 0x28f2 <__ultoa_invert+0xa2>
2900: 62 0f add r22, r18
2902: 73 1f adc r23, r19
2904: 84 1f adc r24, r20
2906: 95 1f adc r25, r21
2908: a0 1d adc r26, r0
290a: 08 95 ret
 
0000290c <__mulsi3>:
290c: 62 9f mul r22, r18
290e: d0 01 movw r26, r0
2910: 73 9f mul r23, r19
2912: f0 01 movw r30, r0
2914: 82 9f mul r24, r18
2916: e0 0d add r30, r0
2918: f1 1d adc r31, r1
291a: 64 9f mul r22, r20
291c: e0 0d add r30, r0
291e: f1 1d adc r31, r1
2920: 92 9f mul r25, r18
2922: f0 0d add r31, r0
2924: 83 9f mul r24, r19
2926: f0 0d add r31, r0
2928: 74 9f mul r23, r20
292a: f0 0d add r31, r0
292c: 65 9f mul r22, r21
292e: f0 0d add r31, r0
2930: 99 27 eor r25, r25
2932: 72 9f mul r23, r18
2934: b0 0d add r27, r0
2936: e1 1d adc r30, r1
2938: f9 1f adc r31, r25
293a: 63 9f mul r22, r19
293c: b0 0d add r27, r0
293e: e1 1d adc r30, r1
2940: f9 1f adc r31, r25
2942: bd 01 movw r22, r26
2944: cf 01 movw r24, r30
2946: 11 24 eor r1, r1
2948: 08 95 ret
 
0000294a <__udivmodsi4>:
294a: a1 e2 ldi r26, 0x21 ; 33
294c: 1a 2e mov r1, r26
294e: aa 1b sub r26, r26
2950: bb 1b sub r27, r27
2952: fd 01 movw r30, r26
2954: 0d c0 rjmp .+26 ; 0x2970 <__udivmodsi4_ep>
 
00002956 <__udivmodsi4_loop>:
2956: aa 1f adc r26, r26
2958: bb 1f adc r27, r27
295a: ee 1f adc r30, r30
295c: ff 1f adc r31, r31
295e: a2 17 cp r26, r18
2960: b3 07 cpc r27, r19
2962: e4 07 cpc r30, r20
2964: f5 07 cpc r31, r21
2966: 20 f0 brcs .+8 ; 0x2970 <__udivmodsi4_ep>
2968: a2 1b sub r26, r18
296a: b3 0b sbc r27, r19
296c: e4 0b sbc r30, r20
296e: f5 0b sbc r31, r21
 
00002970 <__udivmodsi4_ep>:
2970: 66 1f adc r22, r22
2972: 77 1f adc r23, r23
2974: 88 1f adc r24, r24
2976: 99 1f adc r25, r25
2978: 1a 94 dec r1
297a: 69 f7 brne .-38 ; 0x2956 <__udivmodsi4_loop>
297c: 60 95 com r22
297e: 70 95 com r23
2980: 80 95 com r24
2982: 90 95 com r25
2984: 9b 01 movw r18, r22
2986: ac 01 movw r20, r24
2988: bd 01 movw r22, r26
298a: cf 01 movw r24, r30
298c: 08 95 ret
 
0000298e <__prologue_saves__>:
298e: 2f 92 push r2
2990: 3f 92 push r3
2992: 4f 92 push r4
2994: 5f 92 push r5
2996: 6f 92 push r6
2998: 7f 92 push r7
299a: 8f 92 push r8
299c: 9f 92 push r9
299e: af 92 push r10
29a0: bf 92 push r11
29a2: cf 92 push r12
29a4: df 92 push r13
29a6: ef 92 push r14
29a8: ff 92 push r15
29aa: 0f 93 push r16
29ac: 1f 93 push r17
29ae: cf 93 push r28
29b0: df 93 push r29
29b2: cd b7 in r28, 0x3d ; 61
29b4: de b7 in r29, 0x3e ; 62
29b6: ca 1b sub r28, r26
29b8: db 0b sbc r29, r27
29ba: 0f b6 in r0, 0x3f ; 63
29bc: f8 94 cli
29be: de bf out 0x3e, r29 ; 62
29c0: 0f be out 0x3f, r0 ; 63
29c2: cd bf out 0x3d, r28 ; 61
29c4: 09 94 ijmp
 
000029c6 <__epilogue_restores__>:
29c6: 2a 88 ldd r2, Y+18 ; 0x12
29c8: 39 88 ldd r3, Y+17 ; 0x11
29ca: 48 88 ldd r4, Y+16 ; 0x10
29cc: 5f 84 ldd r5, Y+15 ; 0x0f
29ce: 6e 84 ldd r6, Y+14 ; 0x0e
29d0: 7d 84 ldd r7, Y+13 ; 0x0d
29d2: 8c 84 ldd r8, Y+12 ; 0x0c
29d4: 9b 84 ldd r9, Y+11 ; 0x0b
29d6: aa 84 ldd r10, Y+10 ; 0x0a
29d8: b9 84 ldd r11, Y+9 ; 0x09
29da: c8 84 ldd r12, Y+8 ; 0x08
29dc: df 80 ldd r13, Y+7 ; 0x07
29de: ee 80 ldd r14, Y+6 ; 0x06
29e0: fd 80 ldd r15, Y+5 ; 0x05
29e2: 0c 81 ldd r16, Y+4 ; 0x04
29e4: 1b 81 ldd r17, Y+3 ; 0x03
29e6: aa 81 ldd r26, Y+2 ; 0x02
29e8: b9 81 ldd r27, Y+1 ; 0x01
29ea: ce 0f add r28, r30
29ec: d1 1d adc r29, r1
29ee: 0f b6 in r0, 0x3f ; 63
29f0: f8 94 cli
29f2: de bf out 0x3e, r29 ; 62
29f4: 0f be out 0x3f, r0 ; 63
29f6: cd bf out 0x3d, r28 ; 61
29f8: ed 01 movw r28, r26
29fa: 08 95 ret
 
000029fc <__udivmodhi4>:
29fc: aa 1b sub r26, r26
29fe: bb 1b sub r27, r27
2a00: 51 e1 ldi r21, 0x11 ; 17
2a02: 07 c0 rjmp .+14 ; 0x2a12 <__udivmodhi4_ep>
 
00002a04 <__udivmodhi4_loop>:
2a04: aa 1f adc r26, r26
2a06: bb 1f adc r27, r27
2a08: a6 17 cp r26, r22
2a0a: b7 07 cpc r27, r23
2a0c: 10 f0 brcs .+4 ; 0x2a12 <__udivmodhi4_ep>
2a0e: a6 1b sub r26, r22
2a10: b7 0b sbc r27, r23
 
00002a12 <__udivmodhi4_ep>:
2a12: 88 1f adc r24, r24
2a14: 99 1f adc r25, r25
2a16: 5a 95 dec r21
2a18: a9 f7 brne .-22 ; 0x2a04 <__udivmodhi4_loop>
2a1a: 80 95 com r24
2a1c: 90 95 com r25
2a1e: bc 01 movw r22, r24
2a20: cd 01 movw r24, r26
2a22: 08 95 ret
 
00002a24 <_exit>:
2a24: f8 94 cli
 
00002a26 <__stop_program>:
2a26: ff cf rjmp .-2 ; 0x2a26 <__stop_program>
/Designs/Data_loggers/GPSRL03A/main.c
0,0 → 1,402
/*---------------------------------------------------------------*/
/* GPS data logger R0.02 (C)ChaN, 2008 */
/*---------------------------------------------------------------*/
 
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <string.h>
#include "tff.h"
#include "diskio.h"
 
 
#define SYSCLK 10000000UL
 
#define BEEP_ON() TCCR0B=0b011
#define BEEP_OFF() TCCR0B=0b000
#define GPS_ON() PORTB|=0x02
#define GPS_OFF() PORTB&=0xFD
#define DELAY(dly) for(Timer=dly;Timer;)
 
#define GPS_BAUDRATE 4800 // Enable USRAT0 in N81,9600bps
 
#define VTH_LOW (WORD)(8000UL*100/3838)
#define VTH_HIGH (WORD)(11500UL*100/3838)
#define POWER_check 0b01000000 | 1
#define ANALOG_IN1 0b01000000 | 2
 
 
FATFS fatfs; /* File system object for each logical drive */
FIL file1; /* File object */
BYTE Buff[82]; /* File/Console buffer */
 
BYTE Value1[4]; // logged values
BYTE Value2[4];
 
uint16_t battery; // battery voltage
uint16_t intensity; // radiation intensity
 
volatile BYTE Timer; /* 100Hz decrement timer */
volatile BYTE Stat; /* Status */
 
 
typedef struct _fifo {
uint8_t idx_w;
uint8_t idx_r;
uint8_t count;
uint8_t buff[150];
} FIFO;
volatile FIFO rxfifo;
 
 
 
/*---------------------------------------------------------*/
/* ADC interrupt */
/*---------------------------------------------------------*/
 
ISR(ADC_vect)
{
WORD n;
static BYTE l, h;
 
n = ADC;
 
if(ADMUX == POWER_check)
{
if (n < VTH_LOW) {
if (l >= 15) {
Stat |= 0x01;
}
else {l++;}
}
else {l = 0;}
 
if (n > VTH_HIGH) {
if (h >= 15) {
Stat &= 0xFE;
}
else {h++;}
}
else {h = 0;}
 
battery = n;
ADMUX = ANALOG_IN1;
}
 
if(ADMUX == ANALOG_IN1)
{
intensity = n;
ADMUX = POWER_check;
}
 
//!!!!
//Stat &= 0xFE;
 
ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;
}
 
 
/*---------------------------------------------------------*/
/* 100Hz timer interrupt generated by OC1A */
/*---------------------------------------------------------*/
 
 
ISR(TIMER1_COMPA_vect)
{
BYTE n;
static WORD ivt_sync;
 
 
n = Timer;
if (n) Timer = n - 1;
 
if (++ivt_sync >= 180 * 100) {
ivt_sync = 0;
Stat |= 4;
}
 
disk_timerproc(); /* Drive timer procedure of low level disk I/O module */
 
}
 
 
 
/*---------------------------------------------------------*/
/* User Provided Timer Function for FatFs module */
/*---------------------------------------------------------*/
/* This is a real time clock service to be called from */
/* FatFs module. Any valid time must be returned even if */
/* the system does not support a real time clock. */
 
 
DWORD get_fattime ()
{
return ((2007UL - 1980) << 25) /* Fixed to 2007.5.1, 00:00:00 */
| ((5UL) << 21)
| ((1UL) << 16)
| (0 << 11)
| (0 << 5)
| (0 >> 1);
}
 
 
/*--------------------------------------------------------------------------*/
/* UART control */
 
 
static
void uart_init (void)
{
cli();
UCSR0B = 0;
rxfifo.idx_r = 0;
rxfifo.idx_w = 0;
rxfifo.count = 0;
UBRR0L = SYSCLK/16/GPS_BAUDRATE;
UCSR0B = _BV(RXCIE0)|_BV(RXEN0)|_BV(TXEN0);
Stat &= 0xFD; // Clear overflow flag
sei();
}
 
 
static
void uart_stop (void)
{
UCSR0B = 0;
}
 
 
/* Get a received character */
static
uint8_t uart_get ()
{
uint8_t d, i;
 
 
i = rxfifo.idx_r;
if (rxfifo.count == 0) return 0;
d = rxfifo.buff[i++];
cli();
rxfifo.count--;
sei();
if(i >= sizeof(rxfifo.buff))
i = 0;
rxfifo.idx_r = i;
 
return d;
+
+/* USART0 RXC interrupt */
+ISR(USART_RX_vect)
+{
+ uint8_t d, n, i;
+
+
+ d = UDR0;
+ n = rxfifo.count;
+ if(n < sizeof(rxfifo.buff)) {
+ rxfifo.count = ++n;
+ i = rxfifo.idx_w;
+ rxfifo.buff[i++] = d;
+ if(i >= sizeof(rxfifo.buff))
+ i = 0;
+ rxfifo.idx_w = i;
+ } else {
+ Stat |= 2;
+ }
+}
+
+
+
+/*----------------------------------------------------*/
+/* Get a line received from GPS module */
+/*----------------------------------------------------*/
+
+static
+BYTE get_line (void) // 0: Power fail occured, >0: Number of bytes received.
+{
+ BYTE c, i = 0;
+
+
+ for (;;) {
+ if (Stat & 1) return 0; // When power fail is detected, return with zero.
+ c = uart_get();
+ if (Stat & 2) { // When buffer overflow has occured, restart to receive line.
+ uart_init();
+ i = 0; c = 0;
+ }
+ if (!c || (i == 0 && c != '$')) continue;
+ Buff[i++] = c;
+ if (c == '\n') break;
+ if (i >= sizeof(Buff)) i = 0;
+ }
+ return i;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/* Controls */
+
+static
+void beep (BYTE len, BYTE cnt)
+{
+ while (cnt--) {
+ BEEP_ON();
+ DELAY(len);
+ BEEP_OFF();
+ DELAY(len);
+ }
+}
+
+
+
+
+/* Compare sentence header string */
+static
+BYTE gp_comp (BYTE *str1, const prog_uint8_t *str2)
+{
+ BYTE c;
+
+ do {
+ c = pgm_read_byte(str2++);
+ } while (c && c == *str1++);
+ return c;
+}
+
+/* Get a column item */
+static
+BYTE* gp_col ( /* Returns pointer to the item (returns a NULL when not found) */
+ const BYTE* buf, /* Pointer to the sentence */
+ BYTE col /* Column number (0 is the 1st item) */
+) {
+ BYTE c;
+
+
+ while (col) {
+ do {
+ c = *buf++;
+ if (c <= ' ') return NULL;
+ } while (c != ',');
+ col--;
+ }
+ return (BYTE*)buf;
+}
+
+
+
+static
+void ioinit (void)
+{
+ PORTB = 0b00001101; // Port B
+ DDRB = 0b00101110;
+ PORTC = 0b00111111; // Port C
+ DDRC = 0b00000000;
+ PORTD = 0b10101110; // Port D
+ DDRD = 0b01010010;
+
+ SPCR = 0b01010000; /* Initialize SPI port (Mode 0) */
+ SPSR = 0b00000001;
+
+ OCR1A = SYSCLK/8/100-1; // Timer1: 100Hz interval (OC1A)
+ TCCR1B = 0b00001010;
+ TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
+
+ OCR0A = SYSCLK/64/4000/2-1; // Timer0: 4kHz sound (OC0A)
+ TCCR0A = 0b01000010;
+
+ ADMUX = POWER_check; // Select ADC input
+ ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;
+
+ sei();
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Main */
+
+
+int main ()
+{
+ BYTE b, err, *p = NULL;
+ WORD s;
+
+
+ ioinit();
+ f_mount(0, &fatfs); /* Enable file I/O layer */
+
+ for (;;) {
+ uart_stop();
+ GPS_OFF();
+ Timer = 100;
+ do {
+ if (Stat & 1) Timer = 100;
+ } while (Timer);
+
+ GPS_ON();
+ Timer = 255;
+ do {
+ if ((Stat & 1) || (disk_status(0) & STA_NODISK)) Timer = 255;
+ } while (Timer);
+
+ beep(5, 1); // Single beep. Start to get current time.
+ uart_init();
+ do { // Wait for valid RMC sentence.
+ b = get_line();
+ if (!b) break;
+ if (gp_comp(Buff, PSTR("$GPRMC"))) continue;
+ p = gp_col(Buff,2);
+ } while (!p || *p != 'A');
+ if (!b) continue;
+ p = gp_col(Buff,9); // Open log file with the name of current date (YYMMDD.log in UTC).
+
+ if (!p) {err = 3; break;}
+
+ memcpy(&Buff[0], p+4, 2);
+ memcpy(&Buff[2], p+2, 2);
+ memcpy(&Buff[4], p+0, 2);
+ strcpy_P(&Buff[6], PSTR(".log"));
+ if (f_open(&file1, Buff, FA_OPEN_ALWAYS | FA_WRITE) || f_lseek(&file1, file1.fsize)) { err = 4; break; }
+
+ beep(5, 2); // Two beeps. Start logging.
+ err = 0;
+ while ((b = get_line()) > 0) {
+ if ( !gp_comp(Buff, PSTR("$GPGGA")) // Which sentence is logged?
+ || !gp_comp(Buff, PSTR("$GPRMC"))
+ // || !gp_comp(Buff, PSTR("$GPGSA"))
+ // || !gp_comp(Buff, PSTR("$GPGLL"))
+ // || !gp_comp(Buff, PSTR("$GPGSV"))
+ // || !gp_comp(Buff, PSTR("$GPZDA"))
+ // || !gp_comp(Buff, PSTR("$GPVTG"))
+ )
+ {
+ if (f_write(&file1, Buff, b, &s) || b != s) { err = 5; break; };
+ itoa(battery,&Value1,10); // convert number to character
+ itoa(intensity,&Value2,10);
+ sprintf(Buff,"%d,%d\n",Value1,Value2);
+ if (f_write(&file1, Buff,strlen(Buff), &s) || (strlen(Buff) != s)) { err = 8; break; };
+ }
+ if ((Stat & 4) == 0) continue;
+ if (f_sync(&file1)) { err = 6; break; };// Synchronize the file in interval of 300 sec.
+ cli(); Stat &= 0xFB; sei(); // Clear sync request
+ }
+ if (err) break;
+
+ // Turn-off GPS power and close the log file by power supply is discharged.
+ uart_stop();
+ GPS_OFF();
+ if (f_close(&file1)) { err = 7; break; };
+
+ // When a long beep is sounded, the shutdoun process has been succeeded.
+ beep(50, 1);
+ }
+
+ // Unrecoverble error. Enter shutdown state.
+ uart_stop();
+ GPS_OFF();
+ beep(25, err);
+ for (;;);
+}
+
+
/Designs/Data_loggers/GPSRL03A/glg.map
0,0 → 1,573
Archive member included because of file (symbol)
 
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_mulsi3.o)
tff.o (__mulsi3)
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodsi4.o)
tff.o (__udivmodsi4)
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_prologue.o)
main.o (__prologue_saves__)
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_epilogue.o)
tff.o (__epilogue_restores__)
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_exit.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o (exit)
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_copy_data.o)
main.o (__do_copy_data)
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_clear_bss.o)
main.o (__do_clear_bss)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strcpy_P.o)
main.o (strcpy_P)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcmp.o)
tff.o (memcmp)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcpy.o)
tff.o (memcpy)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memset.o)
tff.o (memset)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(itoa.o)
main.o (itoa)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(sprintf.o)
main.o (sprintf)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(sprintf.o) (vfprintf)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen_P.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o) (strnlen_P)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o) (strnlen)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strrev.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(itoa.o) (strrev)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(fputc.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o) (fputc)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(ultoa_invert.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o) (__ultoa_invert)
/usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodhi4.o)
/usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(itoa.o) (__udivmodhi4)
 
Allocating common symbols
Common symbol size file
 
Value1 0x4 main.o
Timer 0x1 main.o
Buff 0x52 main.o
Stat 0x1 main.o
Value2 0x4 main.o
battery 0x2 main.o
rxfifo 0x99 main.o
intensity 0x2 main.o
file1 0x1c main.o
fatfs 0x220 main.o
 
Memory Configuration
 
Name Origin Length Attributes
text 0x00000000 0x00020000 xr
data 0x00800060 0x0000ffa0 rw !x
eeprom 0x00810000 0x00010000 rw !x
fuse 0x00820000 0x00000400 rw !x
lock 0x00830000 0x00000400 rw !x
signature 0x00840000 0x00000400 rw !x
*default* 0x00000000 0xffffffff
 
Linker script and memory map
 
Address of section .data set to 0x800100
LOAD /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
LOAD main.o
LOAD tff.o
LOAD mmc.o
LOAD /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a
LOAD /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a
LOAD /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a
 
.hash
*(.hash)
 
.dynsym
*(.dynsym)
 
.dynstr
*(.dynstr)
 
.gnu.version
*(.gnu.version)
 
.gnu.version_d
*(.gnu.version_d)
 
.gnu.version_r
*(.gnu.version_r)
 
.rel.init
*(.rel.init)
 
.rela.init
*(.rela.init)
 
.rel.text
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t*)
 
.rela.text
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t*)
 
.rel.fini
*(.rel.fini)
 
.rela.fini
*(.rela.fini)
 
.rel.rodata
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r*)
 
.rela.rodata
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r*)
 
.rel.data
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d*)
 
.rela.data
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d*)
 
.rel.ctors
*(.rel.ctors)
 
.rela.ctors
*(.rela.ctors)
 
.rel.dtors
*(.rel.dtors)
 
.rela.dtors
*(.rela.dtors)
 
.rel.got
*(.rel.got)
 
.rela.got
*(.rela.got)
 
.rel.bss
*(.rel.bss)
 
.rela.bss
*(.rela.bss)
 
.rel.plt
*(.rel.plt)
 
.rela.plt
*(.rela.plt)
 
.text 0x00000000 0x2a28
*(.vectors)
.vectors 0x00000000 0x68 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
0x00000000 __vectors
0x00000000 __vector_default
*(.vectors)
*(.progmem.gcc*)
*(.progmem*)
.progmem.data 0x00000068 0x1a main.o
0x00000082 . = ALIGN (0x2)
0x00000082 __trampolines_start = .
*(.trampolines)
.trampolines 0x00000082 0x0 linker stubs
*(.trampolines*)
0x00000082 __trampolines_end = .
*(.jumptables)
*(.jumptables*)
*(.lowtext)
*(.lowtext*)
0x00000082 __ctors_start = .
*(.ctors)
0x00000082 __ctors_end = .
0x00000082 __dtors_start = .
*(.dtors)
0x00000082 __dtors_end = .
SORT(*)(.ctors)
SORT(*)(.dtors)
*(.init0)
.init0 0x00000082 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
0x00000082 __init
*(.init0)
*(.init1)
*(.init1)
*(.init2)
.init2 0x00000082 0xc /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
*(.init2)
*(.init3)
*(.init3)
*(.init4)
.init4 0x0000008e 0x16 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_copy_data.o)
0x0000008e __do_copy_data
.init4 0x000000a4 0x10 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_clear_bss.o)
0x000000a4 __do_clear_bss
*(.init4)
*(.init5)
*(.init5)
*(.init6)
*(.init6)
*(.init7)
*(.init7)
*(.init8)
*(.init8)
*(.init9)
.init9 0x000000b4 0x8 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
*(.init9)
*(.text)
.text 0x000000bc 0x4 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
0x000000bc __vector_22
0x000000bc __vector_1
0x000000bc __vector_24
0x000000bc __vector_12
0x000000bc __bad_interrupt
0x000000bc __vector_6
0x000000bc __vector_3
0x000000bc __vector_23
0x000000bc __vector_25
0x000000bc __vector_13
0x000000bc __vector_17
0x000000bc __vector_19
0x000000bc __vector_7
0x000000bc __vector_5
0x000000bc __vector_4
0x000000bc __vector_9
0x000000bc __vector_2
0x000000bc __vector_15
0x000000bc __vector_8
0x000000bc __vector_14
0x000000bc __vector_10
0x000000bc __vector_16
0x000000bc __vector_20
.text 0x000000c0 0x5cc main.o
0x00000630 __vector_11
0x00000160 get_fattime
0x0000026a main
0x000000c0 __vector_21
0x0000016a __vector_18
.text 0x0000068c 0x153a tff.o
0x00000e00 f_close
0x000010d0 f_read
0x00000d52 f_sync
0x000012fe f_mount
0x00000a78 f_lseek
0x00000e1c f_write
0x000013ae f_open
.text 0x00001bc6 0x758 mmc.o
0x00001d70 disk_initialize
0x00001f2a disk_status
0x000020ee disk_ioctl
0x000022de disk_timerproc
0x00001ff6 disk_write
0x00001f38 disk_read
.text 0x0000231e 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_mulsi3.o)
.text 0x0000231e 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodsi4.o)
.text 0x0000231e 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_prologue.o)
.text 0x0000231e 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_epilogue.o)
.text 0x0000231e 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_exit.o)
.text 0x0000231e 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_copy_data.o)
.text 0x0000231e 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_clear_bss.o)
.text 0x0000231e 0xe /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strcpy_P.o)
0x0000231e strcpy_P
.text 0x0000232c 0x1a /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcmp.o)
0x0000232c memcmp
.text 0x00002346 0x12 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcpy.o)
0x00002346 memcpy
.text 0x00002358 0xe /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memset.o)
0x00002358 memset
.text 0x00002366 0x42 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(itoa.o)
0x00002366 itoa
.text 0x000023a8 0x46 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(sprintf.o)
0x000023a8 sprintf
.text 0x000023ee 0x3be /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o)
0x000023ee vfprintf
.text 0x000027ac 0x16 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen_P.o)
0x000027ac strnlen_P
.text 0x000027c2 0x16 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen.o)
0x000027c2 strnlen
.text 0x000027d8 0x20 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strrev.o)
0x000027d8 strrev
.text 0x000027f8 0x58 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(fputc.o)
0x000027f8 fputc
.text 0x00002850 0xbc /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(ultoa_invert.o)
0x00002850 __ultoa_invert
.text 0x0000290c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodhi4.o)
0x0000290c . = ALIGN (0x2)
*(.text.*)
.text.libgcc 0x0000290c 0x3e /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_mulsi3.o)
0x0000290c __mulsi3
.text.libgcc 0x0000294a 0x44 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodsi4.o)
0x0000294a __udivmodsi4
.text.libgcc 0x0000298e 0x38 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_prologue.o)
0x0000298e __prologue_saves__
.text.libgcc 0x000029c6 0x36 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_epilogue.o)
0x000029c6 __epilogue_restores__
.text.libgcc 0x000029fc 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_exit.o)
.text.libgcc 0x000029fc 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_copy_data.o)
.text.libgcc 0x000029fc 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_clear_bss.o)
.text.libgcc 0x000029fc 0x28 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodhi4.o)
0x000029fc __udivmodhi4
0x00002a24 . = ALIGN (0x2)
*(.fini9)
.fini9 0x00002a24 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_exit.o)
0x00002a24 exit
0x00002a24 _exit
*(.fini9)
*(.fini8)
*(.fini8)
*(.fini7)
*(.fini7)
*(.fini6)
*(.fini6)
*(.fini5)
*(.fini5)
*(.fini4)
*(.fini4)
*(.fini3)
*(.fini3)
*(.fini2)
*(.fini2)
*(.fini1)
*(.fini1)
*(.fini0)
.fini0 0x00002a24 0x4 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_exit.o)
*(.fini0)
0x00002a28 _etext = .
 
.data 0x00800100 0xc load address 0x00002a28
0x00800100 PROVIDE (__data_start, .)
*(.data)
.data 0x00800100 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
.data 0x00800100 0x7 main.o
.data 0x00800107 0x4 tff.o
.data 0x0080010b 0x1 mmc.o
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_mulsi3.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodsi4.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_prologue.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_epilogue.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_exit.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_copy_data.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_clear_bss.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strcpy_P.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcmp.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcpy.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memset.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(itoa.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(sprintf.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen_P.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strrev.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(fputc.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(ultoa_invert.o)
.data 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodhi4.o)
*(.data*)
*(.rodata)
*(.rodata*)
*(.gnu.linkonce.d*)
0x0080010c . = ALIGN (0x2)
0x0080010c _edata = .
0x0080010c PROVIDE (__data_end, .)
 
.bss 0x0080010c 0x341 load address 0x00002a34
0x0080010c PROVIDE (__bss_start, .)
*(.bss)
.bss 0x0080010c 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
.bss 0x0080010c 0x4 main.o
.bss 0x00800110 0x4 tff.o
.bss 0x00800114 0x4 mmc.o
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_mulsi3.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodsi4.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_prologue.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_epilogue.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_exit.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_copy_data.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_clear_bss.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strcpy_P.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcmp.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcpy.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memset.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(itoa.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(sprintf.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen_P.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strrev.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(fputc.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(ultoa_invert.o)
.bss 0x00800118 0x0 /usr/lib/gcc/avr/4.3.0/avr5/libgcc.a(_udivmodhi4.o)
*(.bss*)
*(COMMON)
COMMON 0x00800118 0x335 main.o
0x00800118 Value1
0x0080011c Timer
0x0080011d Buff
0x0080016f Stat
0x00800170 Value2
0x00800174 battery
0x00800176 rxfifo
0x0080020f intensity
0x00800211 file1
0x0080022d fatfs
0x0080044d PROVIDE (__bss_end, .)
0x00002a28 __data_load_start = LOADADDR (.data)
0x00002a34 __data_load_end = (__data_load_start + SIZEOF (.data))
 
.noinit 0x0080044d 0x0
0x0080044d PROVIDE (__noinit_start, .)
*(.noinit*)
0x0080044d PROVIDE (__noinit_end, .)
0x0080044d _end = .
0x0080044d PROVIDE (__heap_start, .)
 
.eeprom 0x00810000 0x0
*(.eeprom*)
0x00810000 __eeprom_end = .
 
.fuse
*(.fuse)
*(.lfuse)
*(.hfuse)
*(.efuse)
 
.lock
*(.lock*)
 
.signature
*(.signature*)
 
.stab 0x00000000 0x2040
*(.stab)
.stab 0x00000000 0x6b4 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
.stab 0x000006b4 0x6c /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strcpy_P.o)
0x78 (size before relaxing)
.stab 0x00000720 0xb4 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcmp.o)
0xc0 (size before relaxing)
.stab 0x000007d4 0x84 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memcpy.o)
0x90 (size before relaxing)
.stab 0x00000858 0x6c /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(memset.o)
0x78 (size before relaxing)
.stab 0x000008c4 0x1b0 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(itoa.o)
0x1bc (size before relaxing)
.stab 0x00000a74 0x3cc /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(sprintf.o)
0x3d8 (size before relaxing)
.stab 0x00000e40 0x99c /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(vfprintf_std.o)
0xb7c (size before relaxing)
.stab 0x000017dc 0x9c /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen_P.o)
0xa8 (size before relaxing)
.stab 0x00001878 0x9c /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strnlen.o)
0xa8 (size before relaxing)
.stab 0x00001914 0xd8 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(strrev.o)
0xe4 (size before relaxing)
.stab 0x000019ec 0x1d4 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(fputc.o)
0x3b4 (size before relaxing)
.stab 0x00001bc0 0x480 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/libc.a(ultoa_invert.o)
0x48c (size before relaxing)
 
.stabstr 0x00000000 0xdb4
*(.stabstr)
.stabstr 0x00000000 0xdb4 /usr/lib/gcc/avr/4.3.0/../../../../avr/lib/avr5/crtm168.o
 
.stab.excl
*(.stab.excl)
 
.stab.exclstr
*(.stab.exclstr)
 
.stab.index
*(.stab.index)
 
.stab.indexstr
*(.stab.indexstr)
 
.comment
*(.comment)
 
.debug
*(.debug)
 
.line
*(.line)
 
.debug_srcinfo
*(.debug_srcinfo)
 
.debug_sfnames
*(.debug_sfnames)
 
.debug_aranges 0x00000000 0x60
*(.debug_aranges)
.debug_aranges
0x00000000 0x20 main.o
.debug_aranges
0x00000020 0x20 tff.o
.debug_aranges
0x00000040 0x20 mmc.o
 
.debug_pubnames
0x00000000 0x19e
*(.debug_pubnames)
.debug_pubnames
0x00000000 0xc6 main.o
.debug_pubnames
0x000000c6 0x63 tff.o
.debug_pubnames
0x00000129 0x75 mmc.o
 
.debug_info 0x00000000 0x1f60
*(.debug_info)
.debug_info 0x00000000 0x906 main.o
.debug_info 0x00000906 0x100d tff.o
.debug_info 0x00001913 0x64d mmc.o
*(.gnu.linkonce.wi.*)
 
.debug_abbrev 0x00000000 0x7b9
*(.debug_abbrev)
.debug_abbrev 0x00000000 0x28d main.o
.debug_abbrev 0x0000028d 0x2d6 tff.o
.debug_abbrev 0x00000563 0x256 mmc.o
 
.debug_line 0x00000000 0x1b85
*(.debug_line)
.debug_line 0x00000000 0x6bb main.o
.debug_line 0x000006bb 0xdd3 tff.o
.debug_line 0x0000148e 0x6f7 mmc.o
 
.debug_frame 0x00000000 0x200
*(.debug_frame)
.debug_frame 0x00000000 0x70 main.o
.debug_frame 0x00000070 0xf0 tff.o
.debug_frame 0x00000160 0xa0 mmc.o
 
.debug_str 0x00000000 0x5cc
*(.debug_str)
.debug_str 0x00000000 0x26d main.o
0x2c8 (size before relaxing)
.debug_str 0x0000026d 0x29f tff.o
0x430 (size before relaxing)
.debug_str 0x0000050c 0xc0 mmc.o
0x1e3 (size before relaxing)
 
.debug_loc 0x00000000 0x2af1
*(.debug_loc)
.debug_loc 0x00000000 0x63f main.o
.debug_loc 0x0000063f 0x1f49 tff.o
.debug_loc 0x00002588 0x569 mmc.o
 
.debug_macinfo
*(.debug_macinfo)
OUTPUT(glg.elf elf32-avr)
LOAD linker stubs
 
.debug_ranges 0x00000000 0x1d0
.debug_ranges 0x00000000 0x30 main.o
.debug_ranges 0x00000030 0x170 tff.o
.debug_ranges 0x000001a0 0x30 mmc.o
/Designs/Data_loggers/GPSRL03A/Makefile
0,0 → 1,52
PRG = glg
OBJ = main.o tff.o mmc.o
MCU_TARGET = atmega168
OPTIMIZE = -Os -mcall-prologues
DEFS =
LIBS =
DEBUG = dwarf-2
 
CC = avr-gcc
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
ALL_ASFLAGS = -mmcu=$(MCU_TARGET) -I. -x assembler-with-cpp $(ASFLAGS)
CFLAGS = -g$(DEBUG) -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
LDFLAGS = -Wl,-Map,$(PRG).map
 
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
 
 
 
all: $(PRG).elf lst text size
 
$(PRG).elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
 
 
clean:
rm -rf *.o $(PRG).elf *.eps *.bak *.a
rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
rm -rf $(PRG).hex
 
 
 
size: $(PRG).elf
$(SIZE) $(PRG).elf
 
lst: $(PRG).lst
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
 
%.o : %.S
$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 
 
text: hex
hex: $(PRG).hex
 
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
 
 
/Designs/Data_loggers/GPSRL03A/diskio.h
0,0 → 1,64
/*-----------------------------------------------------------------------
/ Low level disk interface modlue include file R0.04a (C)ChaN, 2007
/-----------------------------------------------------------------------*/
 
#ifndef _DISKIO
 
#define _READONLY 0 /* 1: Read-only mode */
 
#include "integer.h"
 
 
/* Status of Disk Functions */
typedef BYTE DSTATUS;
 
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
 
 
/*---------------------------------------*/
/* Prototypes for disk control functions */
 
DSTATUS disk_initialize (BYTE);
DSTATUS disk_status (BYTE);
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
#if _READONLY == 0
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
#endif
DRESULT disk_ioctl (BYTE, BYTE, void*);
void disk_timerproc (void);
 
 
 
 
/* Disk Status Bits (DSTATUS) */
 
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
 
 
/* Command code for disk_ioctrl() */
 
#define GET_SECTOR_COUNT 1
#define GET_SECTOR_SIZE 2
#define CTRL_SYNC 3
#define CTRL_POWER 4
#define CTRL_LOCK 5
#define CTRL_EJECT 6
#define MMC_GET_CSD 10
#define MMC_GET_CID 11
#define MMC_GET_OCR 12
#define ATA_GET_REV 20
#define ATA_GET_MODEL 21
#define ATA_GET_SN 22
 
 
#define _DISKIO
#endif
/Designs/Data_loggers/GPSRL03A/ff.c
0,0 → 1,2036
/*----------------------------------------------------------------------------/
/ FatFs - FAT file system module R0.06 (C)ChaN, 2008
/-----------------------------------------------------------------------------/
/ The FatFs module is an experimenal project to implement FAT file system to
/ cheap microcontrollers. This is a free software and is opened for education,
/ research and development under license policy of following trems.
/
/ Copyright (C) 2008, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is no warranty.
/ * You can use, modify and/or redistribute it for personal, non-profit or
/ commercial use without restriction under your responsibility.
/ * Redistributions of source code must retain the above copyright notice.
/
/-----------------------------------------------------------------------------/
/ Feb 26,'06 R0.00 Prototype.
/
/ Apr 29,'06 R0.01 First stable version.
/
/ Jun 01,'06 R0.02 Added FAT12 support.
/ Removed unbuffered mode.
/ Fixed a problem on small (<32M) patition.
/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM).
/
/ Sep 22,'06 R0.03 Added f_rename().
/ Changed option _FS_MINIMUM to _FS_MINIMIZE.
/ Dec 11,'06 R0.03a Improved cluster scan algolithm to write files fast.
/ Fixed f_mkdir() creates incorrect directory on FAT32.
/
/ Feb 04,'07 R0.04 Supported multiple drive system.
/ Changed some interfaces for multiple drive system.
/ Changed f_mountdrv() to f_mount().
/ Added f_mkfs().
/ Apr 01,'07 R0.04a Supported multiple partitions on a plysical drive.
/ Added a capability of extending file size to f_lseek().
/ Added minimization level 3.
/ Fixed an endian sensitive code in f_mkfs().
/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.
/ Added FSInfo support.
/ Fixed DBCS name can result FR_INVALID_NAME.
/ Fixed short seek (<= csize) collapses the file object.
/
/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs().
/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo.
/ Fixed f_mkdir() on FAT32 creates incorrect directory.
/ Feb 03,'08 R0.05a Added f_truncate() and f_utime().
/ Fixed off by one error at FAT sub-type determination.
/ Fixed btr in f_read() can be mistruncated.
/ Fixed cached sector is not flushed when create and close
/ without write.
/
/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets().
/ Improved performance of f_lseek() on moving to the same
/ or following cluster.
/---------------------------------------------------------------------------*/
 
#include <string.h>
#include "ff.h" /* FatFs declarations */
#include "diskio.h" /* Include file for user provided disk functions */
 
 
/*--------------------------------------------------------------------------
 
Module Private Functions
 
---------------------------------------------------------------------------*/
 
static
FATFS *FatFs[_DRIVES]; /* Pointer to the file system objects (logical drives) */
static
WORD fsid; /* File system mount ID */
 
 
 
/*-----------------------------------------------------------------------*/
/* Change window offset */
/*-----------------------------------------------------------------------*/
 
static
BOOL move_window ( /* TRUE: successful, FALSE: failed */
FATFS *fs, /* File system object */
DWORD sector /* Sector number to make apperance in the fs->win[] */
) /* Move to zero only writes back dirty window */
{
DWORD wsect;
 
 
wsect = fs->winsect;
if (wsect != sector) { /* Changed current window */
#if !_FS_READONLY
BYTE n;
if (fs->winflag) { /* Write back dirty window if needed */
if (disk_write(fs->drive, fs->win, wsect, 1) != RES_OK)
return FALSE;
fs->winflag = 0;
if (wsect < (fs->fatbase + fs->sects_fat)) { /* In FAT area */
for (n = fs->n_fats; n >= 2; n--) { /* Refrect the change to FAT copy */
wsect += fs->sects_fat;
disk_write(fs->drive, fs->win, wsect, 1);
}
}
}
#endif
if (sector) {
if (disk_read(fs->drive, fs->win, sector, 1) != RES_OK)
return FALSE;
fs->winsect = sector;
}
}
return TRUE;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Clean-up cached data */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
FRESULT sync ( /* FR_OK: successful, FR_RW_ERROR: failed */
FATFS *fs /* File system object */
)
{
fs->winflag = 1;
if (!move_window(fs, 0)) return FR_RW_ERROR;
#if _USE_FSINFO
/* Update FSInfo sector if needed */
if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {
fs->winsect = 0;
memset(fs->win, 0, 512);
ST_WORD(&fs->win[BS_55AA], 0xAA55);
ST_DWORD(&fs->win[FSI_LeadSig], 0x41615252);
ST_DWORD(&fs->win[FSI_StrucSig], 0x61417272);
ST_DWORD(&fs->win[FSI_Free_Count], fs->free_clust);
ST_DWORD(&fs->win[FSI_Nxt_Free], fs->last_clust);
disk_write(fs->drive, fs->win, fs->fsi_sector, 1);
fs->fsi_flag = 0;
}
#endif
/* Make sure that no pending write process in the physical drive */
if (disk_ioctl(fs->drive, CTRL_SYNC, NULL) != RES_OK)
return FR_RW_ERROR;
return FR_OK;
}
#endif
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Get a cluster status */
/*-----------------------------------------------------------------------*/
 
static
DWORD get_cluster ( /* 0,>=2: successful, 1: failed */
FATFS *fs, /* File system object */
DWORD clust /* Cluster# to get the link information */
)
{
WORD wc, bc;
DWORD fatsect;
 
 
if (clust >= 2 && clust < fs->max_clust) { /* Is it a valid cluster#? */
fatsect = fs->fatbase;
switch (fs->fs_type) {
case FS_FAT12 :
bc = (WORD)clust * 3 / 2;
if (!move_window(fs, fatsect + (bc / SS(fs)))) break;
wc = fs->win[bc & (SS(fs) - 1)]; bc++;
if (!move_window(fs, fatsect + (bc / SS(fs)))) break;
wc |= (WORD)fs->win[bc & (SS(fs) - 1)] << 8;
return (clust & 1) ? (wc >> 4) : (wc & 0xFFF);
 
case FS_FAT16 :
if (!move_window(fs, fatsect + (clust / (SS(fs) / 2)))) break;
return LD_WORD(&fs->win[((WORD)clust * 2) & (SS(fs) - 1)]);
 
case FS_FAT32 :
if (!move_window(fs, fatsect + (clust / (SS(fs) / 4)))) break;
return LD_DWORD(&fs->win[((WORD)clust * 4) & (SS(fs) - 1)]) & 0x0FFFFFFF;
}
}
 
return 1; /* Out of cluster range, or an error occured */
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Change a cluster status */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
BOOL put_cluster ( /* TRUE: successful, FALSE: failed */
FATFS *fs, /* File system object */
DWORD clust, /* Cluster# to change (must be 2 to fs->max_clust-1) */
DWORD val /* New value to mark the cluster */
)
{
WORD bc;
BYTE *p;
DWORD fatsect;
 
 
fatsect = fs->fatbase;
switch (fs->fs_type) {
case FS_FAT12 :
bc = (WORD)clust * 3 / 2;
if (!move_window(fs, fatsect + (bc / SS(fs)))) return FALSE;
p = &fs->win[bc & (SS(fs) - 1)];
*p = (clust & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
bc++;
fs->winflag = 1;
if (!move_window(fs, fatsect + (bc / SS(fs)))) return FALSE;
p = &fs->win[bc & (SS(fs) - 1)];
*p = (clust & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
break;
 
case FS_FAT16 :
if (!move_window(fs, fatsect + (clust / (SS(fs) / 2)))) return FALSE;
ST_WORD(&fs->win[((WORD)clust * 2) & (SS(fs) - 1)], (WORD)val);
break;
 
case FS_FAT32 :
if (!move_window(fs, fatsect + (clust / (SS(fs) / 4)))) return FALSE;
ST_DWORD(&fs->win[((WORD)clust * 4) & (SS(fs) - 1)], val);
break;
 
default :
return FALSE;
}
fs->winflag = 1;
return TRUE;
}
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Remove a cluster chain */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
BOOL remove_chain ( /* TRUE: successful, FALSE: failed */
FATFS *fs, /* File system object */
DWORD clust /* Cluster# to remove chain from */
)
{
DWORD nxt;
 
 
while (clust >= 2 && clust < fs->max_clust) {
nxt = get_cluster(fs, clust);
if (nxt == 1) return FALSE;
if (!put_cluster(fs, clust, 0)) return FALSE;
if (fs->free_clust != 0xFFFFFFFF) {
fs->free_clust++;
#if _USE_FSINFO
fs->fsi_flag = 1;
#endif
}
clust = nxt;
}
return TRUE;
}
#endif
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Stretch or create a cluster chain */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
DWORD create_chain ( /* 0: No free cluster, 1: Error, >=2: New cluster number */
FATFS *fs, /* File system object */
DWORD clust /* Cluster# to stretch, 0 means create new */
)
{
DWORD cstat, ncl, scl, mcl = fs->max_clust;
 
 
if (clust == 0) { /* Create new chain */
scl = fs->last_clust; /* Get suggested start point */
if (scl == 0 || scl >= mcl) scl = 1;
}
else { /* Stretch existing chain */
cstat = get_cluster(fs, clust); /* Check the cluster status */
if (cstat < 2) return 1; /* It is an invalid cluster */
if (cstat < mcl) return cstat; /* It is already followed by next cluster */
scl = clust;
}
 
ncl = scl; /* Start cluster */
for (;;) {
ncl++; /* Next cluster */
if (ncl >= mcl) { /* Wrap around */
ncl = 2;
if (ncl > scl) return 0; /* No free custer */
}
cstat = get_cluster(fs, ncl); /* Get the cluster status */
if (cstat == 0) break; /* Found a free cluster */
if (cstat == 1) return 1; /* Any error occured */
if (ncl == scl) return 0; /* No free custer */
}
 
if (!put_cluster(fs, ncl, 0x0FFFFFFF)) return 1; /* Mark the new cluster "in use" */
if (clust != 0 && !put_cluster(fs, clust, ncl)) return 1; /* Link it to previous one if needed */
 
fs->last_clust = ncl; /* Update fsinfo */
if (fs->free_clust != 0xFFFFFFFF) {
fs->free_clust--;
#if _USE_FSINFO
fs->fsi_flag = 1;
#endif
}
 
return ncl; /* Return new cluster number */
}
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Get sector# from cluster# */
/*-----------------------------------------------------------------------*/
 
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
FATFS *fs, /* File system object */
DWORD clust /* Cluster# to be converted */
)
{
clust -= 2;
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
return clust * fs->csize + fs->database;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Move directory pointer to next */
/*-----------------------------------------------------------------------*/
 
static
BOOL next_dir_entry ( /* TRUE: successful, FALSE: could not move next */
DIR *dj /* Pointer to directory object */
)
{
DWORD clust;
WORD idx;
 
 
idx = dj->index + 1;
if ((idx & ((SS(dj->fs) - 1) / 32)) == 0) { /* Table sector changed? */
dj->sect++; /* Next sector */
if (dj->clust == 0) { /* In static table */
if (idx >= dj->fs->n_rootdir) return FALSE; /* Reached to end of table */
} else { /* In dynamic table */
if (((idx / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */
clust = get_cluster(dj->fs, dj->clust); /* Get next cluster */
if (clust < 2 || clust >= dj->fs->max_clust) /* Reached to end of table */
return FALSE;
dj->clust = clust; /* Initialize for new cluster */
dj->sect = clust2sect(dj->fs, clust);
}
}
}
dj->index = idx; /* Lower several bits of dj->index indicates offset in dj->sect */
return TRUE;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Get file status from directory entry */
/*-----------------------------------------------------------------------*/
 
#if _FS_MINIMIZE <= 1
static
void get_fileinfo ( /* No return code */
FILINFO *finfo, /* Ptr to store the file information */
const BYTE *dir /* Ptr to the directory entry */
)
{
BYTE n, c, a;
char *p;
 
 
p = &finfo->fname[0];
a = _USE_NTFLAG ? dir[DIR_NTres] : 0; /* NT flag */
for (n = 0; n < 8; n++) { /* Convert file name (body) */
c = dir[n];
if (c == ' ') break;
if (c == 0x05) c = 0xE5;
if (a & 0x08 && c >= 'A' && c <= 'Z') c += 0x20;
*p++ = c;
}
if (dir[8] != ' ') { /* Convert file name (extension) */
*p++ = '.';
for (n = 8; n < 11; n++) {
c = dir[n];
if (c == ' ') break;
if (a & 0x10 && c >= 'A' && c <= 'Z') c += 0x20;
*p++ = c;
}
}
*p = '\0';
 
finfo->fattrib = dir[DIR_Attr]; /* Attribute */
finfo->fsize = LD_DWORD(&dir[DIR_FileSize]); /* Size */
finfo->fdate = LD_WORD(&dir[DIR_WrtDate]); /* Date */
finfo->ftime = LD_WORD(&dir[DIR_WrtTime]); /* Time */
}
#endif /* _FS_MINIMIZE <= 1 */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Pick a paragraph and create the name in format of directory entry */
/*-----------------------------------------------------------------------*/
 
static
char make_dirfile ( /* 1: error - detected an invalid format, '\0'or'/': next character */
const char **path, /* Pointer to the file path pointer */
char *dirname /* Pointer to directory name buffer {Name(8), Ext(3), NT flag(1)} */
)
{
BYTE n, t, c, a, b;
 
 
memset(dirname, ' ', 8+3); /* Fill buffer with spaces */
a = 0; b = 0x18; /* NT flag */
n = 0; t = 8;
for (;;) {
c = *(*path)++;
if (c == '\0' || c == '/') { /* Reached to end of str or directory separator */
if (n == 0) break;
dirname[11] = _USE_NTFLAG ? (a & b) : 0;
return c;
}
if (c <= ' ' || c == 0x7F) break; /* Reject invisible chars */
if (c == '.') {
if (!(a & 1) && n >= 1 && n <= 8) { /* Enter extension part */
n = 8; t = 11; continue;
}
break;
}
if (_USE_SJIS &&
((c >= 0x81 && c <= 0x9F) || /* Accept S-JIS code */
(c >= 0xE0 && c <= 0xFC))) {
if (n == 0 && c == 0xE5) /* Change heading \xE5 to \x05 */
c = 0x05;
a ^= 0x01; goto md_l2;
}
if (c == '"') break; /* Reject " */
if (c <= ')') goto md_l1; /* Accept ! # $ % & ' ( ) */
if (c <= ',') break; /* Reject * + , */
if (c <= '9') goto md_l1; /* Accept - 0-9 */
if (c <= '?') break; /* Reject : ; < = > ? */
if (!(a & 1)) { /* These checks are not applied to S-JIS 2nd byte */
if (c == '|') break; /* Reject | */
if (c >= '[' && c <= ']') break;/* Reject [ \ ] */
if (_USE_NTFLAG && c >= 'A' && c <= 'Z')
(t == 8) ? (b &= 0xF7) : (b &= 0xEF);
if (c >= 'a' && c <= 'z') { /* Convert to upper case */
c -= 0x20;
if (_USE_NTFLAG) (t == 8) ? (a |= 0x08) : (a |= 0x10);
}
}
md_l1:
a &= 0xFE;
md_l2:
if (n >= t) break;
dirname[n++] = c;
}
return 1;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Trace a file path */
/*-----------------------------------------------------------------------*/
 
static
FRESULT trace_path ( /* FR_OK(0): successful, !=0: error code */
DIR *dj, /* Pointer to directory object to return last directory */
char *fn, /* Pointer to last segment name to return {file(8),ext(3),attr(1)} */
const char *path, /* Full-path string to trace a file or directory */
BYTE **dir /* Pointer to pointer to found entry to retutn */
)
{
DWORD clust;
char ds;
BYTE *dptr = NULL;
FATFS *fs = dj->fs;
 
 
/* Initialize directory object */
clust = fs->dirbase;
if (fs->fs_type == FS_FAT32) {
dj->clust = dj->sclust = clust;
dj->sect = clust2sect(fs, clust);
} else {
dj->clust = dj->sclust = 0;
dj->sect = clust;
}
dj->index = 0;
 
if (*path == '\0') { /* Null path means the root directory */
*dir = NULL; return FR_OK;
}
 
for (;;) {
ds = make_dirfile(&path, fn); /* Get a paragraph into fn[] */
if (ds == 1) return FR_INVALID_NAME;
for (;;) {
if (!move_window(fs, dj->sect)) return FR_RW_ERROR;
dptr = &fs->win[(dj->index & ((SS(fs) - 1) / 32)) * 32]; /* Pointer to the directory entry */
if (dptr[DIR_Name] == 0) /* Has it reached to end of dir? */
return !ds ? FR_NO_FILE : FR_NO_PATH;
if (dptr[DIR_Name] != 0xE5 /* Matched? */
&& !(dptr[DIR_Attr] & AM_VOL)
&& !memcmp(&dptr[DIR_Name], fn, 8+3) ) break;
if (!next_dir_entry(dj)) /* Next directory pointer */
return !ds ? FR_NO_FILE : FR_NO_PATH;
}
if (!ds) { *dir = dptr; return FR_OK; } /* Matched with end of path */
if (!(dptr[DIR_Attr] & AM_DIR)) return FR_NO_PATH; /* Cannot trace because it is a file */
clust = ((DWORD)LD_WORD(&dptr[DIR_FstClusHI]) << 16) | LD_WORD(&dptr[DIR_FstClusLO]); /* Get cluster# of the directory */
dj->clust = dj->sclust = clust; /* Restart scanning at the new directory */
dj->sect = clust2sect(fs, clust);
dj->index = 2;
}
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Reserve a directory entry */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
FRESULT reserve_direntry ( /* FR_OK: successful, FR_DENIED: no free entry, FR_RW_ERROR: a disk error occured */
DIR *dj, /* Target directory to create new entry */
BYTE **dir /* Pointer to pointer to created entry to retutn */
)
{
DWORD clust, sector;
BYTE c, n, *dptr;
FATFS *fs = dj->fs;
 
 
/* Re-initialize directory object */
clust = dj->sclust;
if (clust != 0) { /* Dyanmic directory table */
dj->clust = clust;
dj->sect = clust2sect(fs, clust);
} else { /* Static directory table */
dj->sect = fs->dirbase;
}
dj->index = 0;
 
do {
if (!move_window(fs, dj->sect)) return FR_RW_ERROR;
dptr = &fs->win[(dj->index & ((SS(dj->fs) - 1) / 32)) * 32]; /* Pointer to the directory entry */
c = dptr[DIR_Name];
if (c == 0 || c == 0xE5) { /* Found an empty entry */
*dir = dptr; return FR_OK;
}
} while (next_dir_entry(dj)); /* Next directory pointer */
/* Reached to end of the directory table */
 
/* Abort when it is a static table or could not stretch dynamic table */
if (clust == 0 || !(clust = create_chain(fs, dj->clust))) return FR_DENIED;
if (clust == 1 || !move_window(fs, 0)) return FR_RW_ERROR;
 
/* Cleanup the expanded table */
fs->winsect = sector = clust2sect(fs, clust);
memset(fs->win, 0, SS(fs));
for (n = fs->csize; n; n--) {
if (disk_write(fs->drive, fs->win, sector, 1) != RES_OK)
return FR_RW_ERROR;
sector++;
}
fs->winflag = 1;
*dir = fs->win;
 
return FR_OK;
}
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Load boot record and check if it is an FAT boot record */
/*-----------------------------------------------------------------------*/
 
static
BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record or error */
FATFS *fs, /* File system object */
DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
)
{
if (disk_read(fs->drive, fs->win, sect, 1) != RES_OK) /* Load boot record */
return 2;
if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */
return 2;
 
if (!memcmp(&fs->win[BS_FilSysType], "FAT", 3)) /* Check FAT signature */
return 0;
if (!memcmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80))
return 0;
 
return 1;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Make sure that the file system is valid */
/*-----------------------------------------------------------------------*/
 
static
FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */
const char **path, /* Pointer to pointer to the path name (drive number) */
FATFS **rfs, /* Pointer to pointer to the found file system object */
BYTE chk_wp /* !=0: Check media write protection for write access */
)
{
BYTE drv, fmt, *tbl;
DSTATUS stat;
DWORD bootsect, fatsize, totalsect, maxclust;
const char *p = *path;
FATFS *fs;
 
 
/* Get drive number from the path name */
while (*p == ' ') p++; /* Strip leading spaces */
drv = p[0] - '0'; /* Is there a drive number? */
if (drv <= 9 && p[1] == ':')
p += 2; /* Found a drive number, get and strip it */
else
drv = 0; /* No drive number is given, use drive number 0 as default */
if (*p == '/') p++; /* Strip heading slash */
*path = p; /* Return pointer to the path name */
 
/* Check if the drive number is valid or not */
if (drv >= _DRIVES) return FR_INVALID_DRIVE; /* Is the drive number valid? */
*rfs = fs = FatFs[drv]; /* Returen pointer to the corresponding file system object */
if (!fs) return FR_NOT_ENABLED; /* Is the file system object registered? */
 
if (fs->fs_type) { /* If the logical drive has been mounted */
stat = disk_status(fs->drive);
if (!(stat & STA_NOINIT)) { /* and physical drive is kept initialized (has not been changed), */
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
#endif
return FR_OK; /* The file system object is valid */
}
}
 
/* The logical drive must be re-mounted. Following code attempts to mount the logical drive */
 
memset(fs, 0, sizeof(FATFS)); /* Clean-up the file system object */
fs->drive = LD2PD(drv); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->drive); /* Initialize low level disk I/O layer */
if (stat & STA_NOINIT) /* Check if the drive is ready */
return FR_NOT_READY;
#if S_MAX_SIZ > 512 /* Get disk sector size if needed */
if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > S_MAX_SIZ)
return FR_NO_FILESYSTEM;
#endif
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
#endif
/* Search FAT partition on the drive */
fmt = check_fs(fs, bootsect = 0); /* Check sector 0 as an SFD format */
if (fmt == 1) { /* Not an FAT boot record, it may be patitioned */
/* Check a partition listed in top of the partition table */
tbl = &fs->win[MBR_Table + LD2PT(drv) * 16]; /* Partition table */
if (tbl[4]) { /* Is the partition existing? */
bootsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */
fmt = check_fs(fs, bootsect); /* Check the partition */
}
}
if (fmt || LD_WORD(&fs->win[BPB_BytsPerSec]) != SS(fs)) /* No valid FAT patition is found */
return FR_NO_FILESYSTEM;
 
/* Initialize the file system object */
fatsize = LD_WORD(&fs->win[BPB_FATSz16]); /* Number of sectors per FAT */
if (!fatsize) fatsize = LD_DWORD(&fs->win[BPB_FATSz32]);
fs->sects_fat = fatsize;
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */
fatsize *= fs->n_fats; /* (Number of sectors in FAT area) */
fs->fatbase = bootsect + LD_WORD(&fs->win[BPB_RsvdSecCnt]); /* FAT start sector (lba) */
fs->csize = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
fs->n_rootdir = LD_WORD(&fs->win[BPB_RootEntCnt]); /* Nmuber of root directory entries */
totalsect = LD_WORD(&fs->win[BPB_TotSec16]); /* Number of sectors on the file system */
if (!totalsect) totalsect = LD_DWORD(&fs->win[BPB_TotSec32]);
fs->max_clust = maxclust = (totalsect /* max_clust = Last cluster# + 1 */
- LD_WORD(&fs->win[BPB_RsvdSecCnt]) - fatsize - fs->n_rootdir / (SS(fs)/32)
) / fs->csize + 2;
 
fmt = FS_FAT12; /* Determine the FAT sub type */
if (maxclust >= 0xFF7) fmt = FS_FAT16;
if (maxclust >= 0xFFF7) fmt = FS_FAT32;
 
if (fmt == FS_FAT32)
fs->dirbase = LD_DWORD(&fs->win[BPB_RootClus]); /* Root directory start cluster */
else
fs->dirbase = fs->fatbase + fatsize; /* Root directory start sector (lba) */
fs->database = fs->fatbase + fatsize + fs->n_rootdir / (SS(fs)/32); /* Data start sector (lba) */
 
#if !_FS_READONLY
/* Initialize allocation information */
fs->free_clust = 0xFFFFFFFF;
#if _USE_FSINFO
/* Get fsinfo if needed */
if (fmt == FS_FAT32) {
fs->fsi_sector = bootsect + LD_WORD(&fs->win[BPB_FSInfo]);
if (disk_read(fs->drive, fs->win, fs->fsi_sector, 1) == RES_OK &&
LD_WORD(&fs->win[BS_55AA]) == 0xAA55 &&
LD_DWORD(&fs->win[FSI_LeadSig]) == 0x41615252 &&
LD_DWORD(&fs->win[FSI_StrucSig]) == 0x61417272) {
fs->last_clust = LD_DWORD(&fs->win[FSI_Nxt_Free]);
fs->free_clust = LD_DWORD(&fs->win[FSI_Free_Count]);
}
}
#endif
#endif
 
fs->fs_type = fmt; /* FAT syb-type */
fs->id = ++fsid; /* File system mount ID */
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Check if the file/dir object is valid or not */
/*-----------------------------------------------------------------------*/
 
static
FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
const FATFS *fs, /* Pointer to the file system object */
WORD id /* Member id of the target object to be checked */
)
{
if (!fs || !fs->fs_type || fs->id != id)
return FR_INVALID_OBJECT;
if (disk_status(fs->drive) & STA_NOINIT)
return FR_NOT_READY;
 
return FR_OK;
}
 
 
 
 
/*--------------------------------------------------------------------------
 
Public Functions
 
--------------------------------------------------------------------------*/
 
 
 
/*-----------------------------------------------------------------------*/
/* Mount/Unmount a Locical Drive */
/*-----------------------------------------------------------------------*/
 
FRESULT f_mount (
BYTE drv, /* Logical drive number to be mounted/unmounted */
FATFS *fs /* Pointer to new file system object (NULL for unmount)*/
)
{
if (drv >= _DRIVES) return FR_INVALID_DRIVE;
 
if (FatFs[drv]) FatFs[drv]->fs_type = 0; /* Clear old object */
 
FatFs[drv] = fs; /* Register and clear new object */
if (fs) fs->fs_type = 0;
 
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Open or Create a File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_open (
FIL *fp, /* Pointer to the blank file object */
const char *path, /* Pointer to the file name */
BYTE mode /* Access mode and file open mode flags */
)
{
FRESULT res;
DIR dj;
BYTE *dir;
char fn[8+3+1];
 
 
fp->fs = NULL; /* Clear file object */
#if !_FS_READONLY
mode &= (FA_READ|FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW);
res = auto_mount(&path, &dj.fs, (BYTE)(mode & (FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)));
#else
mode &= FA_READ;
res = auto_mount(&path, &dj.fs, 0);
#endif
if (res != FR_OK) return res;
res = trace_path(&dj, fn, path, &dir); /* Trace the file path */
 
#if !_FS_READONLY
/* Create or Open a file */
if (mode & (FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)) {
DWORD ps, rs;
if (res != FR_OK) { /* No file, create new */
if (res != FR_NO_FILE) return res;
res = reserve_direntry(&dj, &dir);
if (res != FR_OK) return res;
memset(dir, 0, 32); /* Initialize the new entry with open name */
memcpy(&dir[DIR_Name], fn, 8+3);
dir[DIR_NTres] = fn[11];
mode |= FA_CREATE_ALWAYS;
}
else { /* Any object is already existing */
if (mode & FA_CREATE_NEW) /* Cannot create new */
return FR_EXIST;
if (!dir || (dir[DIR_Attr] & (AM_RDO|AM_DIR))) /* Cannot overwrite it (R/O or DIR) */
return FR_DENIED;
if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero if needed */
rs = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]); /* Get start cluster */
ST_WORD(&dir[DIR_FstClusHI], 0); /* cluster = 0 */
ST_WORD(&dir[DIR_FstClusLO], 0);
ST_DWORD(&dir[DIR_FileSize], 0); /* size = 0 */
dj.fs->winflag = 1;
ps = dj.fs->winsect; /* Remove the cluster chain */
if (!remove_chain(dj.fs, rs) || !move_window(dj.fs, ps))
return FR_RW_ERROR;
dj.fs->last_clust = rs - 1; /* Reuse the cluster hole */
}
}
if (mode & FA_CREATE_ALWAYS) {
dir[DIR_Attr] = 0; /* Reset attribute */
ps = get_fattime();
ST_DWORD(&dir[DIR_CrtTime], ps); /* Created time */
dj.fs->winflag = 1;
mode |= FA__WRITTEN; /* Set file changed flag */
}
}
/* Open an existing file */
else {
#endif /* !_FS_READONLY */
if (res != FR_OK) return res; /* Trace failed */
if (!dir || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */
return FR_NO_FILE;
#if !_FS_READONLY
if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
return FR_DENIED;
}
fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
#endif
fp->flag = mode; /* File access mode */
fp->org_clust = /* File start cluster */
((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]);
fp->fsize = LD_DWORD(&dir[DIR_FileSize]); /* File size */
fp->fptr = 0; fp->csect = 255; /* File pointer */
fp->curr_sect = 0;
fp->fs = dj.fs; fp->id = dj.fs->id; /* Owner file system object of the file */
 
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Read File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_read (
FIL *fp, /* Pointer to the file object */
void *buff, /* Pointer to data buffer */
UINT btr, /* Number of bytes to read */
UINT *br /* Pointer to number of bytes read */
)
{
FRESULT res;
DWORD clust, sect, remain;
UINT rcnt, cc;
BYTE *rbuff = buff;
 
 
*br = 0;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_READ)) return FR_DENIED; /* Check access mode */
remain = fp->fsize - fp->fptr;
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
 
for ( ; btr; /* Repeat until all data transferred */
rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */
clust = (fp->fptr == 0) ? /* On the top of the file? */
fp->org_clust : get_cluster(fp->fs, fp->curr_clust);
if (clust < 2 || clust >= fp->fs->max_clust) goto fr_error;
fp->curr_clust = clust; /* Update current cluster */
fp->csect = 0; /* Reset sector address in the cluster */
}
sect = clust2sect(fp->fs, fp->curr_clust) + fp->csect; /* Get current sector */
cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */
if (cc) { /* Read maximum contiguous sectors directly */
if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */
cc = fp->fs->csize - fp->csect;
if (disk_read(fp->fs->drive, rbuff, sect, (BYTE)cc) != RES_OK)
goto fr_error;
fp->csect += (BYTE)cc; /* Next sector address in the cluster */
rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
continue;
}
if (sect != fp->curr_sect) { /* Is window offset changed? */
#if !_FS_READONLY
if (fp->flag & FA__DIRTY) { /* Write back file I/O buffer if needed */
if (disk_write(fp->fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK)
goto fr_error;
fp->flag &= (BYTE)~FA__DIRTY;
}
#endif
if (disk_read(fp->fs->drive, fp->buffer, sect, 1) != RES_OK) /* Fill file I/O buffer with file data */
goto fr_error;
fp->curr_sect = sect;
}
fp->csect++; /* Next sector address in the cluster */
}
rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector from file I/O buffer */
if (rcnt > btr) rcnt = btr;
memcpy(rbuff, &fp->buffer[fp->fptr % SS(fp->fs)], rcnt);
}
 
return FR_OK;
 
fr_error: /* Abort this file due to an unrecoverable error */
fp->flag |= FA__ERROR;
return FR_RW_ERROR;
}
 
 
 
 
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Write File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_write (
FIL *fp, /* Pointer to the file object */
const void *buff, /* Pointer to the data to be written */
UINT btw, /* Number of bytes to write */
UINT *bw /* Pointer to number of bytes written */
)
{
FRESULT res;
DWORD clust, sect;
UINT wcnt, cc;
const BYTE *wbuff = buff;
 
 
*bw = 0;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
if (fp->fsize + btw < fp->fsize) return FR_OK; /* File size cannot reach 4GB */
 
for ( ; btw; /* Repeat until all data transferred */
wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */
if (fp->fptr == 0) { /* On the top of the file? */
clust = fp->org_clust; /* Follow from the origin */
if (clust == 0) /* When there is no cluster chain, */
fp->org_clust = clust = create_chain(fp->fs, 0); /* Create a new cluster chain */
} else { /* Middle or end of the file */
clust = create_chain(fp->fs, fp->curr_clust); /* Trace or streach cluster chain */
}
if (clust == 0) break; /* Could not allocate a new cluster (disk full) */
if (clust == 1 || clust >= fp->fs->max_clust) goto fw_error;
fp->curr_clust = clust; /* Update current cluster */
fp->csect = 0; /* Reset sector address in the cluster */
}
sect = clust2sect(fp->fs, fp->curr_clust) + fp->csect; /* Get current sector */
cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */
if (cc) { /* Write maximum contiguous sectors directly */
if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */
cc = fp->fs->csize - fp->csect;
if (disk_write(fp->fs->drive, wbuff, sect, (BYTE)cc) != RES_OK)
goto fw_error;
fp->csect += (BYTE)cc; /* Next sector address in the cluster */
wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
continue;
}
if (sect != fp->curr_sect) { /* Is window offset changed? */
if (fp->flag & FA__DIRTY) { /* Write back file I/O buffer if needed */
if (disk_write(fp->fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK)
goto fw_error;
fp->flag &= (BYTE)~FA__DIRTY;
}
if (fp->fptr < fp->fsize && /* Fill file I/O buffer with file data */
disk_read(fp->fs->drive, fp->buffer, sect, 1) != RES_OK)
goto fw_error;
fp->curr_sect = sect;
}
fp->csect++; /* Next sector address in the cluster */
}
wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Put partial sector into file I/O buffer */
if (wcnt > btw) wcnt = btw;
memcpy(&fp->buffer[fp->fptr % SS(fp->fs)], wbuff, wcnt);
fp->flag |= FA__DIRTY;
}
 
if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
fp->flag |= FA__WRITTEN; /* Set file changed flag */
return FR_OK;
 
fw_error: /* Abort this file due to an unrecoverable error */
fp->flag |= FA__ERROR;
return FR_RW_ERROR;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Synchronize the file object */
/*-----------------------------------------------------------------------*/
 
FRESULT f_sync (
FIL *fp /* Pointer to the file object */
)
{
FRESULT res;
DWORD tim;
BYTE *dir;
 
 
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
/* Write back data buffer if needed */
if (fp->flag & FA__DIRTY) {
if (disk_write(fp->fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK)
return FR_RW_ERROR;
fp->flag &= (BYTE)~FA__DIRTY;
}
/* Update the directory entry */
if (!move_window(fp->fs, fp->dir_sect))
return FR_RW_ERROR;
dir = fp->dir_ptr;
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
ST_DWORD(&dir[DIR_FileSize], fp->fsize); /* Update file size */
ST_WORD(&dir[DIR_FstClusLO], fp->org_clust); /* Update start cluster */
ST_WORD(&dir[DIR_FstClusHI], fp->org_clust >> 16);
tim = get_fattime(); /* Updated time */
ST_DWORD(&dir[DIR_WrtTime], tim);
fp->flag &= (BYTE)~FA__WRITTEN;
res = sync(fp->fs);
}
}
return res;
}
 
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Close File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_close (
FIL *fp /* Pointer to the file object to be closed */
)
{
FRESULT res;
 
 
#if !_FS_READONLY
res = f_sync(fp);
#else
res = validate(fp->fs, fp->id);
#endif
if (res == FR_OK) fp->fs = NULL;
return res;
}
 
 
 
 
#if _FS_MINIMIZE <= 2
/*-----------------------------------------------------------------------*/
/* Seek File R/W Pointer */
/*-----------------------------------------------------------------------*/
 
FRESULT f_lseek (
FIL *fp, /* Pointer to the file object */
DWORD ofs /* File pointer from top of file */
)
{
FRESULT res;
DWORD clust, csize, nsect, ifptr;
 
 
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR;
if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */
#if !_FS_READONLY
&& !(fp->flag & FA_WRITE)
#endif
) ofs = fp->fsize;
 
ifptr = fp->fptr;
fp->fptr = 0; fp->csect = 255;
nsect = 0;
if (ofs > 0) {
csize = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */
if (ifptr > 0 &&
(ofs - 1) / csize >= (ifptr - 1) / csize) {/* When seek to same or following cluster, */
fp->fptr = (ifptr - 1) & ~(csize - 1); /* start from the current cluster */
ofs -= fp->fptr;
clust = fp->curr_clust;
} else { /* When seek to back cluster, */
clust = fp->org_clust; /* start from the first cluster */
#if !_FS_READONLY
if (clust == 0) { /* If no cluster chain, create a new chain */
clust = create_chain(fp->fs, 0);
if (clust == 1) goto fk_error;
fp->org_clust = clust;
}
#endif
fp->curr_clust = clust;
}
if (clust != 0) {
while (ofs > csize) { /* Cluster following loop */
#if !_FS_READONLY
if (fp->flag & FA_WRITE) { /* Check if in write mode or not */
clust = create_chain(fp->fs, clust); /* Force streached if in write mode */
if (clust == 0) { /* When disk gets full, clip file size */
ofs = csize; break;
}
} else
#endif
clust = get_cluster(fp->fs, clust); /* Follow cluster chain if not in write mode */
if (clust < 2 || clust >= fp->fs->max_clust) goto fk_error;
fp->curr_clust = clust;
fp->fptr += csize;
ofs -= csize;
}
fp->fptr += ofs;
fp->csect = (BYTE)(ofs / SS(fp->fs)); /* Sector offset in the cluster */
if (ofs & (SS(fp->fs) - 1)) {
nsect = clust2sect(fp->fs, clust) + fp->csect; /* Current sector */
fp->csect++;
}
}
}
if (nsect && nsect != fp->curr_sect) {
#if !_FS_READONLY
if (fp->flag & FA__DIRTY) { /* Write-back dirty buffer if needed */
if (disk_write(fp->fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK)
goto fk_error;
fp->flag &= (BYTE)~FA__DIRTY;
}
#endif
if (disk_read(fp->fs->drive, fp->buffer, nsect, 1) != RES_OK)
goto fk_error;
fp->curr_sect = nsect;
}
 
#if !_FS_READONLY
if (fp->fptr > fp->fsize) { /* Set changed flag if the file was extended */
fp->fsize = fp->fptr;
fp->flag |= FA__WRITTEN;
}
#endif
 
return FR_OK;
 
fk_error: /* Abort this file due to an unrecoverable error */
fp->flag |= FA__ERROR;
return FR_RW_ERROR;
}
 
 
 
 
#if _FS_MINIMIZE <= 1
/*-----------------------------------------------------------------------*/
/* Create a directroy object */
/*-----------------------------------------------------------------------*/
 
FRESULT f_opendir (
DIR *dj, /* Pointer to directory object to create */
const char *path /* Pointer to the directory path */
)
{
FRESULT res;
BYTE *dir;
char fn[8+3+1];
 
 
res = auto_mount(&path, &dj->fs, 0);
if (res == FR_OK) {
res = trace_path(dj, fn, path, &dir); /* Trace the directory path */
if (res == FR_OK) { /* Trace completed */
if (dir) { /* It is not the root dir */
if (dir[DIR_Attr] & AM_DIR) { /* The entry is a directory */
dj->clust = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]);
dj->sect = clust2sect(dj->fs, dj->clust);
dj->index = 2;
} else { /* The entry is not a directory */
res = FR_NO_FILE;
}
}
dj->id = dj->fs->id;
}
}
 
return res;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Read Directory Entry in Sequense */
/*-----------------------------------------------------------------------*/
 
FRESULT f_readdir (
DIR *dj, /* Pointer to the directory object */
FILINFO *finfo /* Pointer to file information to return */
)
{
BYTE *dir, c, res;
 
 
res = validate(dj->fs, dj->id); /* Check validity of the object */
if (res != FR_OK) return res;
 
finfo->fname[0] = 0;
while (dj->sect) {
if (!move_window(dj->fs, dj->sect))
return FR_RW_ERROR;
dir = &dj->fs->win[(dj->index & ((SS(dj->fs) - 1) >> 5)) * 32]; /* pointer to the directory entry */
c = dir[DIR_Name];
if (c == 0) break; /* Has it reached to end of dir? */
if (c != 0xE5 && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */
get_fileinfo(finfo, dir);
if (!next_dir_entry(dj)) dj->sect = 0; /* Next entry */
if (finfo->fname[0]) break; /* Found valid entry */
}
 
return FR_OK;
}
 
 
 
 
#if _FS_MINIMIZE == 0
/*-----------------------------------------------------------------------*/
/* Get File Status */
/*-----------------------------------------------------------------------*/
 
FRESULT f_stat (
const char *path, /* Pointer to the file path */
FILINFO *finfo /* Pointer to file information to return */
)
{
FRESULT res;
DIR dj;
BYTE *dir;
char fn[8+3+1];
 
 
res = auto_mount(&path, &dj.fs, 0);
if (res == FR_OK) {
res = trace_path(&dj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) { /* Trace completed */
if (dir) /* Found an object */
get_fileinfo(finfo, dir);
else /* It is root dir */
res = FR_INVALID_NAME;
}
}
 
return res;
}
 
 
 
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Truncate File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_truncate (
FIL *fp /* Pointer to the file object */
)
{
FRESULT res;
DWORD ncl;
 
 
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (res != FR_OK) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
 
if (fp->fsize > fp->fptr) {
fp->fsize = fp->fptr; /* Set file size to current R/W point */
fp->flag |= FA__WRITTEN;
if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */
if (!remove_chain(fp->fs, fp->org_clust)) goto ft_error;
fp->org_clust = 0;
} else { /* When truncate a part of the file, remove remaining clusters */
ncl = get_cluster(fp->fs, fp->curr_clust);
if (ncl < 2) goto ft_error;
if (ncl < fp->fs->max_clust) {
if (!put_cluster(fp->fs, fp->curr_clust, 0x0FFFFFFF)) goto ft_error;
if (!remove_chain(fp->fs, ncl)) goto ft_error;
}
}
}
 
return FR_OK;
 
ft_error: /* Abort this file due to an unrecoverable error */
fp->flag |= FA__ERROR;
return FR_RW_ERROR;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Get Number of Free Clusters */
/*-----------------------------------------------------------------------*/
 
FRESULT f_getfree (
const char *drv, /* Pointer to the logical drive number (root dir) */
DWORD *nclust, /* Pointer to the variable to return number of free clusters */
FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */
)
{
FRESULT res;
DWORD n, clust, sect;
BYTE fat, f, *p;
 
 
/* Get drive number */
res = auto_mount(&drv, fatfs, 0);
if (res != FR_OK) return res;
 
/* If number of free cluster is valid, return it without cluster scan. */
if ((*fatfs)->free_clust <= (*fatfs)->max_clust - 2) {
*nclust = (*fatfs)->free_clust;
return FR_OK;
}
 
/* Get number of free clusters */
fat = (*fatfs)->fs_type;
n = 0;
if (fat == FS_FAT12) {
clust = 2;
do {
if ((WORD)get_cluster(*fatfs, clust) == 0) n++;
} while (++clust < (*fatfs)->max_clust);
} else {
clust = (*fatfs)->max_clust;
sect = (*fatfs)->fatbase;
f = 0; p = 0;
do {
if (!f) {
if (!move_window(*fatfs, sect++)) return FR_RW_ERROR;
p = (*fatfs)->win;
}
if (fat == FS_FAT16) {
if (LD_WORD(p) == 0) n++;
p += 2; f += 1;
} else {
if (LD_DWORD(p) == 0) n++;
p += 4; f += 2;
}
} while (--clust);
}
(*fatfs)->free_clust = n;
#if _USE_FSINFO
if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
#endif
 
*nclust = n;
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Delete a File or Directory */
/*-----------------------------------------------------------------------*/
 
FRESULT f_unlink (
const char *path /* Pointer to the file or directory path */
)
{
FRESULT res;
DIR dj;
BYTE *dir, *sdir;
DWORD dclust, dsect;
char fn[8+3+1];
 
 
res = auto_mount(&path, &dj.fs, 1);
if (res != FR_OK) return res;
res = trace_path(&dj, fn, path, &dir); /* Trace the file path */
if (res != FR_OK) return res; /* Trace failed */
if (!dir) return FR_INVALID_NAME; /* It is the root directory */
if (dir[DIR_Attr] & AM_RDO) return FR_DENIED; /* It is a R/O object */
dsect = dj.fs->winsect;
dclust = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]);
 
if (dir[DIR_Attr] & AM_DIR) { /* It is a sub-directory */
dj.clust = dclust; /* Check if the sub-dir is empty or not */
dj.sect = clust2sect(dj.fs, dclust);
dj.index = 2;
do {
if (!move_window(dj.fs, dj.sect)) return FR_RW_ERROR;
sdir = &dj.fs->win[(dj.index & ((SS(dj.fs) - 1) >> 5)) * 32];
if (sdir[DIR_Name] == 0) break;
if (sdir[DIR_Name] != 0xE5 && !(sdir[DIR_Attr] & AM_VOL))
return FR_DENIED; /* The directory is not empty */
} while (next_dir_entry(&dj));
}
 
if (!move_window(dj.fs, dsect)) return FR_RW_ERROR; /* Mark the directory entry 'deleted' */
dir[DIR_Name] = 0xE5;
dj.fs->winflag = 1;
if (!remove_chain(dj.fs, dclust)) return FR_RW_ERROR; /* Remove the cluster chain */
 
return sync(dj.fs);
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Create a Directory */
/*-----------------------------------------------------------------------*/
 
FRESULT f_mkdir (
const char *path /* Pointer to the directory path */
)
{
FRESULT res;
DIR dj;
BYTE *dir, *fw, n;
char fn[8+3+1];
DWORD sect, dsect, dclust, pclust, tim;
 
 
res = auto_mount(&path, &dj.fs, 1);
if (res != FR_OK) return res;
res = trace_path(&dj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) return FR_EXIST; /* Any file or directory is already existing */
if (res != FR_NO_FILE) return res;
 
res = reserve_direntry(&dj, &dir); /* Reserve a directory entry */
if (res != FR_OK) return res;
sect = dj.fs->winsect;
dclust = create_chain(dj.fs, 0); /* Allocate a cluster for new directory table */
if (dclust == 1) return FR_RW_ERROR;
dsect = clust2sect(dj.fs, dclust);
if (!dsect) return FR_DENIED;
if (!move_window(dj.fs, dsect)) return FR_RW_ERROR;
 
fw = dj.fs->win;
memset(fw, 0, SS(dj.fs)); /* Clear the new directory table */
for (n = 1; n < dj.fs->csize; n++) {
if (disk_write(dj.fs->drive, fw, ++dsect, 1) != RES_OK)
return FR_RW_ERROR;
}
memset(&fw[DIR_Name], ' ', 8+3); /* Create "." entry */
fw[DIR_Name] = '.';
fw[DIR_Attr] = AM_DIR;
tim = get_fattime();
ST_DWORD(&fw[DIR_WrtTime], tim);
memcpy(&fw[32], &fw[0], 32); fw[33] = '.'; /* Create ".." entry */
ST_WORD(&fw[ DIR_FstClusLO], dclust);
ST_WORD(&fw[ DIR_FstClusHI], dclust >> 16);
pclust = dj.sclust;
if (dj.fs->fs_type == FS_FAT32 && pclust == dj.fs->dirbase) pclust = 0;
ST_WORD(&fw[32+DIR_FstClusLO], pclust);
ST_WORD(&fw[32+DIR_FstClusHI], pclust >> 16);
dj.fs->winflag = 1;
 
if (!move_window(dj.fs, sect)) return FR_RW_ERROR;
memset(&dir[0], 0, 32); /* Initialize the new entry */
memcpy(&dir[DIR_Name], fn, 8+3); /* Name */
dir[DIR_NTres] = fn[11];
dir[DIR_Attr] = AM_DIR; /* Attribute */
ST_DWORD(&dir[DIR_WrtTime], tim); /* Crated time */
ST_WORD(&dir[DIR_FstClusLO], dclust); /* Table start cluster */
ST_WORD(&dir[DIR_FstClusHI], dclust >> 16);
 
return sync(dj.fs);
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Change File Attribute */
/*-----------------------------------------------------------------------*/
 
FRESULT f_chmod (
const char *path, /* Pointer to the file path */
BYTE value, /* Attribute bits */
BYTE mask /* Attribute mask to change */
)
{
FRESULT res;
DIR dj;
BYTE *dir;
char fn[8+3+1];
 
 
res = auto_mount(&path, &dj.fs, 1);
if (res == FR_OK) {
res = trace_path(&dj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) { /* Trace completed */
if (!dir) {
res = FR_INVALID_NAME; /* Root directory */
} else {
mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */
dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
res = sync(dj.fs);
}
}
}
return res;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Change Timestamp */
/*-----------------------------------------------------------------------*/
 
FRESULT f_utime (
const char *path, /* Pointer to the file/directory name */
const FILINFO *finfo /* Pointer to the timestamp to be set */
)
{
FRESULT res;
DIR dj;
BYTE *dir;
char fn[8+3+1];
 
 
res = auto_mount(&path, &dj.fs, 1);
if (res == FR_OK) {
res = trace_path(&dj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) { /* Trace completed */
if (!dir) {
res = FR_INVALID_NAME; /* Root directory */
} else {
ST_WORD(&dir[DIR_WrtTime], finfo->ftime);
ST_WORD(&dir[DIR_WrtDate], finfo->fdate);
res = sync(dj.fs);
}
}
}
return res;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Rename File/Directory */
/*-----------------------------------------------------------------------*/
 
FRESULT f_rename (
const char *path_old, /* Pointer to the old name */
const char *path_new /* Pointer to the new name */
)
{
FRESULT res;
DIR dj;
DWORD sect_old;
BYTE *dir_old, *dir_new, direntry[32-11];
char fn[8+3+1];
 
 
res = auto_mount(&path_old, &dj.fs, 1);
if (res != FR_OK) return res;
 
res = trace_path(&dj, fn, path_old, &dir_old); /* Check old object */
if (res != FR_OK) return res; /* The old object is not found */
if (!dir_old) return FR_NO_FILE;
sect_old = dj.fs->winsect; /* Save the object information */
memcpy(direntry, &dir_old[DIR_Attr], 32-11);
 
res = trace_path(&dj, fn, path_new, &dir_new); /* Check new object */
if (res == FR_OK) return FR_EXIST; /* The new object name is already existing */
if (res != FR_NO_FILE) return res; /* Is there no old name? */
res = reserve_direntry(&dj, &dir_new); /* Reserve a directory entry */
if (res != FR_OK) return res;
 
memcpy(&dir_new[DIR_Attr], direntry, 32-11); /* Create new entry */
memcpy(&dir_new[DIR_Name], fn, 8+3);
dir_new[DIR_NTres] = fn[11];
dj.fs->winflag = 1;
 
if (!move_window(dj.fs, sect_old)) return FR_RW_ERROR; /* Delete old entry */
dir_old[DIR_Name] = 0xE5;
 
return sync(dj.fs);
}
 
#endif /* !_FS_READONLY */
#endif /* _FS_MINIMIZE == 0 */
#endif /* _FS_MINIMIZE <= 1 */
#endif /* _FS_MINIMIZE <= 2 */
 
 
 
#if _USE_MKFS && !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Create File System on the Drive */
/*-----------------------------------------------------------------------*/
#define N_ROOTDIR 512 /* Multiple of 32 and <= 2048 */
#define N_FATS 1 /* 1 or 2 */
#define MAX_SECTOR 64000000UL /* Maximum partition size */
#define MIN_SECTOR 2000UL /* Minimum partition size */
 
 
 
FRESULT f_mkfs (
BYTE drv, /* Logical drive number */
BYTE partition, /* Partitioning rule 0:FDISK, 1:SFD */
WORD allocsize /* Allocation unit size [bytes] */
)
{
BYTE fmt, m, *tbl;
DWORD b_part, b_fat, b_dir, b_data; /* Area offset (LBA) */
DWORD n_part, n_rsv, n_fat, n_dir; /* Area size */
DWORD n_clust, n;
FATFS *fs;
DSTATUS stat;
 
 
/* Check validity of the parameters */
if (drv >= _DRIVES) return FR_INVALID_DRIVE;
if (partition >= 2) return FR_MKFS_ABORTED;
for (n = 512; n <= 32768U && n != allocsize; n <<= 1);
if (n != allocsize) return FR_MKFS_ABORTED;
 
/* Check mounted drive and clear work area */
fs = FatFs[drv];
if (!fs) return FR_NOT_ENABLED;
fs->fs_type = 0;
drv = LD2PD(drv);
 
/* Get disk statics */
stat = disk_initialize(drv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_part) != RES_OK || n_part < MIN_SECTOR)
return FR_MKFS_ABORTED;
if (n_part > MAX_SECTOR) n_part = MAX_SECTOR;
b_part = (!partition) ? 63 : 0; /* Boot sector */
n_part -= b_part;
#if S_MAX_SIZ > 512 /* Check disk sector size */
if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK
|| SS(fs) > S_MAX_SIZ
|| SS(fs) > allocsize)
return FR_MKFS_ABORTED;
#endif
allocsize /= SS(fs); /* Number of sectors per cluster */
 
/* Pre-compute number of clusters and FAT type */
n_clust = n_part / allocsize;
fmt = FS_FAT12;
if (n_clust >= 0xFF5) fmt = FS_FAT16;
if (n_clust >= 0xFFF5) fmt = FS_FAT32;
 
/* Determine offset and size of FAT structure */
switch (fmt) {
case FS_FAT12:
n_fat = ((n_clust * 3 + 1) / 2 + 3 + SS(fs) - 1) / SS(fs);
n_rsv = 1 + partition;
n_dir = N_ROOTDIR * 32 / SS(fs);
break;
case FS_FAT16:
n_fat = ((n_clust * 2) + 4 + SS(fs) - 1) / SS(fs);
n_rsv = 1 + partition;
n_dir = N_ROOTDIR * 32 / SS(fs);
break;
default:
n_fat = ((n_clust * 4) + 8 + SS(fs) - 1) / SS(fs);
n_rsv = 33 - partition;
n_dir = 0;
}
b_fat = b_part + n_rsv; /* FATs start sector */
b_dir = b_fat + n_fat * N_FATS; /* Directory start sector */
b_data = b_dir + n_dir; /* Data start sector */
 
/* Align data start sector to erase block boundary (for flash memory media) */
if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK) return FR_MKFS_ABORTED;
n = (b_data + n - 1) & ~(n - 1);
n_fat += (n - b_data) / N_FATS;
/* b_dir and b_data are no longer used below */
 
/* Determine number of cluster and final check of validity of the FAT type */
n_clust = (n_part - n_rsv - n_fat * N_FATS - n_dir) / allocsize;
if ( (fmt == FS_FAT16 && n_clust < 0xFF5)
|| (fmt == FS_FAT32 && n_clust < 0xFFF5))
return FR_MKFS_ABORTED;
 
/* Create partition table if needed */
if (!partition) {
DWORD n_disk = b_part + n_part;
 
tbl = &fs->win[MBR_Table];
ST_DWORD(&tbl[0], 0x00010180); /* Partition start in CHS */
if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */
n_disk = n_disk / 63 / 255;
tbl[7] = (BYTE)n_disk;
tbl[6] = (BYTE)((n_disk >> 2) | 63);
} else {
ST_WORD(&tbl[6], 0xFFFF);
}
tbl[5] = 254;
if (fmt != FS_FAT32) /* System ID */
tbl[4] = (n_part < 0x10000) ? 0x04 : 0x06;
else
tbl[4] = 0x0c;
ST_DWORD(&tbl[8], 63); /* Partition start in LBA */
ST_DWORD(&tbl[12], n_part); /* Partition size in LBA */
ST_WORD(&tbl[64], 0xAA55); /* Signature */
if (disk_write(drv, fs->win, 0, 1) != RES_OK)
return FR_RW_ERROR;
}
 
/* Create boot record */
tbl = fs->win; /* Clear buffer */
memset(tbl, 0, SS(fs));
ST_DWORD(&tbl[BS_jmpBoot], 0x90FEEB); /* Boot code (jmp $, nop) */
ST_WORD(&tbl[BPB_BytsPerSec], SS(fs)); /* Sector size */
tbl[BPB_SecPerClus] = (BYTE)allocsize; /* Sectors per cluster */
ST_WORD(&tbl[BPB_RsvdSecCnt], n_rsv); /* Reserved sectors */
tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */
ST_WORD(&tbl[BPB_RootEntCnt], SS(fs) / 32 * n_dir); /* Number of rootdir entries */
if (n_part < 0x10000) { /* Number of total sectors */
ST_WORD(&tbl[BPB_TotSec16], n_part);
} else {
ST_DWORD(&tbl[BPB_TotSec32], n_part);
}
tbl[BPB_Media] = 0xF8; /* Media descripter */
ST_WORD(&tbl[BPB_SecPerTrk], 63); /* Number of sectors per track */
ST_WORD(&tbl[BPB_NumHeads], 255); /* Number of heads */
ST_DWORD(&tbl[BPB_HiddSec], b_part); /* Hidden sectors */
n = get_fattime(); /* Use current time as a VSN */
if (fmt != FS_FAT32) {
ST_DWORD(&tbl[BS_VolID], n); /* Volume serial number */
ST_WORD(&tbl[BPB_FATSz16], n_fat); /* Number of secters per FAT */
tbl[BS_DrvNum] = 0x80; /* Drive number */
tbl[BS_BootSig] = 0x29; /* Extended boot signature */
memcpy(&tbl[BS_VolLab], "NO NAME FAT ", 19); /* Volume lavel, FAT signature */
} else {
ST_DWORD(&tbl[BS_VolID32], n); /* Volume serial number */
ST_DWORD(&tbl[BPB_FATSz32], n_fat); /* Number of secters per FAT */
ST_DWORD(&tbl[BPB_RootClus], 2); /* Root directory cluster (2) */
ST_WORD(&tbl[BPB_FSInfo], 1); /* FSInfo record (bs+1) */
ST_WORD(&tbl[BPB_BkBootSec], 6); /* Backup boot record (bs+6) */
tbl[BS_DrvNum32] = 0x80; /* Drive number */
tbl[BS_BootSig32] = 0x29; /* Extended boot signature */
memcpy(&tbl[BS_VolLab32], "NO NAME FAT32 ", 19); /* Volume lavel, FAT signature */
}
ST_WORD(&tbl[BS_55AA], 0xAA55); /* Signature */
if (disk_write(drv, tbl, b_part+0, 1) != RES_OK)
return FR_RW_ERROR;
if (fmt == FS_FAT32)
disk_write(drv, tbl, b_part+6, 1);
 
/* Initialize FAT area */
for (m = 0; m < N_FATS; m++) {
memset(tbl, 0, SS(fs)); /* 1st sector of the FAT */
if (fmt != FS_FAT32) {
n = (fmt == FS_FAT12) ? 0x00FFFFF8 : 0xFFFFFFF8;
ST_DWORD(&tbl[0], n); /* Reserve cluster #0-1 (FAT12/16) */
} else {
ST_DWORD(&tbl[0], 0xFFFFFFF8); /* Reserve cluster #0-1 (FAT32) */
ST_DWORD(&tbl[4], 0xFFFFFFFF);
ST_DWORD(&tbl[8], 0x0FFFFFFF); /* Reserve cluster #2 for root dir */
}
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_RW_ERROR;
memset(tbl, 0, SS(fs)); /* Following FAT entries are filled by zero */
for (n = 1; n < n_fat; n++) {
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_RW_ERROR;
}
}
 
/* Initialize Root directory */
m = (BYTE)((fmt == FS_FAT32) ? allocsize : n_dir);
do {
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_RW_ERROR;
} while (--m);
 
/* Create FSInfo record if needed */
if (fmt == FS_FAT32) {
ST_WORD(&tbl[BS_55AA], 0xAA55);
ST_DWORD(&tbl[FSI_LeadSig], 0x41615252);
ST_DWORD(&tbl[FSI_StrucSig], 0x61417272);
ST_DWORD(&tbl[FSI_Free_Count], n_clust - 1);
ST_DWORD(&tbl[FSI_Nxt_Free], 0xFFFFFFFF);
disk_write(drv, tbl, b_part+1, 1);
disk_write(drv, tbl, b_part+7, 1);
}
 
return (disk_ioctl(drv, CTRL_SYNC, NULL) == RES_OK) ? FR_OK : FR_RW_ERROR;
}
 
#endif /* _USE_MKFS && !_FS_READONLY */
 
 
 
 
#if _USE_STRFUNC >= 1
/*-----------------------------------------------------------------------*/
/* Get a string from the file */
/*-----------------------------------------------------------------------*/
char* fgets (
char* buff, /* Pointer to the string buffer to read */
int len, /* Size of string buffer */
FIL* fil /* Pointer to the file object */
)
{
int i = 0;
char *p = buff;
UINT rc;
 
 
while (i < len - 1) { /* Read bytes until buffer gets filled */
f_read(fil, p, 1, &rc);
if (rc != 1) break; /* Break when no data to read */
#if _USE_STRFUNC >= 2
if (*p == '\r') continue; /* Strip '\r' */
#endif
i++;
if (*p++ == '\n') break; /* Break when reached end of line */
}
*p = 0;
return i ? buff : 0; /* When no data read (eof or error), return with error. */
}
 
 
 
#if !_FS_READONLY
#include <stdarg.h>
/*-----------------------------------------------------------------------*/
/* Put a character to the file */
/*-----------------------------------------------------------------------*/
int fputc (
int chr, /* A character to be output */
FIL* fil /* Ponter to the file object */
)
{
UINT bw;
char c;
 
 
#if _USE_STRFUNC >= 2
if (chr == '\n') fputc ('\r', fil); /* LF -> CRLF conversion */
#endif
if (!fil) { /* Special value may be used to switch the destination to any other device */
/* put_console(chr); */
return chr;
}
c = (char)chr;
f_write(fil, &c, 1, &bw); /* Write a byte to the file */
return bw ? chr : EOF; /* Return the resulut */
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Put a string to the file */
/*-----------------------------------------------------------------------*/
int fputs (
const char* str, /* Pointer to the string to be output */
FIL* fil /* Pointer to the file object */
)
{
int n;
 
 
for (n = 0; *str; str++, n++) {
if (fputc(*str, fil) == EOF) return EOF;
}
return n;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Put a formatted string to the file */
/*-----------------------------------------------------------------------*/
int fprintf (
FIL* fil, /* Pointer to the file object */
const char* str, /* Pointer to the format string */
... /* Optional arguments... */
)
{
va_list arp;
UCHAR c, f, r;
ULONG val;
char s[16];
int i, w, res, cc;
 
 
va_start(arp, str);
 
for (cc = res = 0; cc != EOF; res += cc) {
c = *str++;
if (c == 0) break; /* End of string */
if (c != '%') { /* Non escape cahracter */
cc = fputc(c, fil);
if (cc != EOF) cc = 1;
continue;
}
w = f = 0;
c = *str++;
if (c == '0') { /* Flag: '0' padding */
f = 1; c = *str++;
}
while (c >= '0' && c <= '9') { /* Precision */
w = w * 10 + (c - '0');
c = *str++;
}
if (c == 'l') { /* Prefix: Size is long int */
f |= 2; c = *str++;
}
if (c == 's') { /* Type is string */
cc = fputs(va_arg(arp, char*), fil);
continue;
}
if (c == 'c') { /* Type is character */
cc = fputc(va_arg(arp, char), fil);
if (cc != EOF) cc = 1;
continue;
}
r = 0;
if (c == 'd') r = 10; /* Type is signed decimal */
if (c == 'u') r = 10; /* Type is unsigned decimal */
if (c == 'X') r = 16; /* Type is unsigned hexdecimal */
if (r == 0) break; /* Unknown type */
if (f & 2) { /* Get the value */
val = (ULONG)va_arg(arp, long);
} else {
val = (c == 'd') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int);
}
/* Put numeral string */
if (c == 'd') {
if (val >= 0x80000000) {
val = 0 - val;
f |= 4;
}
}
i = sizeof(s) - 1; s[i] = 0;
do {
c = (UCHAR)(val % r + '0');
if (c > '9') c += 7;
s[--i] = c;
val /= r;
} while (i && val);
if (i && (f & 4)) s[--i] = '-';
w = sizeof(s) - 1 - w;
while (i && i > w) s[--i] = (f & 1) ? '0' : ' ';
cc = fputs(&s[i], fil);
}
 
va_end(arp);
return (cc == EOF) ? cc : res;
}
 
#endif /* !_FS_READONLY */
#endif /* _USE_STRFUNC >= 1*/
/Designs/Data_loggers/GPSRL03A/ff.h
0,0 → 1,339
/*--------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.06 (C)ChaN, 2008
/---------------------------------------------------------------------------/
/ FatFs module is an experimenal project to implement FAT file system to
/ cheap microcontrollers. This is a free software and is opened for education,
/ research and development under license policy of following trems.
/
/ Copyright (C) 2008, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is no warranty.
/ * You can use, modify and/or redistribute it for personal, non-profit or
/ commercial use without any restriction under your responsibility.
/ * Redistributions of source code must retain the above copyright notice.
/
/---------------------------------------------------------------------------*/
 
#ifndef _FATFS
 
#define _MCU_ENDIAN 0
/* The _MCU_ENDIAN defines which access method is used to the FAT structure.
/ 1: Enable word access.
/ 2: Disable word access and use byte-by-byte access instead.
/ When the architectural byte order of the MCU is big-endian and/or address
/ miss-aligned access results incorrect behavior, the _MCU_ENDIAN must be set to 2.
/ If it is not the case, it can also be set to 1 for good code efficiency. */
 
#define _FS_READONLY 0
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
 
#define _FS_MINIMIZE 0
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename are removed.
/ 2: f_opendir and f_readdir are removed in addition to level 1.
/ 3: f_lseek is removed in addition to level 2. */
 
#define _USE_STRFUNC 0
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
 
#define _USE_MKFS 0
/* When _USE_MKFS is set to 1 and _FS_READONLY is set to 0, f_mkfs function is
/ enabled. */
 
#define _DRIVES 2
/* Number of logical drives to be used. This affects the size of internal table. */
 
#define _MULTI_PARTITION 0
/* When _MULTI_PARTITION is set to 0, each logical drive is bound to same
/ physical drive number and can mount only 1st primaly partition. When it is
/ set to 1, each logical drive can mount a partition listed in Drives[]. */
 
#define _USE_FSINFO 0
/* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */
 
#define _USE_SJIS 1
/* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
/ only US-ASCII(7bit) code can be accepted as file/directory name. */
 
#define _USE_NTFLAG 1
/* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
/ Note that the files are always accessed in case insensitive. */
 
 
#include "integer.h"
 
 
 
/* Definitions corresponds to multiple sector size (not tested) */
#define S_MAX_SIZ 512U /* Do not change */
#if S_MAX_SIZ > 512U
#define SS(fs) ((fs)->s_size)
#else
#define SS(fs) 512U
#endif
 
 
/* File system object structure */
typedef struct _FATFS {
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries */
DWORD winsect; /* Current sector appearing in the win[] */
DWORD sects_fat; /* Sectors per fat */
DWORD max_clust; /* Maximum cluster# + 1 */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (cluster# for FAT32) */
DWORD database; /* Data start sector */
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
#if _USE_FSINFO
DWORD fsi_sector; /* fsinfo sector */
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
BYTE pad2;
#endif
#endif
BYTE fs_type; /* FAT sub type */
BYTE csize; /* Number of sectors per cluster */
#if S_MAX_SIZ > 512U
WORD s_size; /* Sector size */
#endif
BYTE n_fats; /* Number of FAT copies */
BYTE drive; /* Physical drive number */
BYTE winflag; /* win[] dirty flag (1:must be written back) */
BYTE pad1;
BYTE win[S_MAX_SIZ]; /* Disk access window for Directory/FAT */
} FATFS;
 
 
/* Directory object structure */
typedef struct _DIR {
WORD id; /* Owner file system mount ID */
WORD index; /* Current index */
FATFS* fs; /* Pointer to the owner file system object */
DWORD sclust; /* Start cluster */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
} DIR;
 
 
/* File object structure */
typedef struct _FIL {
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE csect; /* Sector address in the cluster */
FATFS* fs; /* Pointer to the owner file system object */
DWORD fptr; /* File R/W pointer */
DWORD fsize; /* File size */
DWORD org_clust; /* File start cluster */
DWORD curr_clust; /* Current cluster */
DWORD curr_sect; /* Current sector */
#if _FS_READONLY == 0
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
#endif
BYTE buffer[S_MAX_SIZ]; /* File R/W buffer */
} FIL;
 
 
/* File status structure */
typedef struct _FILINFO {
DWORD fsize; /* Size */
WORD fdate; /* Date */
WORD ftime; /* Time */
BYTE fattrib; /* Attribute */
char fname[8+1+3+1]; /* Name (8.3 format) */
} FILINFO;
 
 
 
/* Definitions corresponds to multi partition */
 
#if _MULTI_PARTITION != 0 /* Multiple partition cfg */
 
typedef struct _PARTITION {
BYTE pd; /* Physical drive # (0-255) */
BYTE pt; /* Partition # (0-3) */
} PARTITION;
extern
const PARTITION Drives[]; /* Logical drive# to physical location conversion table */
#define LD2PD(drv) (Drives[drv].pd) /* Get physical drive# */
#define LD2PT(drv) (Drives[drv].pt) /* Get partition# */
 
#else /* Single partition cfg */
 
#define LD2PD(drv) (drv) /* Physical drive# is equal to logical drive# */
#define LD2PT(drv) 0 /* Always mounts the 1st partition */
 
#endif
 
 
/* File function return code (FRESULT) */
 
typedef enum {
FR_OK = 0, /* 0 */
FR_NOT_READY, /* 1 */
FR_NO_FILE, /* 2 */
FR_NO_PATH, /* 3 */
FR_INVALID_NAME, /* 4 */
FR_INVALID_DRIVE, /* 5 */
FR_DENIED, /* 6 */
FR_EXIST, /* 7 */
FR_RW_ERROR, /* 8 */
FR_WRITE_PROTECTED, /* 9 */
FR_NOT_ENABLED, /* 10 */
FR_NO_FILESYSTEM, /* 11 */
FR_INVALID_OBJECT, /* 12 */
FR_MKFS_ABORTED /* 13 */
} FRESULT;
 
 
 
/*-----------------------------------------------------*/
/* FatFs module application interface */
 
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (DIR*, const char*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (const char*, FILINFO*); /* Get file status */
FRESULT f_getfree (const char*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
FRESULT f_truncate (FIL*); /* Truncate file */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const char*); /* Delete an existing file or directory */
FRESULT f_mkdir (const char*); /* Create a new directory */
FRESULT f_chmod (const char*, BYTE, BYTE); /* Change file/dir attriburte */
FRESULT f_utime (const char*, const FILINFO*); /* Change file/dir timestamp */
FRESULT f_rename (const char*, const char*); /* Rename/Move a file or directory */
FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */
#if _USE_STRFUNC
#define feof(fp) ((fp)->fptr == (fp)->fsize)
#define EOF -1
int fputc (int, FIL*); /* Put a character to the file */
int fputs (const char*, FIL*); /* Put a string to the file */
int fprintf (FIL*, const char*, ...); /* Put a formatted string to the file */
char* fgets (char*, int, FIL*); /* Get a string from the file */
#endif
 
/* User defined function to give a current time to fatfs module */
 
DWORD get_fattime (void); /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
 
 
 
/* File access control and file status flags (FIL.flag) */
 
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#if _FS_READONLY == 0
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
#define FA__ERROR 0x80
 
 
/* FAT sub type (FATFS.fs_type) */
 
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
 
 
/* File attribute bits for directory entry */
 
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
 
 
 
/* Offset of FAT structure members */
 
#define BS_jmpBoot 0
#define BS_OEMName 3
#define BPB_BytsPerSec 11
#define BPB_SecPerClus 13
#define BPB_RsvdSecCnt 14
#define BPB_NumFATs 16
#define BPB_RootEntCnt 17
#define BPB_TotSec16 19
#define BPB_Media 21
#define BPB_FATSz16 22
#define BPB_SecPerTrk 24
#define BPB_NumHeads 26
#define BPB_HiddSec 28
#define BPB_TotSec32 32
#define BS_55AA 510
 
#define BS_DrvNum 36
#define BS_BootSig 38
#define BS_VolID 39
#define BS_VolLab 43
#define BS_FilSysType 54
 
#define BPB_FATSz32 36
#define BPB_ExtFlags 40
#define BPB_FSVer 42
#define BPB_RootClus 44
#define BPB_FSInfo 48
#define BPB_BkBootSec 50
#define BS_DrvNum32 64
#define BS_BootSig32 66
#define BS_VolID32 67
#define BS_VolLab32 71
#define BS_FilSysType32 82
 
#define FSI_LeadSig 0
#define FSI_StrucSig 484
#define FSI_Free_Count 488
#define FSI_Nxt_Free 492
 
#define MBR_Table 446
 
#define DIR_Name 0
#define DIR_Attr 11
#define DIR_NTres 12
#define DIR_CrtTime 14
#define DIR_CrtDate 16
#define DIR_FstClusHI 20
#define DIR_WrtTime 22
#define DIR_WrtDate 24
#define DIR_FstClusLO 26
#define DIR_FileSize 28
 
 
 
/* Multi-byte word access macros */
 
#if _MCU_ENDIAN == 1 /* Use word access */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#elif _MCU_ENDIAN == 2 /* Use byte-by-byte access */
#define LD_WORD(ptr) (WORD)(((WORD)*(volatile BYTE*)((ptr)+1)<<8)|(WORD)*(volatile BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(volatile BYTE*)((ptr)+3)<<24)|((DWORD)*(volatile BYTE*)((ptr)+2)<<16)|((WORD)*(volatile BYTE*)((ptr)+1)<<8)|*(volatile BYTE*)(ptr))
#define ST_WORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(volatile BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(volatile BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
#else
#error Do not forget to set _MCU_ENDIAN properly!
#endif
 
 
#define _FATFS
#endif /* _FATFS */
/Designs/Data_loggers/GPSRL03A/glg_sch.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/Designs/Data_loggers/GPSRL03A/integer.h
0,0 → 1,23
#ifndef _INTEGER
 
typedef int INT;
typedef unsigned int UINT;
 
typedef char CHAR;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
 
typedef short SHORT;
typedef unsigned short USHORT;
typedef unsigned short WORD;
 
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long DWORD;
 
typedef unsigned char BOOL;
#define FALSE 0
#define TRUE 1
 
#define _INTEGER
#endif
/Designs/Data_loggers/GPSRL03A/mmc.c
0,0 → 1,487
/*-----------------------------------------------------------------------*/
/* MMC/SDC (in SPI mode) control module (C)ChaN, 2006 */
/*-----------------------------------------------------------------------*/
/* Only rcvr_spi(), xmit_spi(), disk_timerproc(), disk_initialize () and */
/* some macros are platform dependent. */
/*-----------------------------------------------------------------------*/
 
 
#include <avr/io.h>
#include "diskio.h"
 
 
/* Definitions for MMC/SDC command */
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
#define CMD1 (0x40+1) /* SEND_OP_COND */
#define CMD8 (0x40+8) /* SEND_IF_COND */
#define CMD9 (0x40+9) /* SEND_CSD */
#define CMD10 (0x40+10) /* SEND_CID */
#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (0x40+23) /* SET_BLOCK_COUNT */
#define CMD24 (0x40+24) /* WRITE_BLOCK */
#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
#define CMD41 (0x40+41) /* SEND_OP_COND (ACMD) */
#define CMD55 (0x40+55) /* APP_CMD */
#define CMD58 (0x40+58) /* READ_OCR */
 
 
/* Control signals (Platform dependent) */
#define SELECT() PORTB &= ~_BV(PB2) /* MMC CS = L */
#define DESELECT() PORTB |= _BV(PB2) /* MMC CS = H */
 
#define SOCKPORT PINB /* Socket contact port */
#define SOCKINS 0x01 /* Card detect switch (PB0) */
 
 
 
/*--------------------------------------------------------------------------
 
Module Private Functions
 
---------------------------------------------------------------------------*/
 
static volatile
DSTATUS Stat = STA_NOINIT; /* Disk status */
 
static volatile
BYTE Timer1, Timer2; /* 100Hz decrement timer */
 
static
BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */
 
 
 
/*-----------------------------------------------------------------------*/
/* Transmit a byte to MMC via SPI (Platform dependent) */
/*-----------------------------------------------------------------------*/
 
#define xmit_spi(dat) SPDR=(dat); loop_until_bit_is_set(SPSR,SPIF)
 
 
 
/*-----------------------------------------------------------------------*/
/* Receive a byte from MMC via SPI (Platform dependent) */
/*-----------------------------------------------------------------------*/
 
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
loop_until_bit_is_set(SPSR, SPIF);
return SPDR;
}
 
/* Alternative macro to receive data fast */
#define rcvr_spi_m(dst) SPDR=0xFF; loop_until_bit_is_set(SPSR,SPIF); *(dst)=SPDR
 
 
 
/*-----------------------------------------------------------------------*/
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
 
static
BYTE wait_ready (void)
{
BYTE res;
 
 
Timer2 = 50; /* Wait for ready in timeout of 500ms */
rcvr_spi();
do
res = rcvr_spi();
while ((res != 0xFF) && Timer2);
 
return res;
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Receive a data packet from MMC */
/*-----------------------------------------------------------------------*/
 
static
BOOL rcvr_datablock (
BYTE *buff, /* Data buffer to store received data */
UINT btr /* Byte count (must be even number) */
)
{
BYTE token;
 
 
Timer1 = 10;
do { /* Wait for data packet in timeout of 100ms */
token = rcvr_spi();
} while ((token == 0xFF) && Timer1);
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
 
do { /* Receive the data block into buffer */
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
} while (btr -= 2);
rcvr_spi(); /* Discard CRC */
rcvr_spi();
 
return TRUE; /* Return with success */
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Send a data packet to MMC */
/*-----------------------------------------------------------------------*/
 
#if _READONLY == 0
static
BOOL xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
BYTE resp, wc;
 
 
if (wait_ready() != 0xFF) return FALSE;
 
xmit_spi(token); /* Xmit data token */
if (token != 0xFD) { /* Is data token */
wc = 0;
do { /* Xmit the 512 byte data block to MMC */
xmit_spi(*buff++);
xmit_spi(*buff++);
} while (--wc);
xmit_spi(0xFF); /* CRC (Dummy) */
xmit_spi(0xFF);
resp = rcvr_spi(); /* Reveive data response */
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
return FALSE;
}
 
return TRUE;
}
#endif /* _READONLY */
 
 
 
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
/*-----------------------------------------------------------------------*/
 
static
BYTE send_cmd (
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
BYTE n, res;
 
 
if (wait_ready() != 0xFF) return 0xFF;
 
/* Send command packet */
xmit_spi(cmd); /* Command */
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xmit_spi((BYTE)arg); /* Argument[7..0] */
n = 0;
if (cmd == CMD0) n = 0x95; /* CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* CRC for CMD8(0x1AA) */
xmit_spi(n);
 
/* Receive command response */
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
res = rcvr_spi();
while ((res & 0x80) && --n);
 
return res; /* Return with the response value */
}
 
 
 
 
/*--------------------------------------------------------------------------
 
Public Functions
 
---------------------------------------------------------------------------*/
 
 
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
 
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0) */
)
{
BYTE n, ty, ocr[4];
 
 
if (drv) return STA_NOINIT; /* Supports only single drive */
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
 
for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */
 
SELECT(); /* CS = L */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = 100; /* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
do {
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
} while (Timer1);
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
ty = (ocr[0] & 0x40) ? 6 : 2;
}
}
} else { /* SDC Ver1 or MMC */
ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
do {
if (ty == 2) {
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
} else {
if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
}
} while (Timer1);
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
ty = 0;
}
}
CardType = ty;
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
if (ty) { /* Initialization succeded */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
} else { /* Initialization failed */
Stat |= STA_NOINIT; /* Set STA_NOINIT */
}
 
return Stat;
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
 
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0) */
)
{
if (drv) return STA_NOINIT; /* Supports only single drive */
return Stat;
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
 
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
 
if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
 
SELECT(); /* CS = L */
 
if (count == 1) { /* Single block read */
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
&& rcvr_datablock(buff, 512))
count = 0;
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
}
 
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
return count ? RES_ERROR : RES_OK;
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
 
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
 
if (!(CardType & 4)) sector *= 512; /* Convert to byte address if needed */
 
SELECT(); /* CS = L */
 
if (count == 1) { /* Single block write */
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple block write */
if (CardType & 2) {
send_cmd(CMD55, 0); send_cmd(CMD23, count); /* ACMD23 */
}
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
 
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
return count ? RES_ERROR : RES_OK;
}
#endif /* _READONLY */
 
 
 
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
 
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive data block */
)
{
DRESULT res;
BYTE n, csd[16], *ptr = buff;
WORD csize;
 
 
if (drv) return RES_PARERR;
 
SELECT(); /* CS = L */
 
res = RES_ERROR;
switch (ctrl) {
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
*(DWORD*)buff = (DWORD)csize << 10;
} else { /* MMC or SDC ver 1.XX */
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = (DWORD)csize << (n - 9);
}
res = RES_OK;
}
break;
 
case GET_SECTOR_SIZE : /* Get sectors on the disk (WORD) */
*(WORD*)buff = 512;
res = RES_OK;
break;
 
case CTRL_SYNC : /* Make sure that data has been written */
if (wait_ready() == 0xFF)
res = RES_OK;
break;
 
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
if ((send_cmd(CMD9, 0) == 0) /* READ_CSD */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
 
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
if ((send_cmd(CMD10, 0) == 0) /* READ_CID */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
 
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 0; n < 4; n++)
*ptr++ = rcvr_spi();
res = RES_OK;
}
break;
 
default:
res = RES_PARERR;
}
 
DESELECT(); /* CS = H */
rcvr_spi(); /* Idle (Release DO) */
 
return res;
}
 
 
 
/*---------------------------------------*/
/* Device timer interrupt procedure */
/* This must be called in period of 10ms */
/* (Platform dependent) */
 
void disk_timerproc (void)
{
static BYTE pv;
BYTE n, s;
 
 
n = Timer1; /* 100Hz decrement timer */
if (n) Timer1 = --n;
n = Timer2;
if (n) Timer2 = --n;
 
n = pv;
pv = SOCKPORT & (SOCKINS); /* Sample socket switch */
 
if (n == pv) { /* Have contacts stabled? */
s = Stat;
if (pv & SOCKINS) /* INS = H (Socket empty) */
s |= (STA_NODISK | STA_NOINIT);
else /* INS = L (Card inserted) */
s &= ~STA_NODISK;
 
Stat = s;
}
}
 
/Designs/Data_loggers/GPSRL03A/tff.c
0,0 → 1,1580
/*--------------------------------------------------------------------------/
/ FatFs - Tiny FAT file system module R0.04b (C)ChaN, 2007
/---------------------------------------------------------------------------/
/ The FatFs module is an experimenal project to implement FAT file system to
/ cheap microcontrollers. This is a free software and is opened for education,
/ research and development under license policy of following trems.
/
/ Copyright (C) 2007, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is no warranty.
/ * You can use, modify and/or redistribute it for personal, non-profit or
/ profit use without any restriction under your responsibility.
/ * Redistributions of source code must retain the above copyright notice.
/
/---------------------------------------------------------------------------/
/ Feb 26, 2006 R0.00 Prototype.
/ Apr 29, 2006 R0.01 First stable version.
/ Jun 01, 2006 R0.02 Added FAT12 support.
/ Removed unbuffered mode.
/ Fixed a problem on small (<32M) patition.
/ Jun 10, 2006 R0.02a Added a configuration option (_FS_MINIMUM).
/ Sep 22, 2006 R0.03 Added f_rename().
/ Changed option _FS_MINIMUM to _FS_MINIMIZE.
/ Dec 09, 2006 R0.03a Improved cluster scan algolithm to write files fast.
/ Feb 04, 2007 R0.04 Added FAT32 supprt.
/ Changed some interfaces incidental to FatFs.
/ Changed f_mountdrv() to f_mount().
/ Apr 01, 2007 R0.04a Added a capability of extending file size to f_lseek().
/ Added minimization level 3.
/ Fixed a problem in FAT32 support.
/ xxx xx, 2007 R0.04b Added a configuration option _USE_NTFLAG.
/ Added FSInfo support.
/ Fixed some problems corresponds to FAT32 support.
/ Fixed DBCS name can result FR_INVALID_NAME.
/ Fixed short seek (<= csize) collapses the file object.
/---------------------------------------------------------------------------*/
 
#include <string.h>
#include "tff.h" /* Tiny-FatFs declarations */
#include "diskio.h" /* Include file for user provided disk functions */
 
 
static
FATFS *FatFs; /* Pointer to the file system objects (logical drive) */
static
WORD fsid; /* File system mount ID */
 
 
/*-------------------------------------------------------------------------
 
Module Private Functions
 
-------------------------------------------------------------------------*/
 
 
/*-----------------------------------------------------------------------*/
/* Change window offset */
/*-----------------------------------------------------------------------*/
 
static
BOOL move_window ( /* TRUE: successful, FALSE: failed */
DWORD sector /* Sector number to make apperance in the FatFs->win */
) /* Move to zero only writes back dirty window */
{
DWORD wsect;
FATFS *fs = FatFs;
 
 
wsect = fs->winsect;
if (wsect != sector) { /* Changed current window */
#if !_FS_READONLY
BYTE n;
if (fs->winflag) { /* Write back dirty window if needed */
if (disk_write(0, fs->win, wsect, 1) != RES_OK)
return FALSE;
fs->winflag = 0;
if (wsect < (fs->fatbase + fs->sects_fat)) { /* In FAT area */
for (n = fs->n_fats; n >= 2; n--) { /* Refrect the change to all FAT copies */
wsect += fs->sects_fat;
disk_write(0, fs->win, wsect, 1);
}
}
}
#endif
if (sector) {
if (disk_read(0, fs->win, sector, 1) != RES_OK)
return FALSE;
fs->winsect = sector;
}
}
return TRUE;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Clean-up cached data */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
FRESULT sync (void) /* FR_OK: successful, FR_RW_ERROR: failed */
{
FATFS *fs = FatFs;
 
 
fs->winflag = 1;
if (!move_window(0)) return FR_RW_ERROR;
#if _USE_FSINFO
if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { /* Update FSInfo sector if needed */
fs->winsect = 0;
memset(fs->win, 0, 512);
ST_WORD(&fs->win[BS_55AA], 0xAA55);
ST_DWORD(&fs->win[FSI_LeadSig], 0x41615252);
ST_DWORD(&fs->win[FSI_StrucSig], 0x61417272);
ST_DWORD(&fs->win[FSI_Free_Count], fs->free_clust);
ST_DWORD(&fs->win[FSI_Nxt_Free], fs->last_clust);
disk_write(0, fs->win, fs->fsi_sector, 1);
fs->fsi_flag = 0;
}
#endif
if (disk_ioctl(0, CTRL_SYNC, NULL) != RES_OK) return FR_RW_ERROR;
return FR_OK;
}
#endif
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Get a cluster status */
/*-----------------------------------------------------------------------*/
 
static
CLUST get_cluster ( /* 0,>=2: successful, 1: failed */
CLUST clust /* Cluster# to get the link information */
)
{
WORD wc, bc;
DWORD fatsect;
FATFS *fs = FatFs;
 
 
if (clust >= 2 && clust < fs->max_clust) { /* Valid cluster# */
fatsect = fs->fatbase;
switch (fs->fs_type) {
case FS_FAT12 :
bc = (WORD)clust * 3 / 2;
if (!move_window(fatsect + bc / 512)) break;
wc = fs->win[bc % 512]; bc++;
if (!move_window(fatsect + bc / 512)) break;
wc |= (WORD)fs->win[bc % 512] << 8;
return (clust & 1) ? (wc >> 4) : (wc & 0xFFF);
 
case FS_FAT16 :
if (!move_window(fatsect + clust / 256)) break;
return LD_WORD(&fs->win[((WORD)clust * 2) % 512]);
#if _FAT32
case FS_FAT32 :
if (!move_window(fatsect + clust / 128)) break;
return LD_DWORD(&fs->win[((WORD)clust * 4) % 512]) & 0x0FFFFFFF;
#endif
}
}
 
return 1; /* There is no cluster information, or an error occured */
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Change a cluster status */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
BOOL put_cluster ( /* TRUE: successful, FALSE: failed */
CLUST clust, /* Cluster# to change */
CLUST val /* New value to mark the cluster */
)
{
WORD bc;
BYTE *p;
DWORD fatsect;
FATFS *fs = FatFs;
 
 
fatsect = fs->fatbase;
switch (fs->fs_type) {
case FS_FAT12 :
bc = (WORD)clust * 3 / 2;
if (!move_window(fatsect + bc / 512)) return FALSE;
p = &fs->win[bc % 512];
*p = (clust & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
bc++;
fs->winflag = 1;
if (!move_window(fatsect + bc / 512)) return FALSE;
p = &fs->win[bc % 512];
*p = (clust & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
break;
 
case FS_FAT16 :
if (!move_window(fatsect + clust / 256)) return FALSE;
ST_WORD(&fs->win[((WORD)clust * 2) % 512], (WORD)val);
break;
#if _FAT32
case FS_FAT32 :
if (!move_window(fatsect + clust / 128)) return FALSE;
ST_DWORD(&fs->win[((WORD)clust * 4) % 512], val);
break;
#endif
default :
return FALSE;
}
fs->winflag = 1;
return TRUE;
}
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Remove a cluster chain */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
BOOL remove_chain ( /* TRUE: successful, FALSE: failed */
CLUST clust /* Cluster# to remove chain from */
)
{
CLUST nxt;
FATFS *fs = FatFs;
 
 
while (clust >= 2 && clust < fs->max_clust) {
nxt = get_cluster(clust);
if (nxt == 1) return FALSE;
if (!put_cluster(clust, 0)) return FALSE;
if (fs->free_clust != (CLUST)0xFFFFFFFF) {
fs->free_clust++;
#if _USE_FSINFO
fs->fsi_flag = 1;
#endif
}
clust = nxt;
}
return TRUE;
}
#endif
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Stretch or create a cluster chain */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
CLUST create_chain ( /* 0: no free cluster, 1: error, >=2: new cluster number */
CLUST clust /* Cluster# to stretch, 0 means create new */
)
{
CLUST cstat, ncl, scl, mcl;
FATFS *fs = FatFs;
 
 
mcl = fs->max_clust;
if (clust == 0) { /* Create new chain */
scl = fs->last_clust; /* Get last allocated cluster */
if (scl < 2 || scl >= mcl) scl = 1;
}
else { /* Stretch existing chain */
cstat = get_cluster(clust); /* Check the cluster status */
if (cstat < 2) return 1; /* It is an invalid cluster */
if (cstat < mcl) return cstat; /* It is already followed by next cluster */
scl = clust;
}
 
ncl = scl; /* Start cluster */
for (;;) {
ncl++; /* Next cluster */
if (ncl >= mcl) { /* Wrap around */
ncl = 2;
if (ncl > scl) return 0; /* No free custer */
}
cstat = get_cluster(ncl); /* Get the cluster status */
if (cstat == 0) break; /* Found a free cluster */
if (cstat == 1) return 1; /* Any error occured */
if (ncl == scl) return 0; /* No free custer */
}
 
if (!put_cluster(ncl, (CLUST)0x0FFFFFFF)) return 1; /* Mark the new cluster "in use" */
if (clust && !put_cluster(clust, ncl)) return 1; /* Link it to previous one if needed */
 
fs->last_clust = ncl; /* Update fsinfo */
if (fs->free_clust != (CLUST)0xFFFFFFFF) {
fs->free_clust--;
#if _USE_FSINFO
fs->fsi_flag = 1;
#endif
}
 
return ncl; /* Return new cluster number */
}
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Get sector# from cluster# */
/*-----------------------------------------------------------------------*/
 
static
DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */
CLUST clust /* Cluster# to be converted */
)
{
FATFS *fs = FatFs;
 
 
clust -= 2;
if (clust >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
return (DWORD)clust * fs->sects_clust + fs->database;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Move directory pointer to next */
/*-----------------------------------------------------------------------*/
 
static
BOOL next_dir_entry ( /* TRUE: successful, FALSE: could not move next */
DIR *dirobj /* Pointer to directory object */
)
{
CLUST clust;
WORD idx;
FATFS *fs = FatFs;
 
 
idx = dirobj->index + 1;
if ((idx & 15) == 0) { /* Table sector changed? */
dirobj->sect++; /* Next sector */
if (!dirobj->clust) { /* In static table */
if (idx >= fs->n_rootdir) return FALSE; /* Reached to end of table */
} else { /* In dynamic table */
if (((idx / 16) & (fs->sects_clust - 1)) == 0) { /* Cluster changed? */
clust = get_cluster(dirobj->clust); /* Get next cluster */
if (clust < 2 || clust >= fs->max_clust) /* Reached to end of table */
return FALSE;
dirobj->clust = clust; /* Initialize for new cluster */
dirobj->sect = clust2sect(clust);
}
}
}
dirobj->index = idx; /* Lower 4 bit of dirobj->index indicates offset in dirobj->sect */
return TRUE;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Get file status from directory entry */
/*-----------------------------------------------------------------------*/
 
#if _FS_MINIMIZE <= 1
static
void get_fileinfo ( /* No return code */
FILINFO *finfo, /* Ptr to store the File Information */
const BYTE *dir /* Ptr to the directory entry */
)
{
BYTE n, c, a;
char *p;
 
 
p = &finfo->fname[0];
a = _USE_NTFLAG ? dir[DIR_NTres] : 0; /* NT flag */
for (n = 0; n < 8; n++) { /* Convert file name (body) */
c = dir[n];
if (c == ' ') break;
if (c == 0x05) c = 0xE5;
if (a & 0x08 && c >= 'A' && c <= 'Z') c += 0x20;
*p++ = c;
}
if (dir[8] != ' ') { /* Convert file name (extension) */
*p++ = '.';
for (n = 8; n < 11; n++) {
c = dir[n];
if (c == ' ') break;
if (a & 0x10 && c >= 'A' && c <= 'Z') c += 0x20;
*p++ = c;
}
}
*p = '\0';
 
finfo->fattrib = dir[DIR_Attr]; /* Attribute */
finfo->fsize = LD_DWORD(&dir[DIR_FileSize]); /* Size */
finfo->fdate = LD_WORD(&dir[DIR_WrtDate]); /* Date */
finfo->ftime = LD_WORD(&dir[DIR_WrtTime]); /* Time */
}
#endif /* _FS_MINIMIZE <= 1 */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Pick a paragraph and create the name in format of directory entry */
/*-----------------------------------------------------------------------*/
 
static
char make_dirfile ( /* 1: error - detected an invalid format, '\0'or'/': next character */
const char **path, /* Pointer to the file path pointer */
char *dirname /* Pointer to directory name buffer {Name(8), Ext(3), NT flag(1)} */
)
{
BYTE n, t, c, a, b;
 
 
memset(dirname, ' ', 8+3); /* Fill buffer with spaces */
a = 0; b = 0x18; /* NT flag */
n = 0; t = 8;
for (;;) {
c = *(*path)++;
if (c == '\0' || c == '/') { /* Reached to end of str or directory separator */
if (n == 0) break;
dirname[11] = _USE_NTFLAG ? (a & b) : 0;
return c;
}
if (c <= ' ' || c == 0x7F) break; /* Reject invisible chars */
if (c == '.') {
if (!(a & 1) && n >= 1 && n <= 8) { /* Enter extension part */
n = 8; t = 11; continue;
}
break;
}
if (_USE_SJIS &&
((c >= 0x81 && c <= 0x9F) || /* Accept S-JIS code */
(c >= 0xE0 && c <= 0xFC))) {
if (n == 0 && c == 0xE5) /* Change heading \xE5 to \x05 */
c = 0x05;
a ^= 1; goto md_l2;
}
if (c == '"') break; /* Reject " */
if (c <= ')') goto md_l1; /* Accept ! # $ % & ' ( ) */
if (c <= ',') break; /* Reject * + , */
if (c <= '9') goto md_l1; /* Accept - 0-9 */
if (c <= '?') break; /* Reject : ; < = > ? */
if (!(a & 1)) { /* These checks are not applied to S-JIS 2nd byte */
if (c == '|') break; /* Reject | */
if (c >= '[' && c <= ']') break;/* Reject [ \ ] */
if (_USE_NTFLAG && c >= 'A' && c <= 'Z')
(t == 8) ? (b &= ~0x08) : (b &= ~0x10);
if (c >= 'a' && c <= 'z') { /* Convert to upper case */
c -= 0x20;
if (_USE_NTFLAG) (t == 8) ? (a |= 0x08) : (a |= 0x10);
}
}
md_l1:
a &= ~1;
md_l2:
if (n >= t) break;
dirname[n++] = c;
}
return 1;
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Trace a file path */
/*-----------------------------------------------------------------------*/
 
static
FRESULT trace_path ( /* FR_OK(0): successful, !=0: error code */
DIR *dirobj, /* Pointer to directory object to return last directory */
char *fn, /* Pointer to last segment name to return */
const char *path, /* Full-path string to trace a file or directory */
BYTE **dir /* Directory pointer in Win[] to retutn */
)
{
CLUST clust;
char ds;
BYTE *dptr = NULL;
FATFS *fs = FatFs;
 
/* Initialize directory object */
clust = fs->dirbase;
#if _FAT32
if (fs->fs_type == FS_FAT32) {
dirobj->clust = dirobj->sclust = clust;
dirobj->sect = clust2sect(clust);
} else
#endif
{
dirobj->clust = dirobj->sclust = 0;
dirobj->sect = clust;
}
dirobj->index = 0;
dirobj->fs = fs;
 
if (*path == '\0') { /* Null path means the root directory */
*dir = NULL; return FR_OK;
}
 
for (;;) {
ds = make_dirfile(&path, fn); /* Get a paragraph into fn[] */
if (ds == 1) return FR_INVALID_NAME;
for (;;) {
if (!move_window(dirobj->sect)) return FR_RW_ERROR;
dptr = &fs->win[(dirobj->index & 15) * 32]; /* Pointer to the directory entry */
if (dptr[DIR_Name] == 0) /* Has it reached to end of dir? */
return !ds ? FR_NO_FILE : FR_NO_PATH;
if (dptr[DIR_Name] != 0xE5 /* Matched? */
&& !(dptr[DIR_Attr] & AM_VOL)
&& !memcmp(&dptr[DIR_Name], fn, 8+3) ) break;
if (!next_dir_entry(dirobj)) /* Next directory pointer */
return !ds ? FR_NO_FILE : FR_NO_PATH;
}
if (!ds) { *dir = dptr; return FR_OK; } /* Matched with end of path */
if (!(dptr[DIR_Attr] & AM_DIR)) return FR_NO_PATH; /* Cannot trace because it is a file */
clust = /* Get cluster# of the directory */
#if _FAT32
((DWORD)LD_WORD(&dptr[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dptr[DIR_FstClusLO]);
dirobj->clust = dirobj->sclust = clust; /* Restart scannig with the new directory */
dirobj->sect = clust2sect(clust);
dirobj->index = 2;
}
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Reserve a directory entry */
/*-----------------------------------------------------------------------*/
 
#if !_FS_READONLY
static
FRESULT reserve_direntry ( /* FR_OK: successful, FR_DENIED: no free entry, FR_RW_ERROR: a disk error occured */
DIR *dirobj, /* Target directory to create new entry */
BYTE **dir /* Pointer to pointer to created entry to retutn */
)
{
CLUST clust;
DWORD sector;
BYTE c, n, *dptr;
FATFS *fs = FatFs;
 
 
/* Re-initialize directory object */
clust = dirobj->sclust;
if (clust) { /* Dyanmic directory table */
dirobj->clust = clust;
dirobj->sect = clust2sect(clust);
} else { /* Static directory table */
dirobj->sect = fs->dirbase;
}
dirobj->index = 0;
 
do {
if (!move_window(dirobj->sect)) return FR_RW_ERROR;
dptr = &fs->win[(dirobj->index & 15) * 32]; /* Pointer to the directory entry */
c = dptr[DIR_Name];
if (c == 0 || c == 0xE5) { /* Found an empty entry! */
*dir = dptr; return FR_OK;
}
} while (next_dir_entry(dirobj)); /* Next directory pointer */
/* Reached to end of the directory table */
 
/* Abort when static table or could not stretch dynamic table */
if (!clust || !(clust = create_chain(dirobj->clust))) return FR_DENIED;
if (clust == 1 || !move_window(0)) return FR_RW_ERROR;
 
fs->winsect = sector = clust2sect(clust); /* Cleanup the expanded table */
memset(fs->win, 0, 512);
for (n = fs->sects_clust; n; n--) {
if (disk_write(0, fs->win, sector, 1) != RES_OK)
return FR_RW_ERROR;
sector++;
}
fs->winflag = 1;
*dir = fs->win;
return FR_OK;
}
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Load boot record and check if it is a FAT boot record */
/*-----------------------------------------------------------------------*/
 
static
BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record or error */
DWORD sect /* Sector# to check if it is a FAT boot record or not */
)
{
FATFS *fs = FatFs;
 
if (disk_read(0, fs->win, sect, 1) != RES_OK) /* Load boot record */
return 2;
if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature */
return 2;
 
if (!memcmp(&fs->win[BS_FilSysType], "FAT", 3)) /* Check FAT signature */
return 0;
#if _FAT32
if (!memcmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80))
return 0;
#endif
return 1;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Make sure that the file system is valid */
/*-----------------------------------------------------------------------*/
 
static
FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */
const char **path, /* Pointer to pointer to the path name (drive number) */
BYTE chk_wp /* !=0: Check media write protection for wrinting fuctions */
)
{
BYTE fmt;
DSTATUS stat;
DWORD bootsect, fatsize, totalsect, maxclust;
const char *p = *path;
FATFS *fs = FatFs;
 
 
 
while (*p == ' ') p++; /* Strip leading spaces */
if (*p == '/') p++; /* Strip heading slash */
*path = p; /* Return pointer to the path name */
 
/* Is the file system object registered? */
if (!fs) return FR_NOT_ENABLED;
 
/* Chekck if the logical drive has been mounted or not */
if (fs->fs_type) {
stat = disk_status(0);
if (!(stat & STA_NOINIT)) { /* If the physical drive is kept initialized */
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
#endif
return FR_OK; /* The file system object is valid */
}
}
 
/* The logical drive has not been mounted, following code attempts to mount the logical drive */
 
memset(fs, 0, sizeof(FATFS)); /* Clean-up the file system object */
stat = disk_initialize(0); /* Initialize low level disk I/O layer */
if (stat & STA_NOINIT) /* Check if the drive is ready */
return FR_NOT_READY;
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
#endif
 
/* Search FAT partition on the drive */
fmt = check_fs(bootsect = 0); /* Check sector 0 as an SFD format */
if (fmt == 1) { /* Not a FAT boot record, it may be patitioned */
/* Check a partition listed in top of the partition table */
if (fs->win[MBR_Table+4]) { /* Is the 1st partition existing? */
bootsect = LD_DWORD(&fs->win[MBR_Table+8]); /* Partition offset in LBA */
fmt = check_fs(bootsect); /* Check the partition */
}
}
if (fmt || LD_WORD(&fs->win[BPB_BytsPerSec]) != 512) /* No valid FAT patition is found */
return FR_NO_FILESYSTEM;
 
/* Initialize the file system object */
fatsize = LD_WORD(&fs->win[BPB_FATSz16]); /* Number of sectors per FAT */
if (!fatsize) fatsize = LD_DWORD(&fs->win[BPB_FATSz32]);
fs->sects_fat = (CLUST)fatsize;
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */
fatsize *= fs->n_fats; /* (Number of sectors in FAT area) */
fs->fatbase = bootsect + LD_WORD(&fs->win[BPB_RsvdSecCnt]); /* FAT start sector (lba) */
fs->sects_clust = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
fs->n_rootdir = LD_WORD(&fs->win[BPB_RootEntCnt]); /* Nmuber of root directory entries */
totalsect = LD_WORD(&fs->win[BPB_TotSec16]); /* Number of sectors on the file system */
if (!totalsect) totalsect = LD_DWORD(&fs->win[BPB_TotSec32]);
fs->max_clust = maxclust = (totalsect /* Last cluster# + 1 */
- LD_WORD(&fs->win[BPB_RsvdSecCnt]) - fatsize - fs->n_rootdir / 16
) / fs->sects_clust + 2;
 
fmt = FS_FAT12; /* Determine the FAT sub type */
if (maxclust > 0xFF7) fmt = FS_FAT16;
if (maxclust > 0xFFF7)
#if !_FAT32
return FR_NO_FILESYSTEM;
#else
fmt = FS_FAT32;
if (fmt == FS_FAT32)
fs->dirbase = LD_DWORD(&fs->win[BPB_RootClus]); /* Root directory start cluster */
else
#endif
fs->dirbase = fs->fatbase + fatsize; /* Root directory start sector (lba) */
fs->database = fs->fatbase + fatsize + fs->n_rootdir / 16; /* Data start sector (lba) */
fs->fs_type = fmt; /* FAT sub-type */
 
#if !_FS_READONLY
fs->free_clust = (CLUST)0xFFFFFFFF;
#if _USE_FSINFO
/* Load fsinfo sector if needed */
if (fmt == FS_FAT32) {
fs->fsi_sector = bootsect + LD_WORD(&fs->win[BPB_FSInfo]);
if (disk_read(0, fs->win, fs->fsi_sector, 1) == RES_OK &&
LD_WORD(&fs->win[BS_55AA]) == 0xAA55 &&
LD_DWORD(&fs->win[FSI_LeadSig]) == 0x41615252 &&
LD_DWORD(&fs->win[FSI_StrucSig]) == 0x61417272) {
fs->last_clust = LD_DWORD(&fs->win[FSI_Nxt_Free]);
fs->free_clust = LD_DWORD(&fs->win[FSI_Free_Count]);
}
}
#endif
#endif
fs->id = ++fsid; /* File system mount ID */
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Check if the file/dir object is valid or not */
/*-----------------------------------------------------------------------*/
 
static
FRESULT validate ( /* FR_OK(0): The id is valid, !=0: Not valid */
const FATFS *fs, /* Pointer to the file system object */
WORD id /* id member of the target object to be checked */
)
{
if (!fs || fs->id != id)
return FR_INVALID_OBJECT;
if (disk_status(0) & STA_NOINIT)
return FR_NOT_READY;
 
return FR_OK;
}
 
 
 
 
/*--------------------------------------------------------------------------
 
Public Functions
 
--------------------------------------------------------------------------*/
 
 
/*-----------------------------------------------------------------------*/
/* Mount/Unmount a Locical Drive */
/*-----------------------------------------------------------------------*/
 
FRESULT f_mount (
BYTE drv, /* Logical drive number to be mounted/unmounted */
FATFS *fs /* Pointer to new file system object (NULL for unmount)*/
)
{
FATFS *fsobj;
 
 
if (drv) return FR_INVALID_DRIVE;
fsobj = FatFs;
FatFs = fs;
if (fsobj) memset(fsobj, 0, sizeof(FATFS));
if (fs) memset(fs, 0, sizeof(FATFS));
 
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Open or Create a File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_open (
FIL *fp, /* Pointer to the blank file object */
const char *path, /* Pointer to the file name */
BYTE mode /* Access mode and file open mode flags */
)
{
FRESULT res;
BYTE *dir;
DIR dirobj;
char fn[8+3+1];
FATFS *fs = FatFs;
 
 
fp->fs = NULL;
#if !_FS_READONLY
mode &= (FA_READ|FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW);
res = auto_mount(&path, (BYTE)(mode & (FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)));
#else
mode &= FA_READ;
res = auto_mount(&path, 0);
#endif
if (res != FR_OK) return res;
 
/* Trace the file path */
res = trace_path(&dirobj, fn, path, &dir); /* Trace the file path */
 
#if !_FS_READONLY
/* Create or Open a File */
if (mode & (FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)) {
CLUST rs;
DWORD dw;
if (res != FR_OK) { /* No file, create new */
if (res != FR_NO_FILE) return res;
res = reserve_direntry(&dirobj, &dir);
if (res != FR_OK) return res;
memset(dir, 0, 32); /* Initialize the new entry */
memcpy(&dir[DIR_Name], fn, 8+3);
dir[DIR_NTres] = fn[11];
mode |= FA_CREATE_ALWAYS;
} else { /* Any object is already existing */
if (mode & FA_CREATE_NEW) /* Cannot create new */
return FR_EXIST;
if (dir == NULL || (dir[DIR_Attr] & (AM_RDO|AM_DIR))) /* Cannot overwrite (R/O or DIR) */
return FR_DENIED;
if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero */
#if _FAT32
rs = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]);
ST_WORD(&dir[DIR_FstClusHI], 0);
#else
rs = LD_WORD(&dir[DIR_FstClusLO]);
#endif
ST_WORD(&dir[DIR_FstClusLO], 0); /* cluster = 0 */
ST_DWORD(&dir[DIR_FileSize], 0); /* size = 0 */
fs->winflag = 1;
dw = fs->winsect; /* Remove the cluster chain */
if (!remove_chain(rs) || !move_window(dw))
return FR_RW_ERROR;
fs->last_clust = rs - 1; /* Reuse the cluster hole */
}
}
if (mode & FA_CREATE_ALWAYS) {
dir[DIR_Attr] = AM_ARC; /* New attribute */
dw = get_fattime();
ST_DWORD(&dir[DIR_WrtTime], dw); /* Updated time */
ST_DWORD(&dir[DIR_CrtTime], dw); /* Created time */
fs->winflag = 1;
}
}
/* Open a File */
else {
#endif /* !_FS_READONLY */
if (res != FR_OK) return res; /* Trace failed */
if (dir == NULL || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */
return FR_NO_FILE;
#if !_FS_READONLY
if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
return FR_DENIED;
}
 
fp->dir_sect = fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
#endif
fp->flag = mode; /* File access mode */
fp->org_clust = /* File start cluster */
#if _FAT32
((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dir[DIR_FstClusLO]);
fp->fsize = LD_DWORD(&dir[DIR_FileSize]); /* File size */
fp->fptr = 0; /* File ptr */
fp->sect_clust = 1; /* Sector counter */
fp->fs = fs; fp->id = fs->id; /* Owner file system object of the file */
 
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Read File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_read (
FIL *fp, /* Pointer to the file object */
void *buff, /* Pointer to data buffer */
WORD btr, /* Number of bytes to read */
WORD *br /* Pointer to number of bytes read */
)
{
DWORD sect, remain;
WORD rcnt;
CLUST clust;
BYTE cc, *rbuff = buff;
FRESULT res;
FATFS *fs = fp->fs;
 
 
*br = 0;
res = validate(fs, fp->id); /* Check validity of the object */
if (res) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_READ)) return FR_DENIED; /* Check access mode */
remain = fp->fsize - fp->fptr;
if (btr > remain) btr = (WORD)remain; /* Truncate read count by number of bytes left */
 
for ( ; btr; /* Repeat until all data transferred */
rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
if ((fp->fptr % 512) == 0) { /* On the sector boundary */
if (--fp->sect_clust) { /* Decrement left sector counter */
sect = fp->curr_sect + 1; /* Get current sector */
} else { /* On the cluster boundary, get next cluster */
clust = (fp->fptr == 0) ?
fp->org_clust : get_cluster(fp->curr_clust);
if (clust < 2 || clust >= fs->max_clust)
goto fr_error;
fp->curr_clust = clust; /* Current cluster */
sect = clust2sect(clust); /* Get current sector */
fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */
}
fp->curr_sect = sect; /* Update current sector */
cc = btr / 512; /* When left bytes >= 512, */
if (cc) { /* Read maximum contiguous sectors directly */
if (cc > fp->sect_clust) cc = fp->sect_clust;
if (disk_read(0, rbuff, sect, cc) != RES_OK)
goto fr_error;
fp->sect_clust -= cc - 1;
fp->curr_sect += cc - 1;
rcnt = cc * 512; continue;
}
}
if (!move_window(fp->curr_sect)) goto fr_error; /* Move sector window */
rcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes from sector window */
if (rcnt > btr) rcnt = btr;
memcpy(rbuff, &fs->win[(WORD)fp->fptr % 512], rcnt);
}
 
return FR_OK;
 
fr_error: /* Abort this function due to an unrecoverable error */
fp->flag |= FA__ERROR;
return FR_RW_ERROR;
}
 
 
 
 
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Write File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_write (
FIL *fp, /* Pointer to the file object */
const void *buff, /* Pointer to the data to be written */
WORD btw, /* Number of bytes to write */
WORD *bw /* Pointer to number of bytes written */
)
{
DWORD sect;
WORD wcnt;
CLUST clust;
BYTE cc;
FRESULT res;
const BYTE *wbuff = buff;
FATFS *fs = fp->fs;
 
 
*bw = 0;
res = validate(fs, fp->id); /* Check validity of the object */
if (res) return res;
if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */
if (!(fp->flag & FA_WRITE)) return FR_DENIED; /* Check access mode */
if (fp->fsize + btw < fp->fsize) return FR_OK; /* File size cannot reach 4GB */
 
for ( ; btw; /* Repeat until all data transferred */
wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
if ((fp->fptr % 512) == 0) { /* On the sector boundary */
if (--(fp->sect_clust)) { /* Decrement left sector counter */
sect = fp->curr_sect + 1; /* Get current sector */
} else { /* On the cluster boundary, get next cluster */
if (fp->fptr == 0) { /* Is top of the file */
clust = fp->org_clust;
if (clust == 0) /* No cluster is created yet */
fp->org_clust = clust = create_chain(0); /* Create a new cluster chain */
} else { /* Middle or end of file */
clust = create_chain(fp->curr_clust); /* Trace or streach cluster chain */
}
if (clust == 0) break; /* Disk full */
if (clust == 1 || clust >= fs->max_clust) goto fw_error;
fp->curr_clust = clust; /* Current cluster */
sect = clust2sect(clust); /* Get current sector */
fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */
}
fp->curr_sect = sect; /* Update current sector */
cc = btw / 512; /* When left bytes >= 512, */
if (cc) { /* Write maximum contiguous sectors directly */
if (cc > fp->sect_clust) cc = fp->sect_clust;
if (disk_write(0, wbuff, sect, cc) != RES_OK)
goto fw_error;
fp->sect_clust -= cc - 1;
fp->curr_sect += cc - 1;
wcnt = cc * 512; continue;
}
if (fp->fptr >= fp->fsize) { /* Flush R/W window if needed */
if (!move_window(0)) goto fw_error;
fs->winsect = fp->curr_sect;
}
}
if (!move_window(fp->curr_sect)) /* Move sector window */
goto fw_error;
wcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes bytes to sector window */
if (wcnt > btw) wcnt = btw;
memcpy(&fs->win[(WORD)fp->fptr % 512], wbuff, wcnt);
fs->winflag = 1;
}
 
if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
fp->flag |= FA__WRITTEN; /* Set file changed flag */
return FR_OK;
 
fw_error: /* Abort this function due to an unrecoverable error */
fp->flag |= FA__ERROR;
return FR_RW_ERROR;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Synchronize between File and Disk */
/*-----------------------------------------------------------------------*/
 
FRESULT f_sync (
FIL *fp /* Pointer to the file object */
)
{
DWORD tim;
BYTE *dir;
FRESULT res;
FATFS *fs = fp->fs;
 
 
res = validate(fs, fp->id); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
/* Update the directory entry */
if (!move_window(fp->dir_sect))
return FR_RW_ERROR;
dir = fp->dir_ptr;
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
ST_DWORD(&dir[DIR_FileSize], fp->fsize); /* Update file size */
ST_WORD(&dir[DIR_FstClusLO], fp->org_clust); /* Update start cluster */
#if _FAT32
ST_WORD(&dir[DIR_FstClusHI], fp->org_clust >> 16);
#endif
tim = get_fattime(); /* Updated time */
ST_DWORD(&dir[DIR_WrtTime], tim);
fp->flag &= ~FA__WRITTEN;
res = sync();
}
}
return res;
}
 
#endif /* !_FS_READONLY */
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Close File */
/*-----------------------------------------------------------------------*/
 
FRESULT f_close (
FIL *fp /* Pointer to the file object to be closed */
)
{
FRESULT res;
 
 
#if !_FS_READONLY
res = f_sync(fp);
#else
res = validate(fp->fs, fp->id);
#endif
if (res == FR_OK)
fp->fs = NULL;
 
return res;
}
 
 
 
 
#if _FS_MINIMIZE <= 2
/*-----------------------------------------------------------------------*/
/* Seek File Pointer */
/*-----------------------------------------------------------------------*/
 
FRESULT f_lseek (
FIL *fp, /* Pointer to the file object */
DWORD ofs /* File pointer from top of file */
)
{
CLUST clust;
DWORD csize;
BYTE csect;
FRESULT res;
FATFS *fs = fp->fs;
 
 
res = validate(fs, fp->id); /* Check validity of the object */
if (res) return res;
 
if (fp->flag & FA__ERROR) return FR_RW_ERROR;
#if !_FS_READONLY
if (ofs > fp->fsize && !(fp->flag & FA_WRITE))
#else
if (ofs > fp->fsize)
#endif
ofs = fp->fsize;
fp->fptr = 0; fp->sect_clust = 1; /* Set file R/W pointer to top of the file */
 
/* Move file R/W pointer if needed */
if (ofs) {
clust = fp->org_clust; /* Get start cluster */
#if !_FS_READONLY
if (!clust) { /* If the file does not have a cluster chain, create new cluster chain */
clust = create_chain(0);
if (clust == 1) goto fk_error;
fp->org_clust = clust;
}
#endif
if (clust) { /* If the file has a cluster chain, it can be followed */
csize = (DWORD)fs->sects_clust * 512; /* Cluster size in unit of byte */
for (;;) { /* Loop to skip leading clusters */
fp->curr_clust = clust; /* Update current cluster */
if (ofs <= csize) break;
#if !_FS_READONLY
if (fp->flag & FA_WRITE) /* Check if in write mode or not */
clust = create_chain(clust); /* Force streached if in write mode */
else
#endif
clust = get_cluster(clust); /* Only follow cluster chain if not in write mode */
if (clust == 0) { /* Stop if could not follow the cluster chain */
ofs = csize; break;
}
if (clust == 1 || clust >= fs->max_clust) goto fk_error;
fp->fptr += csize; /* Update R/W pointer */
ofs -= csize;
}
csect = (BYTE)((ofs - 1) / 512); /* Sector offset in the cluster */
fp->curr_sect = clust2sect(clust) + csect; /* Current sector */
fp->sect_clust = fs->sects_clust - csect; /* Left sector counter in the cluster */
fp->fptr += ofs; /* Update file R/W pointer */
}
}
#if !_FS_READONLY
if ((fp->flag & FA_WRITE) && fp->fptr > fp->fsize) { /* Set updated flag if in write mode */
fp->fsize = fp->fptr;
fp->flag |= FA__WRITTEN;
}
#endif
 
return FR_OK;
 
fk_error: /* Abort this function due to an unrecoverable error */
fp->flag |= FA__ERROR;
return FR_RW_ERROR;
}
 
 
 
 
#if _FS_MINIMIZE <= 1
/*-----------------------------------------------------------------------*/
/* Open a directroy */
/*-----------------------------------------------------------------------*/
 
FRESULT f_opendir (
DIR *dirobj, /* Pointer to directory object to create */
const char *path /* Pointer to the directory path */
)
{
BYTE *dir;
char fn[8+3+1];
FRESULT res;
FATFS *fs = FatFs;
 
 
res = auto_mount(&path, 0);
if (res != FR_OK) return res;
 
res = trace_path(dirobj, fn, path, &dir); /* Trace the directory path */
if (res == FR_OK) { /* Trace completed */
if (dir != NULL) { /* It is not the root dir */
if (dir[DIR_Attr] & AM_DIR) { /* The entry is a directory */
dirobj->clust =
#if _FAT32
((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dir[DIR_FstClusLO]);
dirobj->sect = clust2sect(dirobj->clust);
dirobj->index = 2;
} else { /* The entry is not a directory */
res = FR_NO_FILE;
}
}
dirobj->id = fs->id;
}
return res;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Read Directory Entry in Sequense */
/*-----------------------------------------------------------------------*/
 
FRESULT f_readdir (
DIR *dirobj, /* Pointer to the directory object */
FILINFO *finfo /* Pointer to file information to return */
)
{
BYTE *dir, c;
FRESULT res;
FATFS *fs = dirobj->fs;
 
 
res = validate(fs, dirobj->id); /* Check validity of the object */
if (res) return res;
 
finfo->fname[0] = 0;
while (dirobj->sect) {
if (!move_window(dirobj->sect))
return FR_RW_ERROR;
dir = &fs->win[(dirobj->index & 15) * 32]; /* pointer to the directory entry */
c = dir[DIR_Name];
if (c == 0) break; /* Has it reached to end of dir? */
if (c != 0xE5 && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */
get_fileinfo(finfo, dir);
if (!next_dir_entry(dirobj)) dirobj->sect = 0; /* Next entry */
if (finfo->fname[0]) break; /* Found valid entry */
}
 
return FR_OK;
}
 
 
 
 
#if _FS_MINIMIZE == 0
/*-----------------------------------------------------------------------*/
/* Get File Status */
/*-----------------------------------------------------------------------*/
 
FRESULT f_stat (
const char *path, /* Pointer to the file path */
FILINFO *finfo /* Pointer to file information to return */
)
{
BYTE *dir;
char fn[8+3+1];
FRESULT res;
DIR dirobj;
 
 
res = auto_mount(&path, 0);
if (res != FR_OK) return res;
 
res = trace_path(&dirobj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) { /* Trace completed */
if (dir) /* Found an object */
get_fileinfo(finfo, dir);
else /* It is root dir */
res = FR_INVALID_NAME;
}
 
return res;
}
 
 
 
 
#if !_FS_READONLY
/*-----------------------------------------------------------------------*/
/* Get Number of Free Clusters */
/*-----------------------------------------------------------------------*/
 
FRESULT f_getfree (
const char *drv, /* Logical drive number */
DWORD *nclust, /* Pointer to the double word to return number of free clusters */
FATFS **fatfs /* Pointer to pointer to the file system object to return */
)
{
DWORD n, sect;
CLUST clust;
BYTE fat, f, *p;
FRESULT res;
FATFS *fs;
 
 
/* Get drive number */
res = auto_mount(&drv, 0);
if (res != FR_OK) return res;
*fatfs = fs = FatFs;
 
/* If number of free cluster is valid, return it without cluster scan. */
if (fs->free_clust <= fs->max_clust - 2) {
*nclust = fs->free_clust;
return FR_OK;
}
 
/* Count number of free clusters */
fat = fs->fs_type;
n = 0;
if (fat == FS_FAT12) {
clust = 2;
do {
if ((WORD)get_cluster(clust) == 0) n++;
} while (++clust < fs->max_clust);
} else {
clust = fs->max_clust;
sect = fs->fatbase;
f = 0; p = 0;
do {
if (!f) {
if (!move_window(sect++)) return FR_RW_ERROR;
p = fs->win;
}
if (!_FAT32 || fat == FS_FAT16) {
if (LD_WORD(p) == 0) n++;
p += 2; f += 1;
} else {
if (LD_DWORD(p) == 0) n++;
p += 4; f += 2;
}
} while (--clust);
}
fs->free_clust = n;
#if _USE_FSINFO
if (fat == FS_FAT32) fs->fsi_flag = 1;
#endif
 
*nclust = n;
return FR_OK;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Delete a File or a Directory */
/*-----------------------------------------------------------------------*/
 
FRESULT f_unlink (
const char *path /* Pointer to the file or directory path */
)
{
BYTE *dir, *sdir;
DWORD dsect;
char fn[8+3+1];
CLUST dclust;
FRESULT res;
DIR dirobj;
FATFS *fs = FatFs;
 
 
res = auto_mount(&path, 1);
if (res != FR_OK) return res;
 
res = trace_path(&dirobj, fn, path, &dir); /* Trace the file path */
if (res != FR_OK) return res; /* Trace failed */
if (dir == NULL) return FR_INVALID_NAME; /* It is the root directory */
if (dir[DIR_Attr] & AM_RDO) return FR_DENIED; /* It is a R/O object */
dsect = fs->winsect;
dclust =
#if _FAT32
((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) |
#endif
LD_WORD(&dir[DIR_FstClusLO]);
if (dir[DIR_Attr] & AM_DIR) { /* It is a sub-directory */
dirobj.clust = dclust; /* Check if the sub-dir is empty or not */
dirobj.sect = clust2sect(dclust);
dirobj.index = 2;
do {
if (!move_window(dirobj.sect)) return FR_RW_ERROR;
sdir = &fs->win[(dirobj.index & 15) * 32];
if (sdir[DIR_Name] == 0) break;
if (sdir[DIR_Name] != 0xE5 && !(sdir[DIR_Attr] & AM_VOL))
return FR_DENIED; /* The directory is not empty */
} while (next_dir_entry(&dirobj));
}
 
if (!move_window(dsect)) return FR_RW_ERROR; /* Mark the directory entry 'deleted' */
dir[DIR_Name] = 0xE5;
fs->winflag = 1;
if (!remove_chain(dclust)) return FR_RW_ERROR; /* Remove the cluster chain */
 
return sync();
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Create a Directory */
/*-----------------------------------------------------------------------*/
 
FRESULT f_mkdir (
const char *path /* Pointer to the directory path */
)
{
BYTE *dir, *fw, n;
char fn[8+3+1];
DWORD sect, dsect, tim;
CLUST dclust, pclust;
FRESULT res;
DIR dirobj;
FATFS *fs = FatFs;
 
 
res = auto_mount(&path, 1);
if (res != FR_OK) return res;
 
res = trace_path(&dirobj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) return FR_EXIST; /* Any file or directory is already existing */
if (res != FR_NO_FILE) return res;
 
res = reserve_direntry(&dirobj, &dir); /* Reserve a directory entry */
if (res != FR_OK) return res;
sect = fs->winsect;
dclust = create_chain(0); /* Allocate a cluster for new directory table */
if (dclust == 1) return FR_RW_ERROR;
dsect = clust2sect(dclust);
if (!dsect) return FR_DENIED;
if (!move_window(dsect)) return FR_RW_ERROR;
 
fw = fs->win;
memset(fw, 0, 512); /* Clear the directory table */
for (n = 1; n < fs->sects_clust; n++) {
if (disk_write(0, fw, ++dsect, 1) != RES_OK)
return FR_RW_ERROR;
}
 
memset(&fw[DIR_Name], ' ', 8+3); /* Create "." entry */
fw[DIR_Name] = '.';
fw[DIR_Attr] = AM_DIR;
tim = get_fattime();
ST_DWORD(&fw[DIR_WrtTime], tim);
memcpy(&fw[32], &fw[0], 32); fw[33] = '.'; /* Create ".." entry */
pclust = dirobj.sclust;
#if _FAT32
ST_WORD(&fw[ DIR_FstClusHI], dclust >> 16);
if (fs->fs_type == FS_FAT32 && pclust == fs->dirbase) pclust = 0;
ST_WORD(&fw[32+DIR_FstClusHI], pclust >> 16);
#endif
ST_WORD(&fw[ DIR_FstClusLO], dclust);
ST_WORD(&fw[32+DIR_FstClusLO], pclust);
fs->winflag = 1;
 
if (!move_window(sect)) return FR_RW_ERROR;
memset(&dir[0], 0, 32); /* Clean-up the new entry */
memcpy(&dir[DIR_Name], fn, 8+3); /* Name */
dir[DIR_NTres] = fn[11];
dir[DIR_Attr] = AM_DIR; /* Attribute */
ST_DWORD(&dir[DIR_WrtTime], tim); /* Crated time */
ST_WORD(&dir[DIR_FstClusLO], dclust); /* Table start cluster */
#if _FAT32
ST_WORD(&dir[DIR_FstClusHI], dclust >> 16);
#endif
 
return sync();
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Change File Attribute */
/*-----------------------------------------------------------------------*/
 
FRESULT f_chmod (
const char *path, /* Pointer to the file path */
BYTE value, /* Attribute bits */
BYTE mask /* Attribute mask to change */
)
{
FRESULT res;
BYTE *dir;
DIR dirobj;
char fn[8+3+1];
 
 
res = auto_mount(&path, 1);
if (res == FR_OK) {
res = trace_path(&dirobj, fn, path, &dir); /* Trace the file path */
if (res == FR_OK) { /* Trace completed */
if (dir == NULL) {
res = FR_INVALID_NAME;
} else {
mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */
dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
res = sync();
}
}
}
return res;
}
 
 
 
 
/*-----------------------------------------------------------------------*/
/* Rename File/Directory */
/*-----------------------------------------------------------------------*/
 
FRESULT f_rename (
const char *path_old, /* Pointer to the old name */
const char *path_new /* Pointer to the new name */
)
{
FRESULT res;
DWORD sect_old;
BYTE *dir_old, *dir_new, direntry[32-11];
DIR dirobj;
char fn[8+3+1];
FATFS *fs = FatFs;
 
 
res = auto_mount(&path_old, 1);
if (res != FR_OK) return res;
 
res = trace_path(&dirobj, fn, path_old, &dir_old); /* Check old object */
if (res != FR_OK) return res; /* The old object is not found */
if (!dir_old) return FR_NO_FILE;
sect_old = fs->winsect; /* Save the object information */
memcpy(direntry, &dir_old[11], 32-11);
 
res = trace_path(&dirobj, fn, path_new, &dir_new); /* Check new object */
if (res == FR_OK) return FR_EXIST; /* The new object name is already existing */
if (res != FR_NO_FILE) return res; /* Is there no old name? */
res = reserve_direntry(&dirobj, &dir_new); /* Reserve a directory entry */
if (res != FR_OK) return res;
 
memcpy(&dir_new[DIR_Attr], direntry, 32-11); /* Create new entry */
memcpy(&dir_new[DIR_Name], fn, 8+3);
dir_new[DIR_NTres] = fn[11];
fs->winflag = 1;
 
if (!move_window(sect_old)) return FR_RW_ERROR; /* Remove old entry */
dir_old[DIR_Name] = 0xE5;
 
return sync();
}
 
#endif /* !_FS_READONLY */
#endif /* _FS_MINIMIZE == 0 */
#endif /* _FS_MINIMIZE <= 1 */
#endif /* _FS_MINIMIZE <= 2 */
 
/Designs/Data_loggers/GPSRL03A/tff.h
0,0 → 1,289
/*--------------------------------------------------------------------------/
/ Tiny-FatFs - FAT file system module include file R0.04b (C)ChaN, 2007
/---------------------------------------------------------------------------/
/ FatFs module is an experimenal project to implement FAT file system to
/ cheap microcontrollers. This is a free software and is opened for education,
/ research and development under license policy of following trems.
/
/ Copyright (C) 2007, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is no warranty.
/ * You can use, modify and/or redistribute it for personal, non-profit or
/ profit use without any restriction under your responsibility.
/ * Redistributions of source code must retain the above copyright notice.
/
/---------------------------------------------------------------------------*/
 
#ifndef _FATFS
 
#define _MCU_ENDIAN 1
/* The _MCU_ENDIAN defines which access method is used to the FAT structure.
/ 1: Enable word access.
/ 2: Disable word access and use byte-by-byte access instead.
/ When the architectural byte order of the MCU is big-endian and/or address
/ miss-aligned access is prohibited, the _MCU_ENDIAN must be set to 2.
/ If it is not the case, it can be set to 1 for good code efficiency. */
 
#define _FS_READONLY 0
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename
/ and useless f_getfree. */
 
#define _FS_MINIMIZE 2
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod and f_rename are removed.
/ 2: f_opendir and f_readdir are removed in addition to level 1.
/ 3: f_lseek is removed in addition to level 2. */
 
#define _FAT32 0
/* To support FAT32 in addition of FAT12/16, set _FAT32 to 1. */
 
#define _USE_FSINFO 0
/* To support FSInfo on FAT32 volume, set _USE_FSINFO to 1. */
 
#define _USE_SJIS 0
/* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
/ only US-ASCII(7bit) code can be accepted as file/directory name. */
 
#define _USE_NTFLAG 1
/* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved. */
 
 
#include "integer.h"
 
 
/* Type definition for cluster number */
#if _FAT32
typedef DWORD CLUST;
#else
typedef WORD CLUST;
#undef _USE_FSINFO
#define _USE_FSINFO 0
#endif
 
 
/* File system object structure */
typedef struct _FATFS {
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries */
DWORD winsect; /* Current sector appearing in the win[] */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector */
DWORD database; /* Data start sector */
CLUST sects_fat; /* Sectors per fat */
CLUST max_clust; /* Maximum cluster# + 1 */
#if !_FS_READONLY
CLUST last_clust; /* Last allocated cluster */
CLUST free_clust; /* Number of free clusters */
#if _USE_FSINFO
DWORD fsi_sector; /* fsinfo sector */
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
BYTE pad1;
#endif
#endif
BYTE fs_type; /* FAT sub type */
BYTE sects_clust; /* Sectors per cluster */
BYTE n_fats; /* Number of FAT copies */
BYTE winflag; /* win[] dirty flag (1:must be written back) */
BYTE win[512]; /* Disk access window for Directory/FAT/File */
} FATFS;
 
 
/* Directory object structure */
typedef struct _DIR {
WORD id; /* Owner file system mount ID */
WORD index; /* Current index */
FATFS* fs; /* Pointer to the owner file system object */
CLUST sclust; /* Start cluster */
CLUST clust; /* Current cluster */
DWORD sect; /* Current sector */
} DIR;
 
 
/* File object structure */
typedef struct _FIL {
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE sect_clust; /* Left sectors in cluster */
FATFS* fs; /* Pointer to owner file system */
DWORD fptr; /* File R/W pointer */
DWORD fsize; /* File size */
CLUST org_clust; /* File start cluster */
CLUST curr_clust; /* Current cluster */
DWORD curr_sect; /* Current sector */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
#endif
} FIL;
 
 
/* File status structure */
typedef struct _FILINFO {
DWORD fsize; /* Size */
WORD fdate; /* Date */
WORD ftime; /* Time */
BYTE fattrib; /* Attribute */
char fname[8+1+3+1]; /* Name (8.3 format) */
} FILINFO;
 
 
/* File function return code (FRESULT) */
 
typedef enum {
FR_OK = 0, /* 0 */
FR_NOT_READY, /* 1 */
FR_NO_FILE, /* 2 */
FR_NO_PATH, /* 3 */
FR_INVALID_NAME, /* 4 */
FR_INVALID_DRIVE, /* 5 */
FR_DENIED, /* 6 */
FR_EXIST, /* 7 */
FR_RW_ERROR, /* 8 */
FR_WRITE_PROTECTED, /* 9 */
FR_NOT_ENABLED, /* 10 */
FR_NO_FILESYSTEM, /* 11 */
FR_INVALID_OBJECT /* 12 */
} FRESULT;
 
 
 
/*-----------------------------------------------------*/
/* FatFs module application interface */
 
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, WORD, WORD*); /* Read data from a file */
FRESULT f_write (FIL*, const void*, WORD, WORD*); /* Write data to a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (DIR*, const char*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (const char*, FILINFO*); /* Get file status */
FRESULT f_getfree (const char*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const char*); /* Delete an existing file or directory */
FRESULT f_mkdir (const char*); /* Create a new directory */
FRESULT f_chmod (const char*, BYTE, BYTE); /* Change file/dir attriburte */
FRESULT f_rename (const char*, const char*); /* Rename/Move a file or directory */
 
 
/* User defined function to give a current time to fatfs module */
 
DWORD get_fattime (void); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day(1-31) */
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
 
 
 
/* File access control and file status flags (FIL.flag) */
 
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#if !_FS_READONLY
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#endif
#define FA__ERROR 0x80
 
 
/* FAT sub type (FATFS.fs_type) */
 
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
 
 
/* File attribute bits for directory entry */
 
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
 
 
 
/* Offset of FAT structure members */
 
#define BS_jmpBoot 0
#define BS_OEMName 3
#define BPB_BytsPerSec 11
#define BPB_SecPerClus 13
#define BPB_RsvdSecCnt 14
#define BPB_NumFATs 16
#define BPB_RootEntCnt 17
#define BPB_TotSec16 19
#define BPB_Media 21
#define BPB_FATSz16 22
#define BPB_SecPerTrk 24
#define BPB_NumHeads 26
#define BPB_HiddSec 28
#define BPB_TotSec32 32
#define BS_55AA 510
 
#define BS_DrvNum 36
#define BS_BootSig 38
#define BS_VolID 39
#define BS_VolLab 43
#define BS_FilSysType 54
 
#define BPB_FATSz32 36
#define BPB_ExtFlags 40
#define BPB_FSVer 42
#define BPB_RootClus 44
#define BPB_FSInfo 48
#define BPB_BkBootSec 50
#define BS_DrvNum32 64
#define BS_BootSig32 66
#define BS_VolID32 67
#define BS_VolLab32 71
#define BS_FilSysType32 82
 
#define FSI_LeadSig 0
#define FSI_StrucSig 484
#define FSI_Free_Count 488
#define FSI_Nxt_Free 492
 
#define MBR_Table 446
 
#define DIR_Name 0
#define DIR_Attr 11
#define DIR_NTres 12
#define DIR_CrtTime 14
#define DIR_CrtDate 16
#define DIR_FstClusHI 20
#define DIR_WrtTime 22
#define DIR_WrtDate 24
#define DIR_FstClusLO 26
#define DIR_FileSize 28
 
 
 
/* Multi-byte word access macros */
 
#if _MCU_ENDIAN == 1 /* Use word access */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#else
#if _MCU_ENDIAN == 2 /* Use byte-by-byte access */
#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
#else
#error Do not forget to set _MCU_ENDIAN properly!
#endif
#endif
 
 
 
#define _FATFS
#endif /* _FATFS */
/Designs/Data_loggers/GPSRL03A/tt.ini
0,0 → 1,0
bps=115200