├── Makefile ├── README.md ├── sdlocker-tiny.cpp ├── sdlocker-tiny.elf ├── sdlocker-tiny.hex ├── sdlocker-tiny.lst └── sdlocker-tiny.o /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for avr-gcc, avrdude 2 | 3 | SRC=sdlocker-tiny 4 | BAUD=19200 5 | PRGDEV=/dev/ttyACM0 6 | PRGTYPE=avrisp 7 | AVRTYPE=attiny85 8 | AVRTYPESHORT=t85 9 | AVRFREQ=8000000 10 | CFLAGS=-g -DF_CPU=$(AVRFREQ) -Wall -Os -Werror -Wextra 11 | 12 | all : $(SRC).hex 13 | 14 | program : $(SRC).hex 15 | avrdude -P $(PRGDEV) -b $(BAUD) -c $(PRGTYPE) -p $(AVRTYPESHORT) -v -e -U flash:w:$(SRC).hex 16 | 17 | $(SRC).o : $(SRC).cpp 18 | avr-gcc $(CFLAGS) -mmcu=$(AVRTYPE) -Wa,-ahlmns=$(SRC).lst -c -o $(SRC).o $(SRC).cpp 19 | 20 | $(SRC).elf : $(SRC).o 21 | avr-gcc $(CFLAGS) -mmcu=$(AVRTYPE) -o $(SRC).elf $(SRC).o 22 | 23 | $(SRC).hex : $(SRC).elf 24 | avr-objcopy -j .text -j .data -O ihex $(SRC).elf $(SRC).hex 25 | 26 | clean : 27 | rm -f *.hex *.obj *.o *.lst *.elf 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sdlocker-tiny 2 | ============= 3 | **Attiny85**-based device to **enable** and **disable write-protection** on **any SD card**. 4 | [![sdlocker-tiny built inside the shell of an old PlayStation Memory Card](https://raw.githubusercontent.com/Nephiel/sdlocker-tiny/gh-pages/img/sdlocker-tiny-sm.jpg "sdlocker-tiny built inside the shell of an old PlayStation Memory Card")](https://raw.githubusercontent.com/Nephiel/sdlocker-tiny/gh-pages/img/sdlocker-tiny.jpg) 5 | Based on **sdlocker** by ***Karl Lunt***, see http://www.seanet.com/~karllunt/sdlocker.html 6 | 7 | 8 | I routinely use **USB drives** loaded with software tools and benchmarks to diagnose and fix computers. I wanted a way to protect those drives from viruses, malware, filesystem corruption and accidental erase. 9 | 10 | USB drives with a **write-protect switch** do exist, but are hard to find and expensive. Full-sized SD cards have a slider tab to write-protect them, but **it actually does** ***nothing*** - it's up to the card reader to report it to the OS, and it's up to the OS to decide whether to comply and mount the card read-only or not. Most of them simply ignore it, so **SD cards may be overwritten regardless of the write-protect tab**. 11 | 12 | The **sdlocker** allows me to ***truly* write-protect any SD card** by toggling the TMP\_WRITE\_PROTECT bit on the flash memory controller of the card itself. Together with a USB card reader, this write-protected card **can then be used as a read-only USB drive**. 13 | 14 | This is my own fork of the original sdlocker, tailored to suit my needs - smaller, simpler, and USB-powered. 15 | 16 | 17 | Changes from original sdlocker 18 | ------------------------------ 19 | 20 | - Ported from **Atmega328** to **Attiny85** 21 | - Removed all the **UART code** and **unused functions** 22 | - Rewrote the **user interface** (1 button, 1 LED) 23 | 24 | 25 | Device Usage 26 | ------------ 27 | 28 | The **LED** shows the **state of the inserted card** at all times: 29 | - **Steady off:** card is unlocked (writable) 30 | - **Steady on:** card is locked (write-protected) 31 | - **Blinking, fast:** device is reading the card 32 | - **Blinking, slow:** card is faulty or not properly inserted 33 | 34 | **Holding the button** down (over half a second) **toggles** the write-protection of the inserted card. 35 | 36 | 37 | Schematic 38 | --------- 39 | 40 | - See *sdlocker-tiny.cpp* for ASCII schematic. 41 | 42 | - The button and LED share the same pin on the Attiny. 43 | 44 | - The RESET pin on the Attiny is left unconnected. It could be turned into another I/O pin by changing the appropiate fuse, but flashing the chip after that (even to change the fuse back) would require a HV programmer. 45 | 46 | - The SD card socket has a card-detect switch that shorts a pin to ground when a card is inserted. 47 | I used this pin as ground to cut the power to the device while there is no card. 48 | 49 | - To turn the 5V from USB into 3.3V, I used a Texas Instruments LM3940 + 2 capacitors 50 | (see the LM3940 datasheet, *Typical application*) 51 | 52 | - Both the Attiny85 and the SD card **run on 3.3V**. **Do *not* power them with 5V** from USB! 53 | The Attiny can take it, but the card will be destroyed. 54 | 55 | 56 | Compiling and Flashing 57 | ---------------------- 58 | 59 | The provided makefile uses **avr-gcc** and **avrdude**. Edit it to match your programmer. 60 | Run *make* to compile and *make program* to flash. 61 | 62 | -------------------------------------------------------------------------------- /sdlocker-tiny.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * sdlocker-tiny Lock/unlock an SD card, uses ATTINY85 3 | * By Nephiel 4 | * 5 | * Based on sdlocker by karllunt (http://www.seanet.com/~karllunt/sdlocker.html) 6 | * 7 | * 8 | * ATMEL ATTINY85 9 | * +-v-+ 10 | * nc PB5 1| |8 Vcc --- +3.3V 11 | * CS <-- PB3 2| |7 PB2 --> SCK 12 | * LEDSW <-> PB4 3| |6 PB1 <-- MISO 13 | * GND --- GND 4| |5 PB0 --> MOSI 14 | * +---+ 15 | * 16 | * 17 | * LEDSW--+ 18 | * | 19 | * +3.3V R1 LED | R2 Switch 20 | * Vcc----\/\/\---[>|---+---\/\/\---[*]----GND 21 | * 300 300 22 | * 23 | * 24 | * SD CARD 25 | * _______ 26 | * [ 9 ] \ rsv nc 27 | * [ 1 ] | CS <-- CS 28 | * [ 2 ] | DI <-- MOSI 29 | * [ 3 ] | GND --- GND 30 | * [ 4 ] | Vcc --- +3.3V 31 | * [ 5 ] | CLK <-- SCK 32 | * [ 6 ] | GND --- GND 33 | * [ 7 ] | DO --> MISO 34 | * [ 8 ] | rsv nc 35 | * --------+ 36 | * 37 | * 38 | * ADDITIONAL NOTES 39 | * 40 | * You might need to change the fuses on the ATTINY85: 41 | * lfuse=E2, hfuse=DF, efuse=FF or 01 42 | * 43 | * Use the built-in card-detect switch on the SD card socket 44 | * to cut the power to the circuit when the card is removed. 45 | * 46 | * Use a LM3940 to obtain 3.3V from a 5V source such as USB. 47 | * 48 | */ 49 | 50 | 51 | 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | #ifndef FALSE 64 | #define FALSE 0 65 | #define TRUE !FALSE 66 | #endif 67 | 68 | 69 | /* 70 | * Define commands for the SD card 71 | */ 72 | #define SD_GO_IDLE (0x40 + 0) // CMD0 - go to idle state 73 | #define SD_INIT (0x40 + 1) // CMD1 - start initialization 74 | #define SD_SEND_IF_COND (0x40 + 8) // CMD8 - send interface (conditional), works for SDHC only 75 | #define SD_SEND_CSD (0x40 + 9) // CMD9 - send CSD block (16 bytes) 76 | #define SD_SEND_CID (0x40 + 10) // CMD10 - send CID block (16 bytes) 77 | #define SD_SEND_STATUS (0x40 + 13) // CMD13 - send card status 78 | #define SD_SET_BLK_LEN (0x40 + 16) // CMD16 - set length of block in bytes 79 | #define SD_READ_BLK (0x40 + 17) // read single block 80 | #define SD_LOCK_UNLOCK (0x40 + 42) // CMD42 - lock/unlock card 81 | #define CMD55 (0x40 + 55) // multi-byte preface command 82 | #define SD_READ_OCR (0x40 + 58) // read OCR 83 | #define SD_ADV_INIT (0xc0 + 41) // ACMD41, for SDHC cards - advanced start initialization 84 | #define SD_PROGRAM_CSD (0x40 + 27) // CMD27 - get CSD block (15 bytes data + CRC) 85 | 86 | 87 | /* 88 | * Define the lock bit mask within byte 14 of the CSD 89 | */ 90 | #define LOCK_BIT_MASK 0x10 // mask for the lock bit 91 | 92 | 93 | /* 94 | * Define error codes that can be returned by local functions 95 | */ 96 | #define SDCARD_OK 0 // success 97 | #define SDCARD_NOT_DETECTED 1 // unable to detect SD card 98 | #define SDCARD_TIMEOUT 2 // last operation timed out 99 | #define SDCARD_RWFAIL 3 // read/write command failed 100 | 101 | 102 | /* 103 | * Define card types that could be reported by the SD card during probe 104 | */ 105 | #define SDTYPE_UNKNOWN 0 // card type not determined 106 | #define SDTYPE_SD 1 // SD v1 (1 MB to 2 GB) 107 | #define SDTYPE_SDHC 2 // SDHC (4 GB to 32 GB) 108 | 109 | 110 | /* 111 | * Define the port and DDR used by the SPI. 112 | */ 113 | #define SPI_PORT PORTB 114 | #define SPI_DDR DDRB 115 | #define SPI_PIN PINB 116 | 117 | 118 | /* 119 | * Define bits used by the SPI port. 120 | */ 121 | #define MOSI_BIT 0 122 | #define MISO_BIT 1 123 | #define SCK_BIT 2 124 | #define CS_BIT 3 125 | 126 | 127 | /* 128 | * Define the port, DDR, and bit used for the LED and the switch. 129 | * The ATTINY85 doesn't have enough I/O pins so we need to share one. 130 | * Note the LED output is active low. 131 | */ 132 | #define LEDSW_PORT PORTB 133 | #define LEDSW_DDR DDRB 134 | #define LEDSW_PIN PINB 135 | #define LEDSW_BIT 4 136 | #define LEDSW_MASK (1<0; i--) 517 | { 518 | response = SD_send_command(SD_ADV_INIT, 1UL<<30); 519 | if (response == 0) 520 | { 521 | break; 522 | } 523 | } 524 | sdtype = SDTYPE_SDHC; 525 | } 526 | else 527 | { // if card is SD... 528 | response = SD_send_command(SD_READ_OCR, 0); 529 | if (response == 0x01) 530 | { 531 | for (i=0; i<4; i++) // burn the 4-byte response (OCR) 532 | { 533 | Xchg(0xff); 534 | } 535 | for (i=20000; i>0; i--) 536 | { 537 | response = SD_send_command(SD_INIT, 0); 538 | if (response == 0) 539 | { 540 | break; 541 | } 542 | } 543 | SD_send_command(SD_SET_BLK_LEN, 512); 544 | sdtype = SDTYPE_SD; 545 | } 546 | } 547 | 548 | Xchg(0xff); // send 8 final clocks 549 | 550 | /* 551 | * At this point, the SD card has completed initialization. The calling routine 552 | * could now increase the SPI clock rate for the SD card to the maximum allowed by 553 | * the SD card (typically, 20 MHz). 554 | */ 555 | 556 | return SDCARD_OK; // if no power routine or turning off the card, call it good 557 | } 558 | 559 | 560 | 561 | /* 562 | * ReadCSD() 563 | * Reads the CSD from the card, storing it in csd[]. 564 | */ 565 | static uint8_t ReadCSD(void) 566 | { 567 | uint8_t i; 568 | uint8_t response; 569 | 570 | for (i=0; i<16; i++) 571 | { 572 | csd[i] = 0; 573 | } 574 | 575 | response = SD_send_command(SD_SEND_CSD, 0); 576 | response = SD_wait_for_data(); 577 | if (response != 0xfe) 578 | { 579 | return SDCARD_RWFAIL; 580 | } 581 | 582 | for (i=0; i<16; i++) 583 | { 584 | csd[i] = Xchg(0xff); 585 | } 586 | 587 | Xchg(0xff); // burn the CRC 588 | return SDCARD_OK; 589 | } 590 | 591 | 592 | 593 | /* 594 | * WriteCSD() 595 | * Writes csd[] to the CSD on the card. 596 | */ 597 | static uint8_t WriteCSD(void) 598 | { 599 | uint8_t response; 600 | uint8_t tcrc; 601 | uint16_t i; 602 | 603 | response = SD_send_command(SD_PROGRAM_CSD, 0); 604 | if (response != 0) 605 | { 606 | return SDCARD_RWFAIL; 607 | } 608 | 609 | Xchg(0xfe); // send data token marking start of data block 610 | 611 | tcrc = 0; 612 | for (i=0; i<15; i++) // for all 15 data bytes in CSD... 613 | { 614 | Xchg(csd[i]); // send each byte via SPI 615 | tcrc = AddByteToCRC(tcrc, csd[i]); // add byte to CRC 616 | } 617 | Xchg((tcrc<<1) + 1); // format the CRC7 value and send it 618 | 619 | Xchg(0xff); // ignore dummy checksum 620 | Xchg(0xff); // ignore dummy checksum 621 | 622 | i = 0xffff; // max timeout 623 | while (!Xchg(0xff) && (--i)); // wait until we are not busy 624 | 625 | if (i) 626 | { 627 | return SDCARD_OK; // return success 628 | } 629 | else 630 | { 631 | return SDCARD_TIMEOUT; // nope, didn't work 632 | } 633 | } 634 | 635 | 636 | 637 | static void GenerateCRCTable(void) 638 | { 639 | uint16_t i, j; 640 | 641 | // generate a table value for all 256 possible byte values 642 | for (i=0; i<256; i++) 643 | { 644 | crctable[i] = (i & 0x80) ? i ^ CRC7_POLY : i; 645 | for (j=1; j<8; j++) 646 | { 647 | crctable[i] <<= 1; 648 | if (crctable[i] & 0x80) 649 | { 650 | crctable[i] ^= CRC7_POLY; 651 | } 652 | } 653 | } 654 | } 655 | 656 | 657 | 658 | static uint8_t AddByteToCRC(uint8_t crc, uint8_t b) 659 | { 660 | return crctable[(crc << 1) ^ b]; 661 | } 662 | 663 | 664 | 665 | 666 | /* 667 | * SD_send_command(command, arg) 668 | * Sends a raw command to SD card, returns the response. 669 | * 670 | * This routine accepts a single SD command and a 4-byte argument. It sends 671 | * the command plus argument, adding the appropriate CRC. It then returns 672 | * the one-byte response from the SD card. 673 | * 674 | * For advanced commands (those with a command byte having bit 7 set), this 675 | * routine automatically sends the required preface command (CMD55) before 676 | * sending the requested command. 677 | * 678 | * Upon exit, this routine returns the response byte from the SD card. 679 | * Possible responses are: 680 | * 0xff No response from card; card might actually be missing 681 | * 0x01 SD card returned 0x01, which is OK for most commands 682 | * 0x?? other responses are command-specific 683 | */ 684 | static uint8_t SD_send_command(uint8_t command, uint32_t arg) 685 | { 686 | uint8_t response; 687 | uint8_t i; 688 | uint8_t crc; 689 | 690 | if (command & 0x80) // special case, ACMD(n) is sent as CMD55 and CMDn 691 | { 692 | command = command & 0x7f; // strip high bit for later 693 | response = SD_send_command(CMD55, 0); // send first part (recursion) 694 | if (response > 1) 695 | { 696 | return response; 697 | } 698 | } 699 | 700 | Deselect(); 701 | Xchg(0xff); 702 | Select(); // enable CS 703 | Xchg(0xff); 704 | 705 | Xchg(command | 0x40); // command always has bit 6 set! 706 | Xchg((uint8_t)(arg>>24)); // send data, starting with top byte 707 | Xchg((uint8_t)(arg>>16)); 708 | Xchg((uint8_t)(arg>>8)); 709 | Xchg((uint8_t)(arg&0xff)); 710 | crc = 0x01; // good for most cases 711 | 712 | if (command == SD_GO_IDLE) 713 | { 714 | crc = 0x95; // this will be good enough for most commands 715 | } 716 | if (command == SD_SEND_IF_COND) 717 | { 718 | crc = 0x87; // special case, have to use different CRC 719 | } 720 | 721 | Xchg(crc); // send final byte 722 | 723 | for (i=0; i<10; i++) // loop until timeout or response 724 | { 725 | response = Xchg(0xff); 726 | if ((response & 0x80) == 0) 727 | { 728 | break; // high bit cleared means we got a response 729 | } 730 | } 731 | 732 | /* 733 | * We have issued the command but the SD card is still selected. We 734 | * only deselect the card if the command we just sent is NOT a command 735 | * that requires additional data exchange, such as reading or writing 736 | * a block. 737 | */ 738 | if ((command != SD_READ_BLK) && 739 | (command != SD_READ_OCR) && 740 | (command != SD_SEND_CSD) && 741 | (command != SD_SEND_STATUS) && 742 | (command != SD_SEND_CID) && 743 | (command != SD_SEND_IF_COND) && 744 | (command != SD_LOCK_UNLOCK) && 745 | (command != SD_PROGRAM_CSD)) 746 | { 747 | Deselect(); // all done 748 | Xchg(0xff); // close with eight more clocks 749 | } 750 | 751 | return response; // let the caller sort it out 752 | } 753 | 754 | 755 | static uint8_t SD_wait_for_data(void) 756 | { 757 | uint8_t i; 758 | uint8_t r; 759 | 760 | for (i=0; i<100; i++) 761 | { 762 | r = Xchg(0xff); 763 | if (r != 0xff) 764 | { 765 | break; 766 | } 767 | } 768 | return r; 769 | } 770 | -------------------------------------------------------------------------------- /sdlocker-tiny.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nephiel/sdlocker-tiny/0171516190017cc0d1c632b57906e7192eac2bfa/sdlocker-tiny.elf -------------------------------------------------------------------------------- /sdlocker-tiny.hex: -------------------------------------------------------------------------------- 1 | :100000000EC01DC01CC01BC01AC019C018C017C02C 2 | :1000100016C015C014C013C012C011C010C01124E6 3 | :100020001FBECFE5D2E0DEBFCDBF11E0A0E6B0E05D 4 | :1000300001C01D92A538B107E1F752D1EEC1E0CF62 5 | :10004000C49ABC98C49A81E0B49980E0BC9A90911B 6 | :10005000730094FDC4980895C39A089598E087FFAB 7 | :1000600002C0C09A01C0C098C29A880FB19B02C05A 8 | :10007000816001C08E7FC298915089F70895CF9218 9 | :10008000DF92EF92FF920F931F93182F042FF52EFC 10 | :10009000E62ED72E87FF09C087E740E050E0BA017F 11 | :1000A000EEDFC82E8230B8F51F77D6DF8FEFD6DFB0 12 | :1000B000C3988FEFD3DF812F8064D0DF8D2DCEDF0B 13 | :1000C0008E2DCCDF8F2DCADF802FC8DF103421F0BA 14 | :1000D000183421F081E003C085E901C087E8BEDF64 15 | :1000E0000AE08FEFBBDFC82E87FF02C00150C9F7BF 16 | :1000F000113589F01A3779F0193469F01D3459F047 17 | :100100001A3449F0183439F01A3629F01B3519F031 18 | :10011000A3DF8FEFA3DF8C2D1F910F91FF90EF9046 19 | :10012000DF90CF900895CF93DF931092640094DF17 20 | :10013000CAE0D0E08FEF92DF2197E1F7CAE0D0E08C 21 | :1001400080E440E050E0BA019ADF813021F021974D 22 | :10015000B9F781E040C088E44AEA51E060E070E02D 23 | :100160008EDF8130A1F4C4E0D0E08FEF77DF2197FC 24 | :10017000E1F7C0E2DEE489EE40E050E060E070E4E8 25 | :100180007EDF882311F02197B1F782E01FC08AE754 26 | :1001900040E050E0BA0173DF8130D1F4C4E0D0E038 27 | :1001A0008FEF5CDF2197E1F7C0E2DEE481E440E01D 28 | :1001B00050E0BA0164DF882311F02197B9F780E598 29 | :1001C00040E052E060E070E05ADF81E0809364003C 30 | :1001D0008FEF44DF80E0DF91CF9108951F93CF939D 31 | :1001E000DF93C5E6D0E0FE01119280E0E537F80725 32 | :1001F000D9F789E440E050E0BA0141DF14E68FEF1F 33 | :100200002DDF8F3F19F41150D1F70DC08E3F59F4F7 34 | :100210008FEF24DF899380E0C537D807C9F78FEFC8 35 | :100220001DDF80E001C083E0DF91CF911F91089531 36 | :10023000E0E297FF02C0C49801C0C49A2FEB3AEDE8 37 | :1002400040E0215030404040E1F700C00000660F20 38 | :10025000771F881F991F611571058105910511F0A0 39 | :10026000E15039F7089505C060E070E080E090EA61 40 | :10027000DFDF59DF8823C1F705C060E070E080E070 41 | :1002800095EAD6DFABDF8823C1F70895809173002C 42 | :1002900084FF05C060E070E080E090E803C060E0AB 43 | :1002A00070E0CB01C5DF08950F931F93182FC8DEB0 44 | :1002B000082F811789F415E08FEF90E7A2E08150B5 45 | :1002C0009040A040E1F700C00000BADE801721F4A2 46 | :1002D000115091F781E001C080E01F910F910895C6 47 | :1002E000EF92FF920F931F93CF93DF9388B38560B4 48 | :1002F00088BB87B38D6087BBC19AAEDEE5E8F0E0CE 49 | :1003000080E090E059E887FF03C0482F452701C0EF 50 | :10031000482F408327E030E0440F47FD4527215018 51 | :100320003040D1F74193019621E08030920759F790 52 | :10033000BC9A60E070E08BE494E87ADF94DFA6DF9B 53 | :1003400081E0B2DF8823D9F38091730040E1F42E7D 54 | :10035000F82284FF02C08F7E01C080618093730009 55 | :100360008BE540E050E0BA018ADE882359F58EEF34 56 | :1003700075DEC5E6D0E0EE248E0189916FDEEE2DAC 57 | :10038000F0E0EE0FFF1FD8018C9190E0E827F927ED 58 | :10039000EB57FF4FE080B0E0C437DB0769F78E2DE5 59 | :1003A000880F8F5F5BDE8FEF59DE8FEF57DECFEF69 60 | :1003B000DFEF8FEF53DE882319F42197D1F702C0C6 61 | :1003C000209761F46FE070E0CB0132DF6FE070E006 62 | :1003D000CB012EDF6FE070E0CB012ADF44DF80919C 63 | :1003E000730080718F1561F463E070E0CB0120DF52 64 | :1003F00063E070E0CB011CDF63E070E0CB0118DF4D 65 | :1004000045DF06C08FE493EC0197F1F700C00000D0 66 | :0E04100080E04ADF8823B1F392CFF894FFCF4B 67 | :00000001FF 68 | -------------------------------------------------------------------------------- /sdlocker-tiny.lst: -------------------------------------------------------------------------------- 1 | 1 .file "sdlocker-tiny.cpp" 2 | 2 __SREG__ = 0x3f 3 | 3 __SP_H__ = 0x3e 4 | 4 __SP_L__ = 0x3d 5 | 5 __CCP__ = 0x34 6 | 6 __tmp_reg__ = 0 7 | 7 __zero_reg__ = 1 8 | 8 .stabs "/home/nephiel/documents/arduino/sdlocker-tiny/",100,0,4,.Ltext0 9 | 9 .stabs "sdlocker-tiny.cpp",100,0,4,.Ltext0 10 | 10 .text 11 | 11 .Ltext0: 12 | 12 .stabs "gcc2_compiled.",60,0,0,0 13 | 13 .stabs "__builtin_va_list:t(0,1)=*(0,2)=(0,2)",128,0,0,0 14 | 14 .stabs "complex long double:t(0,3)=R3;8;0;",128,0,0,0 15 | 15 .stabs "complex double:t(0,4)=R3;8;0;",128,0,0,0 16 | 16 .stabs "complex float:t(0,5)=R3;8;0;",128,0,0,0 17 | 17 .stabs "complex int:t(0,6)=s4real:(0,7)=r(0,7);-32768;32767;,0,16;imag:(0,7),16,16;;",128,0,0,0 18 | 18 .stabs "long long unsigned int:t(0,8)=@s64;r(0,8);0;01777777777777777777777;",128,0,0,0 19 | 19 .stabs "long unsigned int:t(0,9)=@s32;r(0,9);0;037777777777;",128,0,0,0 20 | 20 .stabs "unsigned int:t(0,10)=r(0,10);0;0177777;",128,0,0,0 21 | 21 .stabs "unsigned char:t(0,11)=@s8;r(0,11);0;255;",128,0,0,0 22 | 22 .stabs "long long int:t(0,12)=@s64;r(0,12);01000000000000000000000;0777777777777777777777;",128,0, 23 | 23 .stabs "long int:t(0,13)=@s32;r(0,13);020000000000;017777777777;",128,0,0,0 24 | 24 .stabs "int:t(0,7)",128,0,0,0 25 | 25 .stabs "signed char:t(0,14)=@s8;r(0,14);-128;127;",128,0,0,0 26 | 26 .stabs "char:t(0,15)=r(0,15);0;127;",128,0,0,0 27 | 27 .stabs "signed:t(0,7)",128,0,0,0 28 | 28 .stabs "unsigned long:t(0,9)",128,0,0,0 29 | 29 .stabs "long long unsigned:t(0,8)",128,0,0,0 30 | 30 .stabs "short int:t(0,16)=r(0,16);-32768;32767;",128,0,0,0 31 | 31 .stabs "short unsigned int:t(0,17)=r(0,17);0;0177777;",128,0,0,0 32 | 32 .stabs "unsigned short:t(0,17)",128,0,0,0 33 | 33 .stabs "float:t(0,18)=r(0,7);4;0;",128,0,0,0 34 | 34 .stabs "double:t(0,19)=r(0,7);4;0;",128,0,0,0 35 | 35 .stabs "long double:t(0,20)=r(0,7);4;0;",128,0,0,0 36 | 36 .stabs "void:t(0,2)",128,0,0,0 37 | 37 .stabs "wchar_t:t(0,21)=r(0,21);-32768;32767;",128,0,0,0 38 | 38 .stabs "bool:t(0,22)=@s8;-16;",128,0,0,0 39 | 39 .stabs "__vtbl_ptr_type:t(0,23)=*(0,24)=f(0,7)",128,0,0,0 40 | 40 .stabs "int8_t:t(0,25)=(0,14)",128,0,121,0 41 | 41 .stabs "uint8_t:t(0,26)=(0,11)",128,0,122,0 42 | 42 .stabs "int16_t:t(0,27)=(0,7)",128,0,123,0 43 | 43 .stabs "uint16_t:t(0,28)=(0,10)",128,0,124,0 44 | 44 .stabs "int32_t:t(0,29)=(0,13)",128,0,125,0 45 | 45 .stabs "uint32_t:t(0,30)=(0,9)",128,0,126,0 46 | 46 .stabs "int64_t:t(0,31)=(0,12)",128,0,128,0 47 | 47 .stabs "uint64_t:t(0,32)=(0,8)",128,0,129,0 48 | 48 .stabs "intptr_t:t(0,33)=(0,27)",128,0,142,0 49 | 49 .stabs "uintptr_t:t(0,34)=(0,28)",128,0,147,0 50 | 50 .stabs "int_least8_t:t(0,35)=(0,25)",128,0,159,0 51 | 51 .stabs "uint_least8_t:t(0,36)=(0,26)",128,0,164,0 52 | 52 .stabs "int_least16_t:t(0,37)=(0,27)",128,0,169,0 53 | 53 .stabs "uint_least16_t:t(0,38)=(0,28)",128,0,174,0 54 | 54 .stabs "int_least32_t:t(0,39)=(0,29)",128,0,179,0 55 | 55 .stabs "uint_least32_t:t(0,40)=(0,30)",128,0,184,0 56 | 56 .stabs "int_least64_t:t(0,41)=(0,31)",128,0,192,0 57 | 57 .stabs "uint_least64_t:t(0,42)=(0,32)",128,0,199,0 58 | 58 .stabs "int_fast8_t:t(0,43)=(0,25)",128,0,213,0 59 | 59 .stabs "uint_fast8_t:t(0,44)=(0,26)",128,0,218,0 60 | 60 .stabs "int_fast16_t:t(0,45)=(0,27)",128,0,223,0 61 | 61 .stabs "uint_fast16_t:t(0,46)=(0,28)",128,0,228,0 62 | 62 .stabs "int_fast32_t:t(0,47)=(0,29)",128,0,233,0 63 | 63 .stabs "uint_fast32_t:t(0,48)=(0,30)",128,0,238,0 64 | 64 .stabs "int_fast64_t:t(0,49)=(0,31)",128,0,246,0 65 | 65 .stabs "uint_fast64_t:t(0,50)=(0,32)",128,0,253,0 66 | 66 .stabs "intmax_t:t(0,51)=(0,31)",128,0,273,0 67 | 67 .stabs "uintmax_t:t(0,52)=(0,32)",128,0,278,0 68 | 68 .stabs "int_farptr_t:t(0,53)=(0,29)",128,0,77,0 69 | 69 .stabs "uint_farptr_t:t(0,54)=(0,30)",128,0,81,0 70 | 70 .stabs "__gnuc_va_list:t(0,55)=(0,1)",128,0,40,0 71 | 71 .stabs "va_list:t(0,56)=(0,55)",128,0,102,0 72 | 72 .stabs "size_t:t(0,57)=(0,10)",128,0,211,0 73 | 73 .stabs "__file:Tt(0,58)=s14buf:(0,59)=*(0,15),0,16;unget:(0,11),16,8;flags:(0,26),24,8;size:(0,7), 74 | 74 .stabs "._0:Tt(0,65)=s4quot:(0,7),0,16;rem:(0,7),16,16;;",128,0,68,0 75 | 75 .stabs "div_t:t(0,65)",128,0,71,0 76 | 76 .stabs "._1:Tt(0,66)=s8quot:(0,13),0,32;rem:(0,13),32,32;;",128,0,74,0 77 | 77 .stabs "ldiv_t:t(0,66)",128,0,77,0 78 | 78 .stabs "__compar_fn_t:t(0,67)=(0,68)=*(0,69)=f(0,7)",128,0,80,0 79 | 79 .stabs "._2:Tt(0,70)=s3low:(0,11),0,8;high:(0,11),8,8;extended:(0,11),16,8;;",128,0,240,0 80 | 80 .stabs "__fuse_t:t(0,70)",128,0,244,0 81 | 81 .stabs "prog_void:t(0,71)=(0,72)=(0,72)",128,0,217,0 82 | 82 .stabs "prog_char:t(0,73)=(0,74)=@s8;r(0,74);-128;127;",128,0,218,0 83 | 83 .stabs "prog_uchar:t(0,75)=(0,76)=@s8;r(0,76);0;255;",128,0,219,0 84 | 84 .stabs "prog_int8_t:t(0,77)=(0,78)=(0,14)",128,0,221,0 85 | 85 .stabs "prog_uint8_t:t(0,79)=(0,80)=(0,11)",128,0,222,0 86 | 86 .stabs "prog_int16_t:t(0,81)=(0,82)=(0,7)",128,0,223,0 87 | 87 .stabs "prog_uint16_t:t(0,83)=(0,84)=(0,10)",128,0,224,0 88 | 88 .stabs "prog_int32_t:t(0,85)=(0,86)=(0,13)",128,0,225,0 89 | 89 .stabs "prog_uint32_t:t(0,87)=(0,88)=(0,9)",128,0,226,0 90 | 90 .stabs "prog_int64_t:t(0,89)=(0,90)=(0,12)",128,0,228,0 91 | 91 .stabs "prog_uint64_t:t(0,91)=(0,92)=(0,8)",128,0,229,0 92 | 92 .stabs "_ZL14ReadSwitchOncev:f(0,26)",36,0,291,_ZL14ReadSwitchOncev 93 | 93 .type _ZL14ReadSwitchOncev, @function 94 | 94 _ZL14ReadSwitchOncev: 95 | 95 .stabd 46,0,0 96 | 1:sdlocker-tiny.cpp **** /* 97 | 2:sdlocker-tiny.cpp **** * sdlocker-tiny Lock/unlock an SD card, uses ATTINY85 98 | 3:sdlocker-tiny.cpp **** * By Nephiel 99 | 4:sdlocker-tiny.cpp **** * 100 | 5:sdlocker-tiny.cpp **** * Based on sdlocker by karllunt (http://www.seanet.com/~karllunt/sdlocker.html) 101 | 6:sdlocker-tiny.cpp **** * 102 | 7:sdlocker-tiny.cpp **** * 103 | 8:sdlocker-tiny.cpp **** * ATMEL ATTINY85 104 | 9:sdlocker-tiny.cpp **** * +-v-+ 105 | 10:sdlocker-tiny.cpp **** * nc PB5 1| |8 Vcc --- +3.3V 106 | 11:sdlocker-tiny.cpp **** * CS <-- PB3 2| |7 PB2 --> SCK 107 | 12:sdlocker-tiny.cpp **** * LEDSW <-> PB4 3| |6 PB1 <-- MISO 108 | 13:sdlocker-tiny.cpp **** * GND --- GND 4| |5 PB0 --> MOSI 109 | 14:sdlocker-tiny.cpp **** * +---+ 110 | 15:sdlocker-tiny.cpp **** * 111 | 16:sdlocker-tiny.cpp **** * 112 | 17:sdlocker-tiny.cpp **** * LEDSW--+ 113 | 18:sdlocker-tiny.cpp **** * | 114 | 19:sdlocker-tiny.cpp **** * +3.3V R1 LED | R2 Switch 115 | 20:sdlocker-tiny.cpp **** * Vcc----\/\/\---[>|---+---\/\/\---[*]----GND 116 | 21:sdlocker-tiny.cpp **** * 300 300 117 | 22:sdlocker-tiny.cpp **** * 118 | 23:sdlocker-tiny.cpp **** * 119 | 24:sdlocker-tiny.cpp **** * SD CARD 120 | 25:sdlocker-tiny.cpp **** * _______ 121 | 26:sdlocker-tiny.cpp **** * [ 9 ] \ rsv nc 122 | 27:sdlocker-tiny.cpp **** * [ 1 ] | CS <-- CS 123 | 28:sdlocker-tiny.cpp **** * [ 2 ] | DI <-- MOSI 124 | 29:sdlocker-tiny.cpp **** * [ 3 ] | GND --- GND 125 | 30:sdlocker-tiny.cpp **** * [ 4 ] | Vcc --- +3.3V 126 | 31:sdlocker-tiny.cpp **** * [ 5 ] | CLK <-- SCK 127 | 32:sdlocker-tiny.cpp **** * [ 6 ] | GND --- GND 128 | 33:sdlocker-tiny.cpp **** * [ 7 ] | DO --> MISO 129 | 34:sdlocker-tiny.cpp **** * [ 8 ] | rsv nc 130 | 35:sdlocker-tiny.cpp **** * --------+ 131 | 36:sdlocker-tiny.cpp **** * 132 | 37:sdlocker-tiny.cpp **** * 133 | 38:sdlocker-tiny.cpp **** * ADDITIONAL NOTES 134 | 39:sdlocker-tiny.cpp **** * 135 | 40:sdlocker-tiny.cpp **** * You might need to change the fuses on the ATTINY85: 136 | 41:sdlocker-tiny.cpp **** * lfuse=E2, hfuse=DF, efuse=FF or 01 137 | 42:sdlocker-tiny.cpp **** * 138 | 43:sdlocker-tiny.cpp **** * Use the built-in card-detect switch on the SD card socket 139 | 44:sdlocker-tiny.cpp **** * to cut the power to the circuit when the card is removed. 140 | 45:sdlocker-tiny.cpp **** * 141 | 46:sdlocker-tiny.cpp **** * Use a LM3940 to obtain 3.3V from a 5V source such as USB. 142 | 47:sdlocker-tiny.cpp **** * 143 | 48:sdlocker-tiny.cpp **** */ 144 | 49:sdlocker-tiny.cpp **** 145 | 50:sdlocker-tiny.cpp **** 146 | 51:sdlocker-tiny.cpp **** 147 | 52:sdlocker-tiny.cpp **** #include 148 | 53:sdlocker-tiny.cpp **** #include 149 | 54:sdlocker-tiny.cpp **** #include 150 | 55:sdlocker-tiny.cpp **** #include 151 | 56:sdlocker-tiny.cpp **** #include 152 | 57:sdlocker-tiny.cpp **** #include 153 | 58:sdlocker-tiny.cpp **** #include 154 | 59:sdlocker-tiny.cpp **** #include 155 | 60:sdlocker-tiny.cpp **** #include 156 | 61:sdlocker-tiny.cpp **** #include 157 | 62:sdlocker-tiny.cpp **** 158 | 63:sdlocker-tiny.cpp **** #ifndef FALSE 159 | 64:sdlocker-tiny.cpp **** #define FALSE 0 160 | 65:sdlocker-tiny.cpp **** #define TRUE !FALSE 161 | 66:sdlocker-tiny.cpp **** #endif 162 | 67:sdlocker-tiny.cpp **** 163 | 68:sdlocker-tiny.cpp **** 164 | 69:sdlocker-tiny.cpp **** /* 165 | 70:sdlocker-tiny.cpp **** * Define commands for the SD card 166 | 71:sdlocker-tiny.cpp **** */ 167 | 72:sdlocker-tiny.cpp **** #define SD_GO_IDLE (0x40 + 0) // CMD0 - go to idle state 168 | 73:sdlocker-tiny.cpp **** #define SD_INIT (0x40 + 1) // CMD1 - start initialization 169 | 74:sdlocker-tiny.cpp **** #define SD_SEND_IF_COND (0x40 + 8) // CMD8 - send interface (conditional), works for SDHC only 170 | 75:sdlocker-tiny.cpp **** #define SD_SEND_CSD (0x40 + 9) // CMD9 - send CSD block (16 bytes) 171 | 76:sdlocker-tiny.cpp **** #define SD_SEND_CID (0x40 + 10) // CMD10 - send CID block (16 bytes) 172 | 77:sdlocker-tiny.cpp **** #define SD_SEND_STATUS (0x40 + 13) // CMD13 - send card status 173 | 78:sdlocker-tiny.cpp **** #define SD_SET_BLK_LEN (0x40 + 16) // CMD16 - set length of block in bytes 174 | 79:sdlocker-tiny.cpp **** #define SD_READ_BLK (0x40 + 17) // read single block 175 | 80:sdlocker-tiny.cpp **** #define SD_LOCK_UNLOCK (0x40 + 42) // CMD42 - lock/unlock card 176 | 81:sdlocker-tiny.cpp **** #define CMD55 (0x40 + 55) // multi-byte preface command 177 | 82:sdlocker-tiny.cpp **** #define SD_READ_OCR (0x40 + 58) // read OCR 178 | 83:sdlocker-tiny.cpp **** #define SD_ADV_INIT (0xc0 + 41) // ACMD41, for SDHC cards - advanced start initialization 179 | 84:sdlocker-tiny.cpp **** #define SD_PROGRAM_CSD (0x40 + 27) // CMD27 - get CSD block (15 bytes data + CRC) 180 | 85:sdlocker-tiny.cpp **** 181 | 86:sdlocker-tiny.cpp **** 182 | 87:sdlocker-tiny.cpp **** /* 183 | 88:sdlocker-tiny.cpp **** * Define the lock bit mask within byte 14 of the CSD 184 | 89:sdlocker-tiny.cpp **** */ 185 | 90:sdlocker-tiny.cpp **** #define LOCK_BIT_MASK 0x10 // mask for the lock bit 186 | 91:sdlocker-tiny.cpp **** 187 | 92:sdlocker-tiny.cpp **** 188 | 93:sdlocker-tiny.cpp **** /* 189 | 94:sdlocker-tiny.cpp **** * Define error codes that can be returned by local functions 190 | 95:sdlocker-tiny.cpp **** */ 191 | 96:sdlocker-tiny.cpp **** #define SDCARD_OK 0 // success 192 | 97:sdlocker-tiny.cpp **** #define SDCARD_NOT_DETECTED 1 // unable to detect SD card 193 | 98:sdlocker-tiny.cpp **** #define SDCARD_TIMEOUT 2 // last operation timed out 194 | 99:sdlocker-tiny.cpp **** #define SDCARD_RWFAIL 3 // read/write command failed 195 | 100:sdlocker-tiny.cpp **** 196 | 101:sdlocker-tiny.cpp **** 197 | 102:sdlocker-tiny.cpp **** /* 198 | 103:sdlocker-tiny.cpp **** * Define card types that could be reported by the SD card during probe 199 | 104:sdlocker-tiny.cpp **** */ 200 | 105:sdlocker-tiny.cpp **** #define SDTYPE_UNKNOWN 0 // card type not determined 201 | 106:sdlocker-tiny.cpp **** #define SDTYPE_SD 1 // SD v1 (1 MB to 2 GB) 202 | 107:sdlocker-tiny.cpp **** #define SDTYPE_SDHC 2 // SDHC (4 GB to 32 GB) 203 | 108:sdlocker-tiny.cpp **** 204 | 109:sdlocker-tiny.cpp **** 205 | 110:sdlocker-tiny.cpp **** /* 206 | 111:sdlocker-tiny.cpp **** * Define the port and DDR used by the SPI. 207 | 112:sdlocker-tiny.cpp **** */ 208 | 113:sdlocker-tiny.cpp **** #define SPI_PORT PORTB 209 | 114:sdlocker-tiny.cpp **** #define SPI_DDR DDRB 210 | 115:sdlocker-tiny.cpp **** #define SPI_PIN PINB 211 | 116:sdlocker-tiny.cpp **** 212 | 117:sdlocker-tiny.cpp **** 213 | 118:sdlocker-tiny.cpp **** /* 214 | 119:sdlocker-tiny.cpp **** * Define bits used by the SPI port. 215 | 120:sdlocker-tiny.cpp **** */ 216 | 121:sdlocker-tiny.cpp **** #define MOSI_BIT 0 217 | 122:sdlocker-tiny.cpp **** #define MISO_BIT 1 218 | 123:sdlocker-tiny.cpp **** #define SCK_BIT 2 219 | 124:sdlocker-tiny.cpp **** #define CS_BIT 3 220 | 125:sdlocker-tiny.cpp **** 221 | 126:sdlocker-tiny.cpp **** 222 | 127:sdlocker-tiny.cpp **** /* 223 | 128:sdlocker-tiny.cpp **** * Define the port, DDR, and bit used for the LED and the switch. 224 | 129:sdlocker-tiny.cpp **** * The ATTINY85 doesn't have enough I/O pins so we need to share one. 225 | 130:sdlocker-tiny.cpp **** * Note the LED output is active low. 226 | 131:sdlocker-tiny.cpp **** */ 227 | 132:sdlocker-tiny.cpp **** #define LEDSW_PORT PORTB 228 | 133:sdlocker-tiny.cpp **** #define LEDSW_DDR DDRB 229 | 134:sdlocker-tiny.cpp **** #define LEDSW_PIN PINB 230 | 135:sdlocker-tiny.cpp **** #define LEDSW_BIT 4 231 | 136:sdlocker-tiny.cpp **** #define LEDSW_MASK (1<0; i--) 759 | 517:sdlocker-tiny.cpp **** { 760 | 518:sdlocker-tiny.cpp **** response = SD_send_command(SD_ADV_INIT, 1UL<<30); 761 | 519:sdlocker-tiny.cpp **** if (response == 0) 762 | 520:sdlocker-tiny.cpp **** { 763 | 521:sdlocker-tiny.cpp **** break; 764 | 522:sdlocker-tiny.cpp **** } 765 | 523:sdlocker-tiny.cpp **** } 766 | 524:sdlocker-tiny.cpp **** sdtype = SDTYPE_SDHC; 767 | 525:sdlocker-tiny.cpp **** } 768 | 526:sdlocker-tiny.cpp **** else 769 | 527:sdlocker-tiny.cpp **** { // if card is SD... 770 | 528:sdlocker-tiny.cpp **** response = SD_send_command(SD_READ_OCR, 0); 771 | 529:sdlocker-tiny.cpp **** if (response == 0x01) 772 | 530:sdlocker-tiny.cpp **** { 773 | 531:sdlocker-tiny.cpp **** for (i=0; i<4; i++) // burn the 4-byte response (OCR) 774 | 532:sdlocker-tiny.cpp **** { 775 | 533:sdlocker-tiny.cpp **** Xchg(0xff); 776 | 534:sdlocker-tiny.cpp **** } 777 | 535:sdlocker-tiny.cpp **** for (i=20000; i>0; i--) 778 | 536:sdlocker-tiny.cpp **** { 779 | 537:sdlocker-tiny.cpp **** response = SD_send_command(SD_INIT, 0); 780 | 538:sdlocker-tiny.cpp **** if (response == 0) 781 | 539:sdlocker-tiny.cpp **** { 782 | 540:sdlocker-tiny.cpp **** break; 783 | 541:sdlocker-tiny.cpp **** } 784 | 542:sdlocker-tiny.cpp **** } 785 | 543:sdlocker-tiny.cpp **** SD_send_command(SD_SET_BLK_LEN, 512); 786 | 544:sdlocker-tiny.cpp **** sdtype = SDTYPE_SD; 787 | 545:sdlocker-tiny.cpp **** } 788 | 546:sdlocker-tiny.cpp **** } 789 | 547:sdlocker-tiny.cpp **** 790 | 548:sdlocker-tiny.cpp **** Xchg(0xff); // send 8 final clocks 791 | 549:sdlocker-tiny.cpp **** 792 | 550:sdlocker-tiny.cpp **** /* 793 | 551:sdlocker-tiny.cpp **** * At this point, the SD card has completed initialization. The calling routine 794 | 552:sdlocker-tiny.cpp **** * could now increase the SPI clock rate for the SD card to the maximum allowed by 795 | 553:sdlocker-tiny.cpp **** * the SD card (typically, 20 MHz). 796 | 554:sdlocker-tiny.cpp **** */ 797 | 555:sdlocker-tiny.cpp **** 798 | 556:sdlocker-tiny.cpp **** return SDCARD_OK; // if no power routine or turning off the card, call it good 799 | 557:sdlocker-tiny.cpp **** } 800 | 558:sdlocker-tiny.cpp **** 801 | 559:sdlocker-tiny.cpp **** 802 | 560:sdlocker-tiny.cpp **** 803 | 561:sdlocker-tiny.cpp **** /* 804 | 562:sdlocker-tiny.cpp **** * ReadCSD() 805 | 563:sdlocker-tiny.cpp **** * Reads the CSD from the card, storing it in csd[]. 806 | 564:sdlocker-tiny.cpp **** */ 807 | 565:sdlocker-tiny.cpp **** static uint8_t ReadCSD(void) 808 | 566:sdlocker-tiny.cpp **** { 809 | 567:sdlocker-tiny.cpp **** uint8_t i; 810 | 568:sdlocker-tiny.cpp **** uint8_t response; 811 | 569:sdlocker-tiny.cpp **** 812 | 570:sdlocker-tiny.cpp **** for (i=0; i<16; i++) 813 | 571:sdlocker-tiny.cpp **** { 814 | 572:sdlocker-tiny.cpp **** csd[i] = 0; 815 | 573:sdlocker-tiny.cpp **** } 816 | 574:sdlocker-tiny.cpp **** 817 | 575:sdlocker-tiny.cpp **** response = SD_send_command(SD_SEND_CSD, 0); 818 | 576:sdlocker-tiny.cpp **** response = SD_wait_for_data(); 819 | 577:sdlocker-tiny.cpp **** if (response != 0xfe) 820 | 578:sdlocker-tiny.cpp **** { 821 | 579:sdlocker-tiny.cpp **** return SDCARD_RWFAIL; 822 | 580:sdlocker-tiny.cpp **** } 823 | 581:sdlocker-tiny.cpp **** 824 | 582:sdlocker-tiny.cpp **** for (i=0; i<16; i++) 825 | 583:sdlocker-tiny.cpp **** { 826 | 584:sdlocker-tiny.cpp **** csd[i] = Xchg(0xff); 827 | 585:sdlocker-tiny.cpp **** } 828 | 586:sdlocker-tiny.cpp **** 829 | 587:sdlocker-tiny.cpp **** Xchg(0xff); // burn the CRC 830 | 588:sdlocker-tiny.cpp **** return SDCARD_OK; 831 | 589:sdlocker-tiny.cpp **** } 832 | 590:sdlocker-tiny.cpp **** 833 | 591:sdlocker-tiny.cpp **** 834 | 592:sdlocker-tiny.cpp **** 835 | 593:sdlocker-tiny.cpp **** /* 836 | 594:sdlocker-tiny.cpp **** * WriteCSD() 837 | 595:sdlocker-tiny.cpp **** * Writes csd[] to the CSD on the card. 838 | 596:sdlocker-tiny.cpp **** */ 839 | 597:sdlocker-tiny.cpp **** static uint8_t WriteCSD(void) 840 | 598:sdlocker-tiny.cpp **** { 841 | 599:sdlocker-tiny.cpp **** uint8_t response; 842 | 600:sdlocker-tiny.cpp **** uint8_t tcrc; 843 | 601:sdlocker-tiny.cpp **** uint16_t i; 844 | 602:sdlocker-tiny.cpp **** 845 | 603:sdlocker-tiny.cpp **** response = SD_send_command(SD_PROGRAM_CSD, 0); 846 | 604:sdlocker-tiny.cpp **** if (response != 0) 847 | 605:sdlocker-tiny.cpp **** { 848 | 606:sdlocker-tiny.cpp **** return SDCARD_RWFAIL; 849 | 607:sdlocker-tiny.cpp **** } 850 | 608:sdlocker-tiny.cpp **** 851 | 609:sdlocker-tiny.cpp **** Xchg(0xfe); // send data token marking start of data block 852 | 610:sdlocker-tiny.cpp **** 853 | 611:sdlocker-tiny.cpp **** tcrc = 0; 854 | 612:sdlocker-tiny.cpp **** for (i=0; i<15; i++) // for all 15 data bytes in CSD... 855 | 613:sdlocker-tiny.cpp **** { 856 | 614:sdlocker-tiny.cpp **** Xchg(csd[i]); // send each byte via SPI 857 | 615:sdlocker-tiny.cpp **** tcrc = AddByteToCRC(tcrc, csd[i]); // add byte to CRC 858 | 616:sdlocker-tiny.cpp **** } 859 | 617:sdlocker-tiny.cpp **** Xchg((tcrc<<1) + 1); // format the CRC7 value and send it 860 | 618:sdlocker-tiny.cpp **** 861 | 619:sdlocker-tiny.cpp **** Xchg(0xff); // ignore dummy checksum 862 | 620:sdlocker-tiny.cpp **** Xchg(0xff); // ignore dummy checksum 863 | 621:sdlocker-tiny.cpp **** 864 | 622:sdlocker-tiny.cpp **** i = 0xffff; // max timeout 865 | 623:sdlocker-tiny.cpp **** while (!Xchg(0xff) && (--i)); // wait until we are not busy 866 | 624:sdlocker-tiny.cpp **** 867 | 625:sdlocker-tiny.cpp **** if (i) 868 | 626:sdlocker-tiny.cpp **** { 869 | 627:sdlocker-tiny.cpp **** return SDCARD_OK; // return success 870 | 628:sdlocker-tiny.cpp **** } 871 | 629:sdlocker-tiny.cpp **** else 872 | 630:sdlocker-tiny.cpp **** { 873 | 631:sdlocker-tiny.cpp **** return SDCARD_TIMEOUT; // nope, didn't work 874 | 632:sdlocker-tiny.cpp **** } 875 | 633:sdlocker-tiny.cpp **** } 876 | 634:sdlocker-tiny.cpp **** 877 | 635:sdlocker-tiny.cpp **** 878 | 636:sdlocker-tiny.cpp **** 879 | 637:sdlocker-tiny.cpp **** static void GenerateCRCTable(void) 880 | 638:sdlocker-tiny.cpp **** { 881 | 639:sdlocker-tiny.cpp **** uint16_t i, j; 882 | 640:sdlocker-tiny.cpp **** 883 | 641:sdlocker-tiny.cpp **** // generate a table value for all 256 possible byte values 884 | 642:sdlocker-tiny.cpp **** for (i=0; i<256; i++) 885 | 643:sdlocker-tiny.cpp **** { 886 | 644:sdlocker-tiny.cpp **** crctable[i] = (i & 0x80) ? i ^ CRC7_POLY : i; 887 | 645:sdlocker-tiny.cpp **** for (j=1; j<8; j++) 888 | 646:sdlocker-tiny.cpp **** { 889 | 647:sdlocker-tiny.cpp **** crctable[i] <<= 1; 890 | 648:sdlocker-tiny.cpp **** if (crctable[i] & 0x80) 891 | 649:sdlocker-tiny.cpp **** { 892 | 650:sdlocker-tiny.cpp **** crctable[i] ^= CRC7_POLY; 893 | 651:sdlocker-tiny.cpp **** } 894 | 652:sdlocker-tiny.cpp **** } 895 | 653:sdlocker-tiny.cpp **** } 896 | 654:sdlocker-tiny.cpp **** } 897 | 655:sdlocker-tiny.cpp **** 898 | 656:sdlocker-tiny.cpp **** 899 | 657:sdlocker-tiny.cpp **** 900 | 658:sdlocker-tiny.cpp **** static uint8_t AddByteToCRC(uint8_t crc, uint8_t b) 901 | 659:sdlocker-tiny.cpp **** { 902 | 660:sdlocker-tiny.cpp **** return crctable[(crc << 1) ^ b]; 903 | 661:sdlocker-tiny.cpp **** } 904 | 662:sdlocker-tiny.cpp **** 905 | 663:sdlocker-tiny.cpp **** 906 | 664:sdlocker-tiny.cpp **** 907 | 665:sdlocker-tiny.cpp **** 908 | 666:sdlocker-tiny.cpp **** /* 909 | 667:sdlocker-tiny.cpp **** * SD_send_command(command, arg) 910 | 668:sdlocker-tiny.cpp **** * Sends a raw command to SD card, returns the response. 911 | 669:sdlocker-tiny.cpp **** * 912 | 670:sdlocker-tiny.cpp **** * This routine accepts a single SD command and a 4-byte argument. It sends 913 | 671:sdlocker-tiny.cpp **** * the command plus argument, adding the appropriate CRC. It then returns 914 | 672:sdlocker-tiny.cpp **** * the one-byte response from the SD card. 915 | 673:sdlocker-tiny.cpp **** * 916 | 674:sdlocker-tiny.cpp **** * For advanced commands (those with a command byte having bit 7 set), this 917 | 675:sdlocker-tiny.cpp **** * routine automatically sends the required preface command (CMD55) before 918 | 676:sdlocker-tiny.cpp **** * sending the requested command. 919 | 677:sdlocker-tiny.cpp **** * 920 | 678:sdlocker-tiny.cpp **** * Upon exit, this routine returns the response byte from the SD card. 921 | 679:sdlocker-tiny.cpp **** * Possible responses are: 922 | 680:sdlocker-tiny.cpp **** * 0xff No response from card; card might actually be missing 923 | 681:sdlocker-tiny.cpp **** * 0x01 SD card returned 0x01, which is OK for most commands 924 | 682:sdlocker-tiny.cpp **** * 0x?? other responses are command-specific 925 | 683:sdlocker-tiny.cpp **** */ 926 | 684:sdlocker-tiny.cpp **** static uint8_t SD_send_command(uint8_t command, uint32_t arg) 927 | 685:sdlocker-tiny.cpp **** { 928 | 239 .stabn 68,0,685,.LM26-.LFBB4 929 | 240 .LM26: 930 | 241 .LFBB4: 931 | 242 003e CF92 push r12 932 | 243 0040 DF92 push r13 933 | 244 0042 EF92 push r14 934 | 245 0044 FF92 push r15 935 | 246 0046 0F93 push r16 936 | 247 0048 1F93 push r17 937 | 248 /* prologue: function */ 938 | 249 /* frame size = 0 */ 939 | 250 /* stack size = 6 */ 940 | 251 .L__stack_usage = 6 941 | 252 004a 182F mov r17,r24 942 | 253 004c 042F mov r16,r20 943 | 254 004e F52E mov r15,r21 944 | 255 0050 E62E mov r14,r22 945 | 256 0052 D72E mov r13,r23 946 | 257 .LBB48: 947 | 686:sdlocker-tiny.cpp **** uint8_t response; 948 | 687:sdlocker-tiny.cpp **** uint8_t i; 949 | 688:sdlocker-tiny.cpp **** uint8_t crc; 950 | 689:sdlocker-tiny.cpp **** 951 | 690:sdlocker-tiny.cpp **** if (command & 0x80) // special case, ACMD(n) is sent as CMD55 and CMDn 952 | 258 .stabn 68,0,690,.LM27-.LFBB4 953 | 259 .LM27: 954 | 260 0054 87FF sbrs r24,7 955 | 261 0056 00C0 rjmp .L13 956 | 691:sdlocker-tiny.cpp **** { 957 | 692:sdlocker-tiny.cpp **** command = command & 0x7f; // strip high bit for later 958 | 693:sdlocker-tiny.cpp **** response = SD_send_command(CMD55, 0); // send first part (recursion) 959 | 262 .stabn 68,0,693,.LM28-.LFBB4 960 | 263 .LM28: 961 | 264 0058 87E7 ldi r24,lo8(119) 962 | 265 005a 40E0 ldi r20,lo8(0) 963 | 266 005c 50E0 ldi r21,hi8(0) 964 | 267 005e BA01 movw r22,r20 965 | 268 0060 00D0 rcall _ZL15SD_send_commandhm 966 | 269 0062 C82E mov r12,r24 967 | 694:sdlocker-tiny.cpp **** if (response > 1) 968 | 270 .stabn 68,0,694,.LM29-.LFBB4 969 | 271 .LM29: 970 | 272 0064 8230 cpi r24,lo8(2) 971 | 273 0066 00F4 brsh .L14 972 | 692:sdlocker-tiny.cpp **** command = command & 0x7f; // strip high bit for later 973 | 274 .stabn 68,0,692,.LM30-.LFBB4 974 | 275 .LM30: 975 | 276 0068 1F77 andi r17,lo8(127) 976 | 277 .L13: 977 | 695:sdlocker-tiny.cpp **** { 978 | 696:sdlocker-tiny.cpp **** return response; 979 | 697:sdlocker-tiny.cpp **** } 980 | 698:sdlocker-tiny.cpp **** } 981 | 699:sdlocker-tiny.cpp **** 982 | 700:sdlocker-tiny.cpp **** Deselect(); 983 | 278 .stabn 68,0,700,.LM31-.LFBB4 984 | 279 .LM31: 985 | 280 006a 00D0 rcall _ZL8Deselectv 986 | 701:sdlocker-tiny.cpp **** Xchg(0xff); 987 | 281 .stabn 68,0,701,.LM32-.LFBB4 988 | 282 .LM32: 989 | 283 006c 8FEF ldi r24,lo8(-1) 990 | 284 006e 00D0 rcall _ZL4Xchgh 991 | 285 .LBB49: 992 | 286 .LBB50: 993 | 433:sdlocker-tiny.cpp **** SPI_PORT &= ~(1<>24)); // send data, starting with top byte 1013 | 301 .stabn 68,0,706,.LM36-.LFBB4 1014 | 302 .LM36: 1015 | 303 007c 8D2D mov r24,r13 1016 | 304 007e 00D0 rcall _ZL4Xchgh 1017 | 707:sdlocker-tiny.cpp **** Xchg((uint8_t)(arg>>16)); 1018 | 305 .stabn 68,0,707,.LM37-.LFBB4 1019 | 306 .LM37: 1020 | 307 0080 8E2D mov r24,r14 1021 | 308 0082 00D0 rcall _ZL4Xchgh 1022 | 708:sdlocker-tiny.cpp **** Xchg((uint8_t)(arg>>8)); 1023 | 309 .stabn 68,0,708,.LM38-.LFBB4 1024 | 310 .LM38: 1025 | 311 0084 8F2D mov r24,r15 1026 | 312 0086 00D0 rcall _ZL4Xchgh 1027 | 709:sdlocker-tiny.cpp **** Xchg((uint8_t)(arg&0xff)); 1028 | 313 .stabn 68,0,709,.LM39-.LFBB4 1029 | 314 .LM39: 1030 | 315 0088 802F mov r24,r16 1031 | 316 008a 00D0 rcall _ZL4Xchgh 1032 | 710:sdlocker-tiny.cpp **** crc = 0x01; // good for most cases 1033 | 711:sdlocker-tiny.cpp **** 1034 | 712:sdlocker-tiny.cpp **** if (command == SD_GO_IDLE) 1035 | 317 .stabn 68,0,712,.LM40-.LFBB4 1036 | 318 .LM40: 1037 | 319 008c 1034 cpi r17,lo8(64) 1038 | 320 008e 01F0 breq .L19 1039 | 713:sdlocker-tiny.cpp **** { 1040 | 714:sdlocker-tiny.cpp **** crc = 0x95; // this will be good enough for most commands 1041 | 715:sdlocker-tiny.cpp **** } 1042 | 716:sdlocker-tiny.cpp **** if (command == SD_SEND_IF_COND) 1043 | 321 .stabn 68,0,716,.LM41-.LFBB4 1044 | 322 .LM41: 1045 | 323 0090 1834 cpi r17,lo8(72) 1046 | 324 0092 01F0 breq .L20 1047 | 710:sdlocker-tiny.cpp **** crc = 0x01; // good for most cases 1048 | 325 .stabn 68,0,710,.LM42-.LFBB4 1049 | 326 .LM42: 1050 | 327 0094 81E0 ldi r24,lo8(1) 1051 | 328 0096 00C0 rjmp .L16 1052 | 329 .L19: 1053 | 714:sdlocker-tiny.cpp **** crc = 0x95; // this will be good enough for most commands 1054 | 330 .stabn 68,0,714,.LM43-.LFBB4 1055 | 331 .LM43: 1056 | 332 0098 85E9 ldi r24,lo8(-107) 1057 | 333 009a 00C0 rjmp .L16 1058 | 334 .L20: 1059 | 717:sdlocker-tiny.cpp **** { 1060 | 718:sdlocker-tiny.cpp **** crc = 0x87; // special case, have to use different CRC 1061 | 335 .stabn 68,0,718,.LM44-.LFBB4 1062 | 336 .LM44: 1063 | 337 009c 87E8 ldi r24,lo8(-121) 1064 | 338 .L16: 1065 | 719:sdlocker-tiny.cpp **** } 1066 | 720:sdlocker-tiny.cpp **** 1067 | 721:sdlocker-tiny.cpp **** Xchg(crc); // send final byte 1068 | 339 .stabn 68,0,721,.LM45-.LFBB4 1069 | 340 .LM45: 1070 | 341 009e 00D0 rcall _ZL4Xchgh 1071 | 342 00a0 0AE0 ldi r16,lo8(10) 1072 | 343 .L18: 1073 | 722:sdlocker-tiny.cpp **** 1074 | 723:sdlocker-tiny.cpp **** for (i=0; i<10; i++) // loop until timeout or response 1075 | 724:sdlocker-tiny.cpp **** { 1076 | 725:sdlocker-tiny.cpp **** response = Xchg(0xff); 1077 | 344 .stabn 68,0,725,.LM46-.LFBB4 1078 | 345 .LM46: 1079 | 346 00a2 8FEF ldi r24,lo8(-1) 1080 | 347 00a4 00D0 rcall _ZL4Xchgh 1081 | 348 00a6 C82E mov r12,r24 1082 | 726:sdlocker-tiny.cpp **** if ((response & 0x80) == 0) 1083 | 349 .stabn 68,0,726,.LM47-.LFBB4 1084 | 350 .LM47: 1085 | 351 00a8 87FF sbrs r24,7 1086 | 352 00aa 00C0 rjmp .L17 1087 | 353 00ac 0150 subi r16,lo8(-(-1)) 1088 | 723:sdlocker-tiny.cpp **** for (i=0; i<10; i++) // loop until timeout or response 1089 | 354 .stabn 68,0,723,.LM48-.LFBB4 1090 | 355 .LM48: 1091 | 356 00ae 01F4 brne .L18 1092 | 357 .L17: 1093 | 727:sdlocker-tiny.cpp **** { 1094 | 728:sdlocker-tiny.cpp **** break; // high bit cleared means we got a response 1095 | 729:sdlocker-tiny.cpp **** } 1096 | 730:sdlocker-tiny.cpp **** } 1097 | 731:sdlocker-tiny.cpp **** 1098 | 732:sdlocker-tiny.cpp **** /* 1099 | 733:sdlocker-tiny.cpp **** * We have issued the command but the SD card is still selected. We 1100 | 734:sdlocker-tiny.cpp **** * only deselect the card if the command we just sent is NOT a command 1101 | 735:sdlocker-tiny.cpp **** * that requires additional data exchange, such as reading or writing 1102 | 736:sdlocker-tiny.cpp **** * a block. 1103 | 737:sdlocker-tiny.cpp **** */ 1104 | 738:sdlocker-tiny.cpp **** if ((command != SD_READ_BLK) && 1105 | 358 .stabn 68,0,738,.LM49-.LFBB4 1106 | 359 .LM49: 1107 | 360 00b0 1135 cpi r17,lo8(81) 1108 | 361 00b2 01F0 breq .L14 1109 | 362 .stabn 68,0,738,.LM50-.LFBB4 1110 | 363 .LM50: 1111 | 364 00b4 1A37 cpi r17,lo8(122) 1112 | 365 00b6 01F0 breq .L14 1113 | 366 .stabn 68,0,738,.LM51-.LFBB4 1114 | 367 .LM51: 1115 | 368 00b8 1934 cpi r17,lo8(73) 1116 | 369 00ba 01F0 breq .L14 1117 | 370 .stabn 68,0,738,.LM52-.LFBB4 1118 | 371 .LM52: 1119 | 372 00bc 1D34 cpi r17,lo8(77) 1120 | 373 00be 01F0 breq .L14 1121 | 374 .stabn 68,0,738,.LM53-.LFBB4 1122 | 375 .LM53: 1123 | 376 00c0 1A34 cpi r17,lo8(74) 1124 | 377 00c2 01F0 breq .L14 1125 | 378 .stabn 68,0,738,.LM54-.LFBB4 1126 | 379 .LM54: 1127 | 380 00c4 1834 cpi r17,lo8(72) 1128 | 381 00c6 01F0 breq .L14 1129 | 382 .stabn 68,0,738,.LM55-.LFBB4 1130 | 383 .LM55: 1131 | 384 00c8 1A36 cpi r17,lo8(106) 1132 | 385 00ca 01F0 breq .L14 1133 | 386 .stabn 68,0,738,.LM56-.LFBB4 1134 | 387 .LM56: 1135 | 388 00cc 1B35 cpi r17,lo8(91) 1136 | 389 00ce 01F0 breq .L14 1137 | 739:sdlocker-tiny.cpp **** (command != SD_READ_OCR) && 1138 | 740:sdlocker-tiny.cpp **** (command != SD_SEND_CSD) && 1139 | 741:sdlocker-tiny.cpp **** (command != SD_SEND_STATUS) && 1140 | 742:sdlocker-tiny.cpp **** (command != SD_SEND_CID) && 1141 | 743:sdlocker-tiny.cpp **** (command != SD_SEND_IF_COND) && 1142 | 744:sdlocker-tiny.cpp **** (command != SD_LOCK_UNLOCK) && 1143 | 745:sdlocker-tiny.cpp **** (command != SD_PROGRAM_CSD)) 1144 | 746:sdlocker-tiny.cpp **** { 1145 | 747:sdlocker-tiny.cpp **** Deselect(); // all done 1146 | 390 .stabn 68,0,747,.LM57-.LFBB4 1147 | 391 .LM57: 1148 | 392 00d0 00D0 rcall _ZL8Deselectv 1149 | 748:sdlocker-tiny.cpp **** Xchg(0xff); // close with eight more clocks 1150 | 393 .stabn 68,0,748,.LM58-.LFBB4 1151 | 394 .LM58: 1152 | 395 00d2 8FEF ldi r24,lo8(-1) 1153 | 396 00d4 00D0 rcall _ZL4Xchgh 1154 | 397 .L14: 1155 | 398 .LBE48: 1156 | 749:sdlocker-tiny.cpp **** } 1157 | 750:sdlocker-tiny.cpp **** 1158 | 751:sdlocker-tiny.cpp **** return response; // let the caller sort it out 1159 | 752:sdlocker-tiny.cpp **** } 1160 | 399 .stabn 68,0,752,.LM59-.LFBB4 1161 | 400 .LM59: 1162 | 401 00d6 8C2D mov r24,r12 1163 | 402 /* epilogue start */ 1164 | 403 00d8 1F91 pop r17 1165 | 404 00da 0F91 pop r16 1166 | 405 00dc FF90 pop r15 1167 | 406 00de EF90 pop r14 1168 | 407 00e0 DF90 pop r13 1169 | 408 00e2 CF90 pop r12 1170 | 409 00e4 0895 ret 1171 | 410 .size _ZL15SD_send_commandhm, .-_ZL15SD_send_commandhm 1172 | 411 .stabs "response:r(0,26)",64,0,686,12 1173 | 412 .stabs "crc:r(0,26)",64,0,688,24 1174 | 413 .stabn 192,0,0,.LBB48-.LFBB4 1175 | 414 .stabn 224,0,0,.LBE48-.LFBB4 1176 | 415 .Lscope4: 1177 | 416 .stabs "",36,0,0,.Lscope4-.LFBB4 1178 | 417 .stabd 78,0,0 1179 | 418 .stabs "_ZL6SDInitv:f(0,26)",36,0,479,_ZL6SDInitv 1180 | 419 .type _ZL6SDInitv, @function 1181 | 420 _ZL6SDInitv: 1182 | 421 .stabd 46,0,0 1183 | 480:sdlocker-tiny.cpp **** { 1184 | 422 .stabn 68,0,480,.LM60-.LFBB5 1185 | 423 .LM60: 1186 | 424 .LFBB5: 1187 | 425 00e6 CF93 push r28 1188 | 426 00e8 DF93 push r29 1189 | 427 /* prologue: function */ 1190 | 428 /* frame size = 0 */ 1191 | 429 /* stack size = 2 */ 1192 | 430 .L__stack_usage = 2 1193 | 431 .LBB51: 1194 | 484:sdlocker-tiny.cpp **** sdtype = SDTYPE_UNKNOWN; // assume this fails 1195 | 432 .stabn 68,0,484,.LM61-.LFBB5 1196 | 433 .LM61: 1197 | 434 00ea 1092 0000 sts sdtype,__zero_reg__ 1198 | 490:sdlocker-tiny.cpp **** Deselect(); // always make sure card was not selected 1199 | 435 .stabn 68,0,490,.LM62-.LFBB5 1200 | 436 .LM62: 1201 | 437 00ee 00D0 rcall _ZL8Deselectv 1202 | 438 00f0 CAE0 ldi r28,lo8(10) 1203 | 439 00f2 D0E0 ldi r29,hi8(10) 1204 | 440 .L23: 1205 | 493:sdlocker-tiny.cpp **** Xchg(0xff); 1206 | 441 .stabn 68,0,493,.LM63-.LFBB5 1207 | 442 .LM63: 1208 | 443 00f4 8FEF ldi r24,lo8(-1) 1209 | 444 00f6 00D0 rcall _ZL4Xchgh 1210 | 445 00f8 2197 sbiw r28,1 1211 | 491:sdlocker-tiny.cpp **** for (i=0; i<10; i++) // send several clocks while card power stabilizes 1212 | 446 .stabn 68,0,491,.LM64-.LFBB5 1213 | 447 .LM64: 1214 | 448 00fa 01F4 brne .L23 1215 | 491:sdlocker-tiny.cpp **** for (i=0; i<10; i++) // send several clocks while card power stabilizes 1216 | 449 .stabn 68,0,491,.LM65-.LFBB5 1217 | 450 .LM65: 1218 | 451 00fc CAE0 ldi r28,lo8(10) 1219 | 452 00fe D0E0 ldi r29,hi8(10) 1220 | 453 .L25: 1221 | 498:sdlocker-tiny.cpp **** response = SD_send_command(SD_GO_IDLE, 0); // send CMD0 - go to idle state 1222 | 454 .stabn 68,0,498,.LM66-.LFBB5 1223 | 455 .LM66: 1224 | 456 0100 80E4 ldi r24,lo8(64) 1225 | 457 0102 40E0 ldi r20,lo8(0) 1226 | 458 0104 50E0 ldi r21,hi8(0) 1227 | 459 0106 BA01 movw r22,r20 1228 | 460 0108 00D0 rcall _ZL15SD_send_commandhm 1229 | 499:sdlocker-tiny.cpp **** if (response == 0x01) 1230 | 461 .stabn 68,0,499,.LM67-.LFBB5 1231 | 462 .LM67: 1232 | 463 010a 8130 cpi r24,lo8(1) 1233 | 464 010c 01F0 breq .L24 1234 | 465 010e 2197 sbiw r28,1 1235 | 496:sdlocker-tiny.cpp **** for (i=0; i<10; i++) 1236 | 466 .stabn 68,0,496,.LM68-.LFBB5 1237 | 467 .LM68: 1238 | 468 0110 01F4 brne .L25 1239 | 506:sdlocker-tiny.cpp **** return SDCARD_NOT_DETECTED; 1240 | 469 .stabn 68,0,506,.LM69-.LFBB5 1241 | 470 .LM69: 1242 | 471 0112 81E0 ldi r24,lo8(1) 1243 | 472 0114 00C0 rjmp .L26 1244 | 473 .L24: 1245 | 509:sdlocker-tiny.cpp **** response = SD_send_command(SD_SEND_IF_COND, 0x1aa); // check if card is SDv2 (SDHC) 1246 | 474 .stabn 68,0,509,.LM70-.LFBB5 1247 | 475 .LM70: 1248 | 476 0116 88E4 ldi r24,lo8(72) 1249 | 477 0118 4AEA ldi r20,lo8(426) 1250 | 478 011a 51E0 ldi r21,hi8(426) 1251 | 479 011c 60E0 ldi r22,hlo8(426) 1252 | 480 011e 70E0 ldi r23,hhi8(426) 1253 | 481 0120 00D0 rcall _ZL15SD_send_commandhm 1254 | 510:sdlocker-tiny.cpp **** if (response == 0x01) // if card is SDHC... 1255 | 482 .stabn 68,0,510,.LM71-.LFBB5 1256 | 483 .LM71: 1257 | 484 0122 8130 cpi r24,lo8(1) 1258 | 485 0124 01F4 brne .L27 1259 | 510:sdlocker-tiny.cpp **** if (response == 0x01) // if card is SDHC... 1260 | 486 .stabn 68,0,510,.LM72-.LFBB5 1261 | 487 .LM72: 1262 | 488 0126 C4E0 ldi r28,lo8(4) 1263 | 489 0128 D0E0 ldi r29,hi8(4) 1264 | 490 .L28: 1265 | 514:sdlocker-tiny.cpp **** Xchg(0xff); 1266 | 491 .stabn 68,0,514,.LM73-.LFBB5 1267 | 492 .LM73: 1268 | 493 012a 8FEF ldi r24,lo8(-1) 1269 | 494 012c 00D0 rcall _ZL4Xchgh 1270 | 495 012e 2197 sbiw r28,1 1271 | 512:sdlocker-tiny.cpp **** for (i=0; i<4; i++) // burn the 4-byte response (OCR) 1272 | 496 .stabn 68,0,512,.LM74-.LFBB5 1273 | 497 .LM74: 1274 | 498 0130 01F4 brne .L28 1275 | 512:sdlocker-tiny.cpp **** for (i=0; i<4; i++) // burn the 4-byte response (OCR) 1276 | 499 .stabn 68,0,512,.LM75-.LFBB5 1277 | 500 .LM75: 1278 | 501 0132 C0E2 ldi r28,lo8(20000) 1279 | 502 0134 DEE4 ldi r29,hi8(20000) 1280 | 503 .L30: 1281 | 518:sdlocker-tiny.cpp **** response = SD_send_command(SD_ADV_INIT, 1UL<<30); 1282 | 504 .stabn 68,0,518,.LM76-.LFBB5 1283 | 505 .LM76: 1284 | 506 0136 89EE ldi r24,lo8(-23) 1285 | 507 0138 40E0 ldi r20,lo8(1073741824) 1286 | 508 013a 50E0 ldi r21,hi8(1073741824) 1287 | 509 013c 60E0 ldi r22,hlo8(1073741824) 1288 | 510 013e 70E4 ldi r23,hhi8(1073741824) 1289 | 511 0140 00D0 rcall _ZL15SD_send_commandhm 1290 | 519:sdlocker-tiny.cpp **** if (response == 0) 1291 | 512 .stabn 68,0,519,.LM77-.LFBB5 1292 | 513 .LM77: 1293 | 514 0142 8823 tst r24 1294 | 515 0144 01F0 breq .L29 1295 | 516 0146 2197 sbiw r28,1 1296 | 516:sdlocker-tiny.cpp **** for (i=20000; i>0; i--) 1297 | 517 .stabn 68,0,516,.LM78-.LFBB5 1298 | 518 .LM78: 1299 | 519 0148 01F4 brne .L30 1300 | 520 .L29: 1301 | 524:sdlocker-tiny.cpp **** sdtype = SDTYPE_SDHC; 1302 | 521 .stabn 68,0,524,.LM79-.LFBB5 1303 | 522 .LM79: 1304 | 523 014a 82E0 ldi r24,lo8(2) 1305 | 524 014c 00C0 rjmp .L41 1306 | 525 .L27: 1307 | 528:sdlocker-tiny.cpp **** response = SD_send_command(SD_READ_OCR, 0); 1308 | 526 .stabn 68,0,528,.LM80-.LFBB5 1309 | 527 .LM80: 1310 | 528 014e 8AE7 ldi r24,lo8(122) 1311 | 529 0150 40E0 ldi r20,lo8(0) 1312 | 530 0152 50E0 ldi r21,hi8(0) 1313 | 531 0154 BA01 movw r22,r20 1314 | 532 0156 00D0 rcall _ZL15SD_send_commandhm 1315 | 529:sdlocker-tiny.cpp **** if (response == 0x01) 1316 | 533 .stabn 68,0,529,.LM81-.LFBB5 1317 | 534 .LM81: 1318 | 535 0158 8130 cpi r24,lo8(1) 1319 | 536 015a 01F4 brne .L31 1320 | 529:sdlocker-tiny.cpp **** if (response == 0x01) 1321 | 537 .stabn 68,0,529,.LM82-.LFBB5 1322 | 538 .LM82: 1323 | 539 015c C4E0 ldi r28,lo8(4) 1324 | 540 015e D0E0 ldi r29,hi8(4) 1325 | 541 .L32: 1326 | 533:sdlocker-tiny.cpp **** Xchg(0xff); 1327 | 542 .stabn 68,0,533,.LM83-.LFBB5 1328 | 543 .LM83: 1329 | 544 0160 8FEF ldi r24,lo8(-1) 1330 | 545 0162 00D0 rcall _ZL4Xchgh 1331 | 546 0164 2197 sbiw r28,1 1332 | 531:sdlocker-tiny.cpp **** for (i=0; i<4; i++) // burn the 4-byte response (OCR) 1333 | 547 .stabn 68,0,531,.LM84-.LFBB5 1334 | 548 .LM84: 1335 | 549 0166 01F4 brne .L32 1336 | 531:sdlocker-tiny.cpp **** for (i=0; i<4; i++) // burn the 4-byte response (OCR) 1337 | 550 .stabn 68,0,531,.LM85-.LFBB5 1338 | 551 .LM85: 1339 | 552 0168 C0E2 ldi r28,lo8(20000) 1340 | 553 016a DEE4 ldi r29,hi8(20000) 1341 | 554 .L34: 1342 | 537:sdlocker-tiny.cpp **** response = SD_send_command(SD_INIT, 0); 1343 | 555 .stabn 68,0,537,.LM86-.LFBB5 1344 | 556 .LM86: 1345 | 557 016c 81E4 ldi r24,lo8(65) 1346 | 558 016e 40E0 ldi r20,lo8(0) 1347 | 559 0170 50E0 ldi r21,hi8(0) 1348 | 560 0172 BA01 movw r22,r20 1349 | 561 0174 00D0 rcall _ZL15SD_send_commandhm 1350 | 538:sdlocker-tiny.cpp **** if (response == 0) 1351 | 562 .stabn 68,0,538,.LM87-.LFBB5 1352 | 563 .LM87: 1353 | 564 0176 8823 tst r24 1354 | 565 0178 01F0 breq .L33 1355 | 566 017a 2197 sbiw r28,1 1356 | 535:sdlocker-tiny.cpp **** for (i=20000; i>0; i--) 1357 | 567 .stabn 68,0,535,.LM88-.LFBB5 1358 | 568 .LM88: 1359 | 569 017c 01F4 brne .L34 1360 | 570 .L33: 1361 | 543:sdlocker-tiny.cpp **** SD_send_command(SD_SET_BLK_LEN, 512); 1362 | 571 .stabn 68,0,543,.LM89-.LFBB5 1363 | 572 .LM89: 1364 | 573 017e 80E5 ldi r24,lo8(80) 1365 | 574 0180 40E0 ldi r20,lo8(512) 1366 | 575 0182 52E0 ldi r21,hi8(512) 1367 | 576 0184 60E0 ldi r22,hlo8(512) 1368 | 577 0186 70E0 ldi r23,hhi8(512) 1369 | 578 0188 00D0 rcall _ZL15SD_send_commandhm 1370 | 544:sdlocker-tiny.cpp **** sdtype = SDTYPE_SD; 1371 | 579 .stabn 68,0,544,.LM90-.LFBB5 1372 | 580 .LM90: 1373 | 581 018a 81E0 ldi r24,lo8(1) 1374 | 582 .L41: 1375 | 583 018c 8093 0000 sts sdtype,r24 1376 | 584 .L31: 1377 | 548:sdlocker-tiny.cpp **** Xchg(0xff); // send 8 final clocks 1378 | 585 .stabn 68,0,548,.LM91-.LFBB5 1379 | 586 .LM91: 1380 | 587 0190 8FEF ldi r24,lo8(-1) 1381 | 588 0192 00D0 rcall _ZL4Xchgh 1382 | 556:sdlocker-tiny.cpp **** return SDCARD_OK; // if no power routine or turning off the card, call it good 1383 | 589 .stabn 68,0,556,.LM92-.LFBB5 1384 | 590 .LM92: 1385 | 591 0194 80E0 ldi r24,lo8(0) 1386 | 592 .L26: 1387 | 593 /* epilogue start */ 1388 | 594 .LBE51: 1389 | 557:sdlocker-tiny.cpp **** } 1390 | 595 .stabn 68,0,557,.LM93-.LFBB5 1391 | 596 .LM93: 1392 | 597 0196 DF91 pop r29 1393 | 598 0198 CF91 pop r28 1394 | 599 019a 0895 ret 1395 | 600 .size _ZL6SDInitv, .-_ZL6SDInitv 1396 | 601 .Lscope5: 1397 | 602 .stabs "",36,0,0,.Lscope5-.LFBB5 1398 | 603 .stabd 78,0,0 1399 | 604 .stabs "_ZL7ReadCSDv:f(0,26)",36,0,565,_ZL7ReadCSDv 1400 | 605 .type _ZL7ReadCSDv, @function 1401 | 606 _ZL7ReadCSDv: 1402 | 607 .stabd 46,0,0 1403 | 566:sdlocker-tiny.cpp **** { 1404 | 608 .stabn 68,0,566,.LM94-.LFBB6 1405 | 609 .LM94: 1406 | 610 .LFBB6: 1407 | 611 019c 1F93 push r17 1408 | 612 019e CF93 push r28 1409 | 613 01a0 DF93 push r29 1410 | 614 /* prologue: function */ 1411 | 615 /* frame size = 0 */ 1412 | 616 /* stack size = 3 */ 1413 | 617 .L__stack_usage = 3 1414 | 618 .LBB52: 1415 | 619 .LBB53: 1416 | 620 .LBB54: 1417 | 579:sdlocker-tiny.cpp **** return SDCARD_RWFAIL; 1418 | 621 .stabn 68,0,579,.LM95-.LFBB6 1419 | 622 .LM95: 1420 | 623 01a2 C0E0 ldi r28,lo8(csd) 1421 | 624 01a4 D0E0 ldi r29,hi8(csd) 1422 | 625 .LBE54: 1423 | 626 .LBE53: 1424 | 627 .LBE52: 1425 | 565:sdlocker-tiny.cpp **** static uint8_t ReadCSD(void) 1426 | 628 .stabn 68,0,565,.LM96-.LFBB6 1427 | 629 .LM96: 1428 | 630 01a6 FE01 movw r30,r28 1429 | 631 .L43: 1430 | 632 .LBB57: 1431 | 572:sdlocker-tiny.cpp **** csd[i] = 0; 1432 | 633 .stabn 68,0,572,.LM97-.LFBB6 1433 | 634 .LM97: 1434 | 635 01a8 1192 st Z+,__zero_reg__ 1435 | 570:sdlocker-tiny.cpp **** for (i=0; i<16; i++) 1436 | 636 .stabn 68,0,570,.LM98-.LFBB6 1437 | 637 .LM98: 1438 | 638 01aa 80E0 ldi r24,hi8(csd+16) 1439 | 639 01ac E030 cpi r30,lo8(csd+16) 1440 | 640 01ae F807 cpc r31,r24 1441 | 641 01b0 01F4 brne .L43 1442 | 575:sdlocker-tiny.cpp **** response = SD_send_command(SD_SEND_CSD, 0); 1443 | 642 .stabn 68,0,575,.LM99-.LFBB6 1444 | 643 .LM99: 1445 | 644 01b2 89E4 ldi r24,lo8(73) 1446 | 645 01b4 40E0 ldi r20,lo8(0) 1447 | 646 01b6 50E0 ldi r21,hi8(0) 1448 | 647 01b8 BA01 movw r22,r20 1449 | 648 01ba 00D0 rcall _ZL15SD_send_commandhm 1450 | 649 01bc 14E6 ldi r17,lo8(100) 1451 | 650 .L45: 1452 | 651 .LBB56: 1453 | 652 .LBB55: 1454 | 753:sdlocker-tiny.cpp **** 1455 | 754:sdlocker-tiny.cpp **** 1456 | 755:sdlocker-tiny.cpp **** static uint8_t SD_wait_for_data(void) 1457 | 756:sdlocker-tiny.cpp **** { 1458 | 757:sdlocker-tiny.cpp **** uint8_t i; 1459 | 758:sdlocker-tiny.cpp **** uint8_t r; 1460 | 759:sdlocker-tiny.cpp **** 1461 | 760:sdlocker-tiny.cpp **** for (i=0; i<100; i++) 1462 | 761:sdlocker-tiny.cpp **** { 1463 | 762:sdlocker-tiny.cpp **** r = Xchg(0xff); 1464 | 653 .stabn 68,0,762,.LM100-.LFBB6 1465 | 654 .LM100: 1466 | 655 01be 8FEF ldi r24,lo8(-1) 1467 | 656 01c0 00D0 rcall _ZL4Xchgh 1468 | 763:sdlocker-tiny.cpp **** if (r != 0xff) 1469 | 657 .stabn 68,0,763,.LM101-.LFBB6 1470 | 658 .LM101: 1471 | 659 01c2 8F3F cpi r24,lo8(-1) 1472 | 660 01c4 01F4 brne .L44 1473 | 661 01c6 1150 subi r17,lo8(-(-1)) 1474 | 760:sdlocker-tiny.cpp **** for (i=0; i<100; i++) 1475 | 662 .stabn 68,0,760,.LM102-.LFBB6 1476 | 663 .LM102: 1477 | 664 01c8 01F4 brne .L45 1478 | 665 01ca 00C0 rjmp .L48 1479 | 666 .L44: 1480 | 667 .LBE55: 1481 | 668 .LBE56: 1482 | 577:sdlocker-tiny.cpp **** if (response != 0xfe) 1483 | 669 .stabn 68,0,577,.LM103-.LFBB6 1484 | 670 .LM103: 1485 | 671 01cc 8E3F cpi r24,lo8(-2) 1486 | 672 01ce 01F4 brne .L48 1487 | 673 .L49: 1488 | 584:sdlocker-tiny.cpp **** csd[i] = Xchg(0xff); 1489 | 674 .stabn 68,0,584,.LM104-.LFBB6 1490 | 675 .LM104: 1491 | 676 01d0 8FEF ldi r24,lo8(-1) 1492 | 677 01d2 00D0 rcall _ZL4Xchgh 1493 | 678 01d4 8993 st Y+,r24 1494 | 582:sdlocker-tiny.cpp **** for (i=0; i<16; i++) 1495 | 679 .stabn 68,0,582,.LM105-.LFBB6 1496 | 680 .LM105: 1497 | 681 01d6 80E0 ldi r24,hi8(csd+16) 1498 | 682 01d8 C030 cpi r28,lo8(csd+16) 1499 | 683 01da D807 cpc r29,r24 1500 | 684 01dc 01F4 brne .L49 1501 | 587:sdlocker-tiny.cpp **** Xchg(0xff); // burn the CRC 1502 | 685 .stabn 68,0,587,.LM106-.LFBB6 1503 | 686 .LM106: 1504 | 687 01de 8FEF ldi r24,lo8(-1) 1505 | 688 01e0 00D0 rcall _ZL4Xchgh 1506 | 588:sdlocker-tiny.cpp **** return SDCARD_OK; 1507 | 689 .stabn 68,0,588,.LM107-.LFBB6 1508 | 690 .LM107: 1509 | 691 01e2 80E0 ldi r24,lo8(0) 1510 | 692 01e4 00C0 rjmp .L46 1511 | 693 .L48: 1512 | 579:sdlocker-tiny.cpp **** return SDCARD_RWFAIL; 1513 | 694 .stabn 68,0,579,.LM108-.LFBB6 1514 | 695 .LM108: 1515 | 696 01e6 83E0 ldi r24,lo8(3) 1516 | 697 .L46: 1517 | 698 /* epilogue start */ 1518 | 699 .LBE57: 1519 | 589:sdlocker-tiny.cpp **** } 1520 | 700 .stabn 68,0,589,.LM109-.LFBB6 1521 | 701 .LM109: 1522 | 702 01e8 DF91 pop r29 1523 | 703 01ea CF91 pop r28 1524 | 704 01ec 1F91 pop r17 1525 | 705 01ee 0895 ret 1526 | 706 .size _ZL7ReadCSDv, .-_ZL7ReadCSDv 1527 | 707 .stabs "response:r(0,26)",64,0,568,24 1528 | 708 .stabn 192,0,0,.LBB52-.LFBB6 1529 | 709 .stabn 224,0,0,.LBE52-.LFBB6 1530 | 710 .stabs "response:r(0,26)",64,0,568,24 1531 | 711 .stabn 192,0,0,.LBB57-.LFBB6 1532 | 712 .stabn 224,0,0,.LBE57-.LFBB6 1533 | 713 .Lscope6: 1534 | 714 .stabs "",36,0,0,.Lscope6-.LFBB6 1535 | 715 .stabd 78,0,0 1536 | 716 .stabs "_ZL8BlinkLEDm:f(0,2)",36,0,316,_ZL8BlinkLEDm 1537 | 717 .stabs "pattern:P(0,30)",64,0,316,22 1538 | 718 .type _ZL8BlinkLEDm, @function 1539 | 719 _ZL8BlinkLEDm: 1540 | 720 .stabd 46,0,0 1541 | 317:sdlocker-tiny.cpp **** { 1542 | 721 .stabn 68,0,317,.LM110-.LFBB7 1543 | 722 .LM110: 1544 | 723 .LFBB7: 1545 | 724 /* prologue: function */ 1546 | 725 /* frame size = 0 */ 1547 | 726 /* stack size = 0 */ 1548 | 727 .L__stack_usage = 0 1549 | 317:sdlocker-tiny.cpp **** { 1550 | 728 .stabn 68,0,317,.LM111-.LFBB7 1551 | 729 .LM111: 1552 | 730 01f0 E0E2 ldi r30,lo8(32) 1553 | 731 .L57: 1554 | 732 .LBB58: 1555 | 321:sdlocker-tiny.cpp **** if (pattern & 0x80000000) 1556 | 733 .stabn 68,0,321,.LM112-.LFBB7 1557 | 734 .LM112: 1558 | 735 01f2 97FF sbrs r25,7 1559 | 736 01f4 00C0 rjmp .L54 1560 | 323:sdlocker-tiny.cpp **** TURN_LED_ON; 1561 | 737 .stabn 68,0,323,.LM113-.LFBB7 1562 | 738 .LM113: 1563 | 739 01f6 C498 cbi 56-32,4 1564 | 740 01f8 00C0 rjmp .L55 1565 | 741 .L54: 1566 | 327:sdlocker-tiny.cpp **** TURN_LED_OFF; 1567 | 742 .stabn 68,0,327,.LM114-.LFBB7 1568 | 743 .LM114: 1569 | 744 01fa C49A sbi 56-32,4 1570 | 745 .L55: 1571 | 746 .LBB59: 1572 | 747 .LBB60: 1573 | 748 .stabs "/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h",132,0,0,.Ltext1 1574 | 749 .Ltext1: 1575 | 1:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** /* Copyright (c) 2002, Marek Michalkiewicz 1576 | 2:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Copyright (c) 2004,2005,2007 Joerg Wunsch 1577 | 3:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Copyright (c) 2007 Florin-Viorel Petrov 1578 | 4:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** All rights reserved. 1579 | 5:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1580 | 6:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Redistribution and use in source and binary forms, with or without 1581 | 7:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** modification, are permitted provided that the following conditions are met: 1582 | 8:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1583 | 9:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** * Redistributions of source code must retain the above copyright 1584 | 10:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** notice, this list of conditions and the following disclaimer. 1585 | 11:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1586 | 12:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** * Redistributions in binary form must reproduce the above copyright 1587 | 13:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** notice, this list of conditions and the following disclaimer in 1588 | 14:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** the documentation and/or other materials provided with the 1589 | 15:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** distribution. 1590 | 16:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1591 | 17:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** * Neither the name of the copyright holders nor the names of 1592 | 18:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** contributors may be used to endorse or promote products derived 1593 | 19:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** from this software without specific prior written permission. 1594 | 20:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1595 | 21:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1596 | 22:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1597 | 23:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1598 | 24:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1599 | 25:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1600 | 26:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1601 | 27:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1602 | 28:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1603 | 29:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1604 | 30:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1605 | 31:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** POSSIBILITY OF SUCH DAMAGE. */ 1606 | 32:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1607 | 33:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** /* $Id: delay.h.in 2189 2010-10-13 09:39:34Z aboyapati $ */ 1608 | 34:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1609 | 35:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #ifndef _UTIL_DELAY_H_ 1610 | 36:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #define _UTIL_DELAY_H_ 1 1611 | 37:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1612 | 38:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #ifndef __HAS_DELAY_CYCLES 1613 | 39:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #define __HAS_DELAY_CYCLES 1 1614 | 40:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #endif 1615 | 41:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1616 | 42:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #include 1617 | 43:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #include 1618 | 44:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #include 1619 | 45:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1620 | 46:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** /** \file */ 1621 | 47:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** /** \defgroup util_delay : Convenience functions for busy-wait delay loops 1622 | 48:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** \code 1623 | 49:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #define F_CPU 1000000UL // 1 MHz 1624 | 50:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** //#define F_CPU 14.7456E6 1625 | 51:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #include 1626 | 52:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** \endcode 1627 | 53:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1628 | 54:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** \note As an alternative method, it is possible to pass the 1629 | 55:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** F_CPU macro down to the compiler from the Makefile. 1630 | 56:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Obviously, in that case, no \c \#define statement should be 1631 | 57:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** used. 1632 | 58:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1633 | 59:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** The functions in this header file are wrappers around the basic 1634 | 60:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** busy-wait functions from . They are meant as 1635 | 61:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** convenience functions where actual time values can be specified 1636 | 62:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** rather than a number of cycles to wait for. The idea behind is 1637 | 63:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** that compile-time constant expressions will be eliminated by 1638 | 64:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** compiler optimization so floating-point expressions can be used 1639 | 65:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** to calculate the number of delay cycles needed based on the CPU 1640 | 66:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** frequency passed by the macro F_CPU. 1641 | 67:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1642 | 68:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** \note In order for these functions to work as intended, compiler 1643 | 69:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** optimizations must be enabled, and the delay time 1644 | 70:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** must be an expression that is a known constant at 1645 | 71:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** compile-time. If these requirements are not met, the resulting 1646 | 72:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** delay will be much longer (and basically unpredictable), and 1647 | 73:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** applications that otherwise do not use floating-point calculations 1648 | 74:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** will experience severe code bloat by the floating-point library 1649 | 75:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** routines linked into the application. 1650 | 76:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1651 | 77:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** The functions available allow the specification of microsecond, and 1652 | 78:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** millisecond delays directly, using the application-supplied macro 1653 | 79:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** F_CPU as the CPU clock frequency (in Hertz). 1654 | 80:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1655 | 81:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** */ 1656 | 82:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1657 | 83:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #if !defined(__DOXYGEN__) 1658 | 84:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** static inline void _delay_us(double __us) __attribute__((always_inline)); 1659 | 85:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** static inline void _delay_ms(double __ms) __attribute__((always_inline)); 1660 | 86:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #endif 1661 | 87:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1662 | 88:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #ifndef F_CPU 1663 | 89:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** /* prevent compiler error by supplying a default */ 1664 | 90:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** # warning "F_CPU not defined for " 1665 | 91:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** # define F_CPU 1000000UL 1666 | 92:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #endif 1667 | 93:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1668 | 94:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #ifndef __OPTIMIZE__ 1669 | 95:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** # warning "Compiler optimizations disabled; functions from won't work as designed" 1670 | 96:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #endif 1671 | 97:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1672 | 98:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** /** 1673 | 99:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** \ingroup util_delay 1674 | 100:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1675 | 101:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Perform a delay of \c __ms milliseconds, using _delay_loop_2(). 1676 | 102:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1677 | 103:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** The macro F_CPU is supposed to be defined to a 1678 | 104:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** constant defining the CPU clock frequency (in Hertz). 1679 | 105:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1680 | 106:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** The maximal possible delay is 262.14 ms / F_CPU in MHz. 1681 | 107:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1682 | 108:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** When the user request delay which exceed the maximum possible one, 1683 | 109:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** _delay_ms() provides a decreased resolution functionality. In this 1684 | 110:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** mode _delay_ms() will work with a resolution of 1/10 ms, providing 1685 | 111:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** delays up to 6.5535 seconds (independent from CPU frequency). The 1686 | 112:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** user will not be informed about decreased resolution. 1687 | 113:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1688 | 114:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) 1689 | 115:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For 1690 | 116:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** values greater than the maximal possible delay, overflows results in 1691 | 117:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** no delay i.e., 0ms. 1692 | 118:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1693 | 119:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Conversion of __us into clock cycles may not always result in integer. 1694 | 120:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** By default, the clock cycles rounded up to next integer. This ensures that 1695 | 121:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** the user gets atleast __us microseconds of delay. 1696 | 122:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1697 | 123:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__ 1698 | 124:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** to round down and round to closest integer. 1699 | 125:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1700 | 126:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** Note: The new implementation of _delay_ms(double __ms) with 1701 | 127:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 1702 | 128:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay 1703 | 129:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** although this will be deprecated in future. 1704 | 130:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1705 | 131:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** */ 1706 | 132:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** void 1707 | 133:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** _delay_ms(double __ms) 1708 | 134:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** { 1709 | 135:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** uint16_t __ticks; 1710 | 136:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** double __tmp ; 1711 | 137:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && !defined(__DELAY_BACKWARD_COMPATIBLE__) 1712 | 138:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** uint32_t __ticks_dc; 1713 | 139:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** extern void __builtin_avr_delay_cycles(unsigned long); 1714 | 140:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** __tmp = ((F_CPU) / 1e3) * __ms; 1715 | 141:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1716 | 142:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #if defined(__DELAY_ROUND_DOWN__) 1717 | 143:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** __ticks_dc = (uint32_t)fabs(__tmp); 1718 | 144:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1719 | 145:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #elif defined(__DELAY_ROUND_CLOSEST__) 1720 | 146:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 1721 | 147:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1722 | 148:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #else 1723 | 149:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** //round up by default 1724 | 150:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 1725 | 151:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** #endif 1726 | 152:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** 1727 | 153:/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h **** __builtin_avr_delay_cycles(__ticks_dc); 1728 | 750 .stabn 68,0,153,.LM115-.LFBB7 1729 | 751 .LM115: 1730 | 752 01fc 2FEB ldi r18,lo8(55999) 1731 | 753 01fe 3AED ldi r19,hi8(55999) 1732 | 754 0200 40E0 ldi r20,hlo8(55999) 1733 | 755 0202 2150 1:subi r18,1 1734 | 756 0204 3040 sbci r19,0 1735 | 757 0206 4040 sbci r20,0 1736 | 758 0208 01F4 brne 1b 1737 | 759 020a 00C0 rjmp . 1738 | 760 020c 0000 nop 1739 | 761 .LBE60: 1740 | 762 .LBE59: 1741 | 763 .stabs "sdlocker-tiny.cpp",132,0,0,.Ltext2 1742 | 764 .Ltext2: 1743 | 330:sdlocker-tiny.cpp **** pattern = pattern << 1; 1744 | 765 .stabn 68,0,330,.LM116-.LFBB7 1745 | 766 .LM116: 1746 | 767 020e 660F lsl r22 1747 | 768 0210 771F rol r23 1748 | 769 0212 881F rol r24 1749 | 770 0214 991F rol r25 1750 | 331:sdlocker-tiny.cpp **** if (pattern == 0) 1751 | 771 .stabn 68,0,331,.LM117-.LFBB7 1752 | 772 .LM117: 1753 | 773 0216 6115 cp r22,__zero_reg__ 1754 | 774 0218 7105 cpc r23,__zero_reg__ 1755 | 775 021a 8105 cpc r24,__zero_reg__ 1756 | 776 021c 9105 cpc r25,__zero_reg__ 1757 | 777 021e 01F0 breq .L53 1758 | 778 0220 E150 subi r30,lo8(-(-1)) 1759 | 319:sdlocker-tiny.cpp **** for (i=0; i<32; i++) 1760 | 779 .stabn 68,0,319,.LM118-.LFBB7 1761 | 780 .LM118: 1762 | 781 0222 01F4 brne .L57 1763 | 782 .L53: 1764 | 783 0224 0895 ret 1765 | 784 .LBE58: 1766 | 785 .size _ZL8BlinkLEDm, .-_ZL8BlinkLEDm 1767 | 786 .Lscope7: 1768 | 787 .stabs "",36,0,0,.Lscope7-.LFBB7 1769 | 788 .stabd 78,0,0 1770 | 789 .stabs "_ZL9ReadStatev:f(0,2)",36,0,345,_ZL9ReadStatev 1771 | 790 .type _ZL9ReadStatev, @function 1772 | 791 _ZL9ReadStatev: 1773 | 792 .stabd 46,0,0 1774 | 346:sdlocker-tiny.cpp **** { 1775 | 793 .stabn 68,0,346,.LM119-.LFBB8 1776 | 794 .LM119: 1777 | 795 .LFBB8: 1778 | 796 0226 00C0 rjmp .L64 1779 | 797 /* prologue: function */ 1780 | 798 /* frame size = 0 */ 1781 | 799 /* stack size = 0 */ 1782 | 800 .L__stack_usage = 0 1783 | 801 .L61: 1784 | 802 .LBB61: 1785 | 353:sdlocker-tiny.cpp **** BlinkLED(PATTERN_LOADING); 1786 | 803 .stabn 68,0,353,.LM120-.LFBB8 1787 | 804 .LM120: 1788 | 805 0228 60E0 ldi r22,lo8(-1610612736) 1789 | 806 022a 70E0 ldi r23,hi8(-1610612736) 1790 | 807 022c 80E0 ldi r24,hlo8(-1610612736) 1791 | 808 022e 90EA ldi r25,hhi8(-1610612736) 1792 | 809 0230 00D0 rcall _ZL8BlinkLEDm 1793 | 810 .L64: 1794 | 354:sdlocker-tiny.cpp **** r = SDInit(); // keep trying 1795 | 811 .stabn 68,0,354,.LM121-.LFBB8 1796 | 812 .LM121: 1797 | 813 0232 00D0 rcall _ZL6SDInitv 1798 | 351:sdlocker-tiny.cpp **** while (r != SDCARD_OK) 1799 | 814 .stabn 68,0,351,.LM122-.LFBB8 1800 | 815 .LM122: 1801 | 816 0234 8823 tst r24 1802 | 817 0236 01F4 brne .L61 1803 | 818 0238 00C0 rjmp .L65 1804 | 819 .L63: 1805 | 361:sdlocker-tiny.cpp **** BlinkLED(PATTERN_READING); 1806 | 820 .stabn 68,0,361,.LM123-.LFBB8 1807 | 821 .LM123: 1808 | 822 023a 60E0 ldi r22,lo8(-1526726656) 1809 | 823 023c 70E0 ldi r23,hi8(-1526726656) 1810 | 824 023e 80E0 ldi r24,hlo8(-1526726656) 1811 | 825 0240 95EA ldi r25,hhi8(-1526726656) 1812 | 826 0242 00D0 rcall _ZL8BlinkLEDm 1813 | 827 .L65: 1814 | 362:sdlocker-tiny.cpp **** r = ReadCSD(); // keep trying 1815 | 828 .stabn 68,0,362,.LM124-.LFBB8 1816 | 829 .LM124: 1817 | 830 0244 00D0 rcall _ZL7ReadCSDv 1818 | 359:sdlocker-tiny.cpp **** while (r != SDCARD_OK) 1819 | 831 .stabn 68,0,359,.LM125-.LFBB8 1820 | 832 .LM125: 1821 | 833 0246 8823 tst r24 1822 | 834 0248 01F4 brne .L63 1823 | 835 /* epilogue start */ 1824 | 836 .LBE61: 1825 | 364:sdlocker-tiny.cpp **** } 1826 | 837 .stabn 68,0,364,.LM126-.LFBB8 1827 | 838 .LM126: 1828 | 839 024a 0895 ret 1829 | 840 .size _ZL9ReadStatev, .-_ZL9ReadStatev 1830 | 841 .Lscope8: 1831 | 842 .stabs "",36,0,0,.Lscope8-.LFBB8 1832 | 843 .stabd 78,0,0 1833 | 844 .stabs "_ZL9ShowStatev:f(0,2)",36,0,374,_ZL9ShowStatev 1834 | 845 .type _ZL9ShowStatev, @function 1835 | 846 _ZL9ShowStatev: 1836 | 847 .stabd 46,0,0 1837 | 375:sdlocker-tiny.cpp **** { 1838 | 848 .stabn 68,0,375,.LM127-.LFBB9 1839 | 849 .LM127: 1840 | 850 .LFBB9: 1841 | 851 /* prologue: function */ 1842 | 852 /* frame size = 0 */ 1843 | 853 /* stack size = 0 */ 1844 | 854 .L__stack_usage = 0 1845 | 855 .LBB62: 1846 | 856 .LBB63: 1847 | 422:sdlocker-tiny.cpp **** return (csd[14] & LOCK_BIT_MASK); // check lock bit from CSD 1848 | 857 .stabn 68,0,422,.LM128-.LFBB9 1849 | 858 .LM128: 1850 | 859 024c 8091 0000 lds r24,csd+14 1851 | 860 .LBE63: 1852 | 861 .LBE62: 1853 | 376:sdlocker-tiny.cpp **** if (CardIsLocked()) 1854 | 862 .stabn 68,0,376,.LM129-.LFBB9 1855 | 863 .LM129: 1856 | 864 0250 84FF sbrs r24,4 1857 | 865 0252 00C0 rjmp .L67 1858 | 378:sdlocker-tiny.cpp **** BlinkLED(PATTERN_LOCKED); 1859 | 866 .stabn 68,0,378,.LM130-.LFBB9 1860 | 867 .LM130: 1861 | 868 0254 60E0 ldi r22,lo8(-2147483648) 1862 | 869 0256 70E0 ldi r23,hi8(-2147483648) 1863 | 870 0258 80E0 ldi r24,hlo8(-2147483648) 1864 | 871 025a 90E8 ldi r25,hhi8(-2147483648) 1865 | 872 025c 00C0 rjmp .L69 1866 | 873 .L67: 1867 | 382:sdlocker-tiny.cpp **** BlinkLED(PATTERN_UNLOCKED); 1868 | 874 .stabn 68,0,382,.LM131-.LFBB9 1869 | 875 .LM131: 1870 | 876 025e 60E0 ldi r22,lo8(0) 1871 | 877 0260 70E0 ldi r23,hi8(0) 1872 | 878 0262 CB01 movw r24,r22 1873 | 879 .L69: 1874 | 880 0264 00D0 rcall _ZL8BlinkLEDm 1875 | 881 0266 0895 ret 1876 | 882 .size _ZL9ShowStatev, .-_ZL9ShowStatev 1877 | 883 .Lscope9: 1878 | 884 .stabs "",36,0,0,.Lscope9-.LFBB9 1879 | 885 .stabd 78,0,0 1880 | 886 .stabs "_ZL8ButtonIsh:f(0,26)",36,0,262,_ZL8ButtonIsh 1881 | 887 .stabs "state:P(0,26)",64,0,262,17 1882 | 888 .type _ZL8ButtonIsh, @function 1883 | 889 _ZL8ButtonIsh: 1884 | 890 .stabd 46,0,0 1885 | 263:sdlocker-tiny.cpp **** { 1886 | 891 .stabn 68,0,263,.LM132-.LFBB10 1887 | 892 .LM132: 1888 | 893 .LFBB10: 1889 | 894 0268 0F93 push r16 1890 | 895 026a 1F93 push r17 1891 | 896 /* prologue: function */ 1892 | 897 /* frame size = 0 */ 1893 | 898 /* stack size = 2 */ 1894 | 899 .L__stack_usage = 2 1895 | 900 026c 182F mov r17,r24 1896 | 901 .LBB64: 1897 | 267:sdlocker-tiny.cpp **** if (ReadSwitchOnce() == state) // if switch state seems to match 1898 | 902 .stabn 68,0,267,.LM133-.LFBB10 1899 | 903 .LM133: 1900 | 904 026e 00D0 rcall _ZL14ReadSwitchOncev 1901 | 905 0270 082F mov r16,r24 1902 | 906 0272 8117 cp r24,r17 1903 | 907 0274 01F4 brne .L74 1904 | 908 0276 15E0 ldi r17,lo8(5) 1905 | 909 .L72: 1906 | 910 .LBB65: 1907 | 911 .LBB66: 1908 | 912 .stabs "/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h",132,0,0,.Ltext3 1909 | 913 .Ltext3: 1910 | 914 .stabn 68,0,153,.LM134-.LFBB10 1911 | 915 .LM134: 1912 | 916 0278 8FEF ldi r24,lo8(159999) 1913 | 917 027a 90E7 ldi r25,hi8(159999) 1914 | 918 027c A2E0 ldi r26,hlo8(159999) 1915 | 919 027e 8150 1:subi r24,1 1916 | 920 0280 9040 sbci r25,0 1917 | 921 0282 A040 sbci r26,0 1918 | 922 0284 01F4 brne 1b 1919 | 923 0286 00C0 rjmp . 1920 | 924 0288 0000 nop 1921 | 925 .LBE66: 1922 | 926 .LBE65: 1923 | 927 .stabs "sdlocker-tiny.cpp",132,0,0,.Ltext4 1924 | 928 .Ltext4: 1925 | 273:sdlocker-tiny.cpp **** if (ReadSwitchOnce() != state) // if state doesn't match now 1926 | 929 .stabn 68,0,273,.LM135-.LFBB10 1927 | 930 .LM135: 1928 | 931 028a 00D0 rcall _ZL14ReadSwitchOncev 1929 | 932 028c 8017 cp r24,r16 1930 | 933 028e 01F4 brne .L74 1931 | 934 0290 1150 subi r17,lo8(-(-1)) 1932 | 270:sdlocker-tiny.cpp **** for (i=0; i<5; i++) // debounce check every 100ms, 5 times 1933 | 935 .stabn 68,0,270,.LM136-.LFBB10 1934 | 936 .LM136: 1935 | 937 0292 01F4 brne .L72 1936 | 269:sdlocker-tiny.cpp **** match = 1; 1937 | 938 .stabn 68,0,269,.LM137-.LFBB10 1938 | 939 .LM137: 1939 | 940 0294 81E0 ldi r24,lo8(1) 1940 | 941 0296 00C0 rjmp .L71 1941 | 942 .L74: 1942 | 275:sdlocker-tiny.cpp **** match = 0; // terminate debounce check 1943 | 943 .stabn 68,0,275,.LM138-.LFBB10 1944 | 944 .LM138: 1945 | 945 0298 80E0 ldi r24,lo8(0) 1946 | 946 .L71: 1947 | 947 /* epilogue start */ 1948 | 948 .LBE64: 1949 | 281:sdlocker-tiny.cpp **** } 1950 | 949 .stabn 68,0,281,.LM139-.LFBB10 1951 | 950 .LM139: 1952 | 951 029a 1F91 pop r17 1953 | 952 029c 0F91 pop r16 1954 | 953 029e 0895 ret 1955 | 954 .size _ZL8ButtonIsh, .-_ZL8ButtonIsh 1956 | 955 .stabs "match:r(0,26)",64,0,264,24 1957 | 956 .stabn 192,0,0,.LBB64-.LFBB10 1958 | 957 .stabn 224,0,0,.LBE64-.LFBB10 1959 | 958 .Lscope10: 1960 | 959 .stabs "",36,0,0,.Lscope10-.LFBB10 1961 | 960 .stabd 78,0,0 1962 | 961 .stabs "main:F(0,7)",36,0,209,main 1963 | 962 .global main 1964 | 963 .type main, @function 1965 | 964 main: 1966 | 965 .stabd 46,0,0 1967 | 210:sdlocker-tiny.cpp **** { 1968 | 966 .stabn 68,0,210,.LM140-.LFBB11 1969 | 967 .LM140: 1970 | 968 .LFBB11: 1971 | 969 02a0 EF92 push r14 1972 | 970 02a2 FF92 push r15 1973 | 971 02a4 0F93 push r16 1974 | 972 02a6 1F93 push r17 1975 | 973 02a8 CF93 push r28 1976 | 974 02aa DF93 push r29 1977 | 975 /* prologue: function */ 1978 | 976 /* frame size = 0 */ 1979 | 977 /* stack size = 6 */ 1980 | 978 .L__stack_usage = 6 1981 | 979 .LBB85: 1982 | 214:sdlocker-tiny.cpp **** SPI_PORT |= (1<