diff --git a/bootloader_zevero_sd_m1284p_make/.cproject b/bootloader_zevero_sd_m1284p_make/.cproject
new file mode 100644
index 0000000..d50f016
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/.cproject
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ make
+
+ program
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/bootloader_zevero_sd_m1284p_make/.gitignore b/bootloader_zevero_sd_m1284p_make/.gitignore
new file mode 100644
index 0000000..3c2fcf6
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/.gitignore
@@ -0,0 +1,10 @@
+*.o
+*.eps
+*.bak
+*.a
+*.bin
+*.elf
+*.hex
+*.lst
+*.map
+/nbproject
\ No newline at end of file
diff --git a/bootloader_zevero_sd_m1284p_make/.project b/bootloader_zevero_sd_m1284p_make/.project
new file mode 100644
index 0000000..7e47f47
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/.project
@@ -0,0 +1,27 @@
+
+
+ bootloader_zevero_sd_m1284p_make
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+ de.innot.avreclipse.core.avrnature
+
+
diff --git a/bootloader_zevero_sd_m1284p_make/LICENSE b/bootloader_zevero_sd_m1284p_make/LICENSE
new file mode 100644
index 0000000..0c0bbe3
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2015, zevero
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/bootloader_zevero_sd_m1284p_make/Makefile b/bootloader_zevero_sd_m1284p_make/Makefile
new file mode 100644
index 0000000..1d11c93
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/Makefile
@@ -0,0 +1,70 @@
+#------------------------------------------------------------------
+# Makefile for stand-alone MMC boot strap loader
+#------------------------------------------------------------------
+# Change these defs for the target device
+
+MCU_TARGET = atmega1284p # Target device to be used (32K or larger)
+BOOT_ADR = 0x1F000 # Boot loader start address [byte] NOT [word] as in http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega1284p
+F_CPU = 16000000 # CPU clock frequency [Hz] NOT critical: it just should be higher than the actual Hz
+SD_CS_PORT = PORTB # Data Register of the SD CS pin
+SD_CS_DDR = DDRB # Data Direction Register of the SD CS pin
+SD_CS_BIT = 0 # Bit of the SD CS pin
+USE_LED = 1 # Debug with two (defined in asmfunc.S)
+USE_UART = 0 # Debug on Serial. 0 ... deactivate or divider of http://wormfood.net/avrbaudcalc.php for baud rate!
+#------------------------------------------------------------------
+ifeq ($(strip $(USE_UART)),0)
+CSRC = main.c pff/src/pff.c diskio.c
+else
+CSRC = main.c pff/src/pff.c diskio.c uart/uart.c
+endif
+
+TARGET = avr_boot
+ASRC = asmfunc.S
+OPTIMIZE = -Os -mcall-prologues -ffunction-sections -fdata-sections
+DEFS = -DBOOT_ADR=$(BOOT_ADR) -DF_CPU=$(F_CPU) -DUSE_LED=$(USE_LED) -DUSE_UART=$(USE_UART) -DSD_CS_PORT=$(SD_CS_PORT) -DSD_CS_DDR=$(SD_CS_DDR) -DSD_CS_BIT=$(SD_CS_BIT)
+LIBS =
+DEBUG = dwarf-2
+
+ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs $(DEFS)
+ALL_ASFLAGS = -mmcu=$(MCU_TARGET) -I. -x assembler-with-cpp $(ASFLAGS)
+CFLAGS = -g$(DEBUG) -Wall $(OPTIMIZE) $(ADDED_CFLAGS) -mmcu=$(MCU_TARGET) -std=c99 $(DEFS)
+LDFLAGS = -Wl,-Map,$(TARGET).map -Wl,--gc-sections -Wl,--section-start,.text=$(BOOT_ADR)
+OBJ = $(CSRC:.c=.o) $(ASRC:.S=.o)
+
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+
+
+all: clean $(TARGET).elf lst text bin size
+
+$(TARGET).elf: $(OBJ)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+clean:
+ rm -rf *.o $(TARGET).elf *.eps *.bak *.a *.bin
+ rm -rf pff/src/*.o uart/*.o
+ rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
+ rm -rf $(TARGET).hex
+
+size: $(TARGET).elf
+ $(SIZE) -C --mcu=$(MCU_TARGET) $(TARGET).elf
+
+lst: $(TARGET).lst
+%.lst: %.elf
+ $(OBJDUMP) -h -S $< > $@
+
+%.o : %.S
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+text: $(TARGET).hex
+%.hex: %.elf
+ $(OBJCOPY) -j .text -j .data -j .fuse -O ihex $< $@
+# --- make bin just to check size :)
+bin: $(TARGET).bin
+%.bin: %.hex
+ $(OBJCOPY) -I ihex -O binary $< $@
+
+print-% : ; @echo $* = $($*) #test any var with make print-XXX
+
diff --git a/bootloader_zevero_sd_m1284p_make/README.md b/bootloader_zevero_sd_m1284p_make/README.md
new file mode 100644
index 0000000..dd2b29a
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/README.md
@@ -0,0 +1,86 @@
+avr_boot
+========
+
+SD card bootloader for atmega processors
+
+As easy as it can get! I spent days with this. Hopefully you wont!
+
+- for any ATMega with 4096kb Bootloader
+- uses Petit FatFs R0.03 for FAT12, FAT16, FAT32
+- looks for FIRMWARE.BIN and flashes it nearly instantly
+- without any interference to your application
+- no CRC Check and no version bytes in EEPROM (see KISS)
+
+### Boards Manager installation
+
+avr_boot is integrated in Arduino IDE version 1.6.4 or greater!!! [See here for instructions.](https://github.com/zevero/avr_boot/tree/gh-pages)
+
+### Manual installation
+
+This is with avr-gcc and avrdude under linux with an Atmega1284p and AVRISP mkII! Adaption to your case (WinAvr, another Atmega, another flash-tool) will not be complicated...
+
+- adapt Makefile
+ - MCU_TARGET: Your atmegaXXX
+ - BOOT_ADR: in bytes not words!
+ - F_CPU: CPU Frequency (not critical. A higher value will work as well)
+ - SD_CS_PORT: Data Register of the SD CS pin(see the datasheet for your microcontroller)
+ - SD_CS_DDR: Data Direction Register of the SD CS pin
+ - SD_CS_BIT: Bit of the SD CS pin
+ - USE_LED: For debugging 0...deactivate or 1...active
+ - USE_UART: For debugging 0...deactivate or divider (UBRR) for baudate see http://wormfood.net/avrbaudcalc.php
+- update spi_pins.h with the SPI pins of your microcontroller if not already defined
+- if using USE_LED adapt LED-pins in asmfunc.S
+- if you want to add FAT12 adapt pff/src/pffconfh.h (default ist FAT16 + FAT32)
+- if you want to support lower case filenames adapt pff/src/pffconfh.h (default is uppercase)
+- if you prefer another filename instead of FIRMWARE.BIN adapt main.c
+- make (you may need to do "sudo apt-get install avr-libc gcc-avr")
+- set fuses: avrdude -c avrispmkII -p m1284p -U hfuse:w:0xda:m
+ - find high fuse in http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega1284p
+- flash: avrdude -c avrispmkII -p m1284p -Uflash:w:./avr_boot.hex:i -Ulock:w:0x3F:m
+
+### Put your sketch on SD card
+
+- in Arduino IDE go to File > Preferences and check "Show verbose output during compiliation"
+- compile sketch and find the location of your /tmp/buildxxx/sketch.cpp.hex
+- make bin file: avr-objcopy -I ihex -O binary sketch.cpp.hex FIRMWARE.BIN
+- copy the file into the root of an SD (FAT16/FAT32)
+- put it into the SD slot of your ATmega
+- reset it
+- it might already have happend!
+
+### Bootloader sizes
+Compiled under linux for atmega328p / atmega1284p
+ - 3674 / 3724 bytes
+ - 3984 / 4034 bytes debugging with USE_LED
+ - 3992 / 4052 bytes debugging with USE_UART
+
+### Tested successfully on
+ - ATmega168
+ - ATmega328P
+ - ATmega32u4
+ - ATmega1284P
+ - ATmega2560 (see issue #2)
+
+### Serial support - Help wanted
+it should not be impossible to fit a normal serial bootloader (with automatic baudrate detection?) into the remaining bytes ... help is appreciated!
+
+### KISS
+If you wish you *can* add CRC Check or versioning with EEPROM *but* I prefere to keep things simple. avr_boot will reflash your FIRMWARE.BIN as long as it is present.
+Is this a problem? No! It happens nearly instantly and only differing bytes are flashed really.
+You may consider putting your logic into your application and perform a CRC Check after the fact to inform the user and delete or rename FIRMWARE.BIN
+
+### Thanks to
+- https://github.com/per1234 - Boards Manager Installation and help with differenct MCUs
+- http://elm-chan.org/fsw/ff/00index_p.html
+- Wilfried Klaas for the MCSDepthLogger https://github.com/willie68/OpenSeaMapLogger
+- https://github.com/mharizanov/avr_boot
+- https://github.com/osbock/avr_boot
+- and others???
+
+### Alternatives
+
+- https://spaces.atmel.com/gf/project/sdbootloader/
+- https://github.com/thseiler/embedded/tree/master/avr/2boots
+- http://www.mikrocontroller.net/articles/MMC/SD_Bootloader_f%C3%BCr_AT_Mega
+
+... call me stupid, but I passed several days debugging those - without success ...
diff --git a/bootloader_zevero_sd_m1284p_make/asmfunc.S b/bootloader_zevero_sd_m1284p_make/asmfunc.S
new file mode 100644
index 0000000..099a8d1
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/asmfunc.S
@@ -0,0 +1,271 @@
+;---------------------------------------------------------------------------;
+; MMC hardware controls and Flash controls (C)ChaN, 2010
+;---------------------------------------------------------------------------;
+; Hardware dependent macros to be modified //do this in Makefile
+#include "spi_pins.h"
+
+; ALL Pins given as Port (A,B,C,...) plus number
+
+; LED Pins
+;#define DDR_SS _SFR_IO_ADDR(DDRD), 5 // SS pin (PIN, PORT)
+;#define PORT_SS _SFR_IO_ADDR(PORTD), 5
+#define DDR_SS _SFR_IO_ADDR(DDRC), 3 // SS pin (PIN, PORT)
+#define PORT_SS _SFR_IO_ADDR(PORTC), 3
+
+;#define DDR_PW _SFR_IO_ADDR(DDRD), 6 // Power pin (PIN, PORT)
+;#define PORT_PW _SFR_IO_ADDR(PORTD), 6
+
+;SD CARD PINS
+#define DDR_CS _SFR_IO_ADDR(SD_CS_DDR), SD_CS_BIT
+#define PORT_CS _SFR_IO_ADDR(SD_CS_PORT), SD_CS_BIT
+
+;---------------------------------------------------------------------------;
+.nolist
+#include
+.list
+.text
+
+.global init_leds
+.func init_leds
+init_leds:
+ sbi DDR_SS
+; sbi DDR_PW
+ ret
+.endfunc
+
+
+.global led_write_on
+.func led_write_on
+led_write_on:
+ sbi PORT_SS
+ ret
+.endfunc
+
+.global led_write_off
+.func led_write_off
+led_write_off:
+ cbi PORT_SS
+ ret
+.endfunc
+
+;.global led_power_on
+;.func led_power_on
+;led_power_on:
+; sbi PORT_PW
+; ret
+;.endfunc
+
+;.;global led_power_off
+;.;func led_power_off
+;led_power_off:
+; cbi PORT_PW
+; ret
+;.endfunc
+
+;.;global led_power_toggle
+;.func led_power_toggle
+;led_power_toggle:
+; sbis PORT_PW
+; jmp led_power_on
+; jmp led_power_off
+;.endfunc
+
+.global led_write_toggle
+.func led_write_toggle
+led_write_toggle:
+ sbis PORT_SS
+ jmp led_write_on
+ jmp led_write_off
+.endfunc
+
+;---------------------------------------------------------------------------;
+; Initialize MMC port
+;
+; void init_spi (void);
+
+.global init_spi
+.func init_spi
+init_spi:
+ sbi DDR_CS ; CS: output
+ sbi DDR_DI ; DI: output
+ sbi DDR_CK ; SCLK: output
+ sbi PORT_DO ; DO: pull-up
+ ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Delay 100 microseconds
+;
+; void dly_us (UINT n);
+
+.global dly_100us
+.func dly_100us
+dly_100us:
+ ldi r24, lo8(F_CPU / 100000) /* Loop counter */
+1: sbiw r30, 1 /* 10 clocks per loop */
+ sbiw r30, 1
+ sbiw r30, 1
+ nop
+ dec r24
+ brne 1b
+ ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Select MMC
+;
+; void select (void);
+
+.global select
+.func select
+select:
+ rcall deselect
+ cbi PORT_CS
+ rjmp rcv_spi
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Deselect MMC
+;
+; void deselect (void);
+
+.global deselect
+.func deselect
+deselect:
+ sbi PORT_CS
+ ; Goto next function
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Receive a byte
+;
+; BYTE rcv_spi (void);
+
+.global rcv_spi
+.func rcv_spi
+rcv_spi:
+ ldi r24, 0xFF ; Send 0xFF to receive data
+ ; Goto next function
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Transmit a byte
+;
+; void xmit_spi (BYTE);
+
+.global xmit_spi
+.func xmit_spi
+xmit_spi:
+ ldi r25, 8
+1: sbrc r24, 7 ; DI = Bit to sent
+ sbi PORT_DI ;
+ sbrs r24, 7 ;
+ cbi PORT_DI ; /
+ lsl r24 ; Get DO from MMC
+ sbic PIN_DO ;
+ inc r24 ; /
+ sbi PORT_CK ; A positive pulse to SCLK
+ cbi PORT_CK ; /
+ dec r25 ; Repeat 8 times
+ brne 1b ; /
+ ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------
+; Erase a flash page
+;
+; void flash_erase (DWORD flash_addr);
+
+#ifndef SPMCSR
+#define SPMCSR SPMCR
+#endif
+
+.global flash_erase
+.func flash_erase
+flash_erase:
+
+ movw ZL, r22
+#if FLASHEND >= 0x10000
+ out _SFR_IO_ADDR(RAMPZ), r24
+#endif
+
+ ; Initiate erase operation
+ ldi r24, 0b00000011
+ sts _SFR_MEM_ADDR(SPMCSR), r24
+ spm
+
+ ; Wait for end of erase operation
+1: lds r24, _SFR_MEM_ADDR(SPMCSR)
+ sbrc r24, 0
+ rjmp 1b
+
+ ; Re-enable read access to the flash
+ ldi r24, 0b00010001
+ sts _SFR_MEM_ADDR(SPMCSR), r24
+ spm
+
+9: ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------
+; Write a flash page
+;
+; void flash_write (DWORD flash_addr, const BYTE* data);
+
+.global flash_write
+.func flash_write
+flash_write:
+ push r0
+ push r1
+
+#if FLASHEND >= 0x10000
+ out _SFR_IO_ADDR(RAMPZ), r24
+#endif
+
+ ; Fill page buffer
+ movw ZL, r22
+ movw XL, r20
+ ldi r25, lo8(SPM_PAGESIZE/2)
+1: ld r0, X+
+ ld r1, X+
+ ldi r24, 0b00000001
+ sts _SFR_MEM_ADDR(SPMCSR), r24
+ spm
+ adiw ZL, 2
+ dec r25
+ brne 1b
+
+ ; Initiate write operation
+ movw ZL, r22
+ ldi r24, 0b00000101
+ sts _SFR_MEM_ADDR(SPMCSR), r24
+ spm
+
+ ; Wait for end of write operation
+2: lds r24, _SFR_MEM_ADDR(SPMCSR)
+ sbrc r24, 0
+ rjmp 2b
+
+ ; Re-enable read access to the flash
+ ldi r24, 0b00010001
+ sts _SFR_MEM_ADDR(SPMCSR), r24
+ spm
+
+9: pop r1
+ pop r0
+ ret
+.endfunc
diff --git a/bootloader_zevero_sd_m1284p_make/diskio.c b/bootloader_zevero_sd_m1284p_make/diskio.c
new file mode 100644
index 0000000..4608c5e
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/diskio.c
@@ -0,0 +1,226 @@
+/*-----------------------------------------------------------------------*/
+/* Low level disk I/O module skeleton for Petit FatFs (C)ChaN, 2014 */
+/*-----------------------------------------------------------------------*/
+
+#include "pff/src/pff.h"
+#include "pff/src/diskio.h"
+
+void init_spi (void); /* Initialize SPI port (asmfunc.S) */
+void deselect (void); /* Select MMC (asmfunc.S) */
+void select (void); /* Deselect MMC (asmfunc.S) */
+void xmit_spi (BYTE d); /* Send a byte to the MMC (asmfunc.S) */
+BYTE rcv_spi (void); /* Send a 0xFF to the MMC and get the received byte (asmfunc.S) */
+void dly_100us (void); /* Delay 100 microseconds (asmfunc.S) */
+
+
+
+/*--------------------------------------------------------------------------
+
+ Module Private Functions
+
+---------------------------------------------------------------------------*/
+
+/* Definitions for MMC/SDC command */
+#define CMD0 (0x40+0) /* GO_IDLE_STATE */
+#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
+#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
+#define CMD8 (0x40+8) /* SEND_IF_COND */
+#define CMD16 (0x40+16) /* SET_BLOCKLEN */
+#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
+#define CMD24 (0x40+24) /* WRITE_BLOCK */
+#define CMD55 (0x40+55) /* APP_CMD */
+#define CMD58 (0x40+58) /* READ_OCR */
+
+
+/* Card type flags (CardType) */
+#define CT_MMC 0x01 /* MMC ver 3 */
+#define CT_SD1 0x02 /* SD ver 1 */
+#define CT_SD2 0x04 /* SD ver 2 */
+#define CT_BLOCK 0x08 /* Block addressing */
+
+
+static
+BYTE CardType;
+
+
+/*-----------------------------------------------------------------------*/
+/* Send a command packet to MMC */
+/*-----------------------------------------------------------------------*/
+
+static
+BYTE send_cmd (
+ BYTE cmd, /* 1st byte (Start + Index) */
+ DWORD arg /* Argument (32 bits) */
+)
+{
+ BYTE n, res;
+
+
+ if (cmd & 0x80) { /* ACMD is the command sequense of CMD55-CMD */
+ cmd &= 0x7F;
+ res = send_cmd(CMD55, 0);
+ if (res > 1) return res;
+ }
+
+ /* Select the card */
+ select();
+
+ /* Send a command packet */
+ xmit_spi(cmd); /* Start + Command index */
+ 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 = 0x01; /* Dummy CRC + Stop */
+ if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
+ if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
+ xmit_spi(n);
+
+ /* Receive a command response */
+ n = 10; /* Wait for a valid response in timeout of 10 attempts */
+ do {
+ res = rcv_spi();
+ } while ((res & 0x80) && --n);
+
+ return res; /* Return with the response value */
+}
+
+
+
+
+/*--------------------------------------------------------------------------
+
+ Public Functions
+
+---------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------*/
+/* Initialize Disk Drive */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_initialize (void)
+{
+ DSTATUS stat;
+
+ BYTE n, cmd, ty, ocr[4];
+ UINT tmr;
+
+
+ init_spi(); /* Initialize ports to control MMC */
+ for (n = 100; n; n--) dly_100us(); /* 10ms delay */
+ for (n = 10; n; n--) deselect(); /* 80 Dummy clocks with CS=H */
+
+ ty = 0;
+ if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
+ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */
+ for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); /* Get trailing return value of R7 resp */
+ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
+ for (tmr = 10000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) dly_100us(); /* Wait for leaving idle state (ACMD41 with HCS bit) */
+ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
+ for (n = 0; n < 4; n++) ocr[n] = rcv_spi();
+ ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */
+ }
+ }
+ } else { /* SDv1 or MMCv3 */
+ if (send_cmd(ACMD41, 0) <= 1) {
+ ty = CT_SD1; cmd = ACMD41; /* SDv1 */
+ } else {
+ ty = CT_MMC; cmd = CMD1; /* MMCv3 */
+ }
+ for (tmr = 10000; tmr && send_cmd(cmd, 0); tmr--) dly_100us(); /* Wait for leaving idle state */
+ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
+ ty = 0;
+ }
+ }
+ CardType = ty;
+ deselect();
+
+ stat = ty ? 0 : STA_NOINIT;
+
+ return stat;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Partial Sector */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_readp (
+ BYTE* buff, /* Pointer to the destination object */
+ DWORD sector, /* Sector number (LBA) */
+ UINT offset, /* Offset in the sector */
+ UINT count /* Byte count (bit15:destination) */
+)
+{
+ DRESULT res;
+ BYTE rc;
+ WORD bc;
+
+ if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
+
+ res = RES_ERROR;
+ if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */
+
+ bc = 40000;
+ do { /* Wait for data packet */
+ rc = rcv_spi();
+ } while (rc == 0xFF && --bc);
+
+ if (rc == 0xFE) { /* A data packet arrived */
+ bc = 514 - offset - count;
+
+ /* Skip leading bytes */
+ if (offset) {
+ do rcv_spi(); while (--offset);
+ }
+
+ /* Receive a part of the sector */
+ do {
+ *buff++ = rcv_spi();
+ } while (--count);
+
+ /* Skip trailing bytes and CRC */
+ do rcv_spi(); while (--bc);
+
+ res = RES_OK;
+ }
+ }
+
+ deselect();
+
+ return res;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write Partial Sector */
+/*-----------------------------------------------------------------------*/
+/*
+DRESULT disk_writep (
+ const BYTE* buff, // Pointer to the data to be written, NULL:Initiate/Finalize write operation
+ DWORD sc // Sector number (LBA) or Number of bytes to send
+)
+{
+ DRESULT res;
+
+
+ if (!buff) {
+ if (sc) {
+
+ // Initiate write process
+
+ } else {
+
+ // Finalize write process
+
+ }
+ } else {
+
+ // Send data to the disk
+
+ }
+
+ return res;
+}
+*/
diff --git a/bootloader_zevero_sd_m1284p_make/m1284p_zevero_sd_m1284p_fuses.txt b/bootloader_zevero_sd_m1284p_make/m1284p_zevero_sd_m1284p_fuses.txt
new file mode 100644
index 0000000..e50695a
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/m1284p_zevero_sd_m1284p_fuses.txt
@@ -0,0 +1,29 @@
+3) Working FUSE for M1284 (with bootloader Zevero-SD)
+I.e - Arduino Bootloader to Flash from SD Card: https://github.com/zevero/avr_boot
+
+PS. SET FUSES:
+==============
+ LOW = 0xFF
+ HIGH = 0xDA
+ EXTD = 0xFD
+========================================
+It means:
+Ext. XTAL High FREQ START-UP 16K CK + 65ms
+JTAG DISABLED
+BROWN-OUT 2.7V ON
+BOOT-LOADER ENABLED
+BOOT Flash Section Size = 2048 words; Boot Start address = 0xF800
+=========================================
+
+AVRDUDE arguments:
+-U lfuse:w:0xff:m -U hfuse:w:0xda:m -U efuse:w:0xfd:m
+
+Full commands to write from console:
+avrdude -Pusb -cavrispmkii -patmega1284p -B5 -U lfuse:w:0xff:m -U hfuse:w:0xda:m -U efuse:w:0xfd:m
+
+
+Detection avrdude CPU: B5 (5us bit clock period for programmer SPI) - VERY IMPORTANT (1Mhz CPU M1284p FREQ DEFAULT)
+avrdude -Pusb -cavrispmkii -patmega1284p -B5
+
+Check m1284p fuse here:
+http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega1284p
diff --git a/bootloader_zevero_sd_m1284p_make/main.c b/bootloader_zevero_sd_m1284p_make/main.c
new file mode 100644
index 0000000..e06a340
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/main.c
@@ -0,0 +1,259 @@
+/*-------------------------------------------------------------------------/
+/ Stand-alone MMC boot loader R0.01
+/--------------------------------------------------------------------------/
+/
+/ Copyright (C) 2010, ChaN, all right reserved.
+/
+/ * This software is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/--------------------------------------------------------------------------/
+/ Dec 6, 2010 R0.01 First release
+/--------------------------------------------------------------------------/
+/ This is a stand-alone MMC/SD boot loader for megaAVRs. It requires a 4KB
+/ boot section for code, four GPIO pins for MMC/SD as shown in sch.jpg and
+/ nothing else. To port the boot loader into your project, follow the
+/ instruction described below.
+/
+/ 1. Setup the hardware. Attach a memory card socket to the any GPIO port
+/ where you like. Select boot size at least 4KB for the boot loader with
+/ BOOTSZ fuses and enable boot loader with BOOTRST fuse.
+/
+/ 2. Setup the software. Change the four port definitions in the asmfunc.S.
+/ Change MCU_TARGET, BOOT_ADR and MCU_FREQ in the Makefile. The BOOT_ADR
+/ is a BYTE address of boot section in the flash. Build the boot loader
+/ and write it to the device with a programmer.
+/
+/ 3. Build the application program and output it in binary form instead of
+/ hex format. Rename the file "app.bin" and put it into the memory card.
+/
+/ 4. Insert the card and turn the target power on. When the boot loader found
+/ the application file, the file is written into the flash memory prior to
+/ start the application program. On-board LED lights (if exist) during
+/ the flash programming operation.
+/
+/-------------------------------------------------------------------------*/
+
+const char filename[13] ="FIRMWARE.BIN\0"; // EDIT FILENAME HERE
+#include
+#include
+#include
+#include
+#include
+#include "pff/src/pff.h"
+#include //Watchdog
+// The following code is recommended in http://avr-libc.nongnu.org/user-manual/group__avr__watchdog.html but is disabled for now because avr_boot doesn't currently do anything with mcusr_mirror so for now we will only reset MCUSR and disable WDT.
+//uint8_t mcusr_mirror __attribute__ ((section (".noinit")));void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));void get_mcusr(void){mcusr_mirror = MCUSR;MCUSR = 0;wdt_disable();}
+void disable_watchdog(void) __attribute__((naked)) __attribute__((section(".init3")));
+void disable_watchdog(void)
+{
+#if defined(MCUCSR)
+ MCUCSR = ~(_BV(WDRF)); //Some MCUs require the watchdog reset flag to be cleared before WDT can be disabled. & operation is skipped to spare few bytes as bits in MCUSR can only be cleared.
+#else
+ MCUSR = ~(_BV(WDRF)); //Some MCUs require the watchdog reset flag to be cleared before WDT can be disabled. & operation is skipped to spare few bytes as bits in MCUSR can only be cleared.
+#endif
+ wdt_disable(); //immediately disable watchdog in case it was running in the application to avoid perpetual reset loop
+}
+
+#if BOOT_ADR > 0xFFFF
+ #define PGM_READ_BYTE(x) pgm_read_byte_far(x)
+#else
+ #define PGM_READ_BYTE(x) pgm_read_byte(x)
+#endif
+
+#if USE_UART
+ #include "uart/uart.h"
+#endif
+
+#if USE_LED
+void init_leds();
+void led_power_on();
+void led_power_off();
+void led_power_toggle();
+void led_write_on();
+void led_write_off();
+void led_write_toggle();
+#endif
+void flash_erase (DWORD); /* Erase a flash page (asmfunc.S) */
+void flash_write (DWORD, const BYTE*); /* Program a flash page (asmfunc.S) */
+
+
+FATFS Fatfs; // Petit-FatFs work area
+BYTE Buff[SPM_PAGESIZE]; // Page data buffer
+
+
+
+static uint8_t pagecmp(const DWORD fa, uint8_t buff[SPM_PAGESIZE])
+{
+ UINT i;
+ uint8_t b_flash,b_buff;
+ for (i = 0; i < SPM_PAGESIZE; i++) {
+ b_flash = PGM_READ_BYTE(fa+i);
+ b_buff = buff[i];
+ if ( b_flash != b_buff) {
+ #if USE_UART //output first difference
+ UART_puthex32(fa);UART_puts(PSTR(":"));
+ UART_puthex(b_flash);UART_puts(PSTR(" "));
+ UART_puthex(b_buff); UART_newline();
+ #endif
+ return 1;
+ }
+ }
+ #if USE_UART //output first difference
+ UART_puthex32(fa);UART_puts(PSTR(":"));
+ UART_puts(PSTR("="));UART_newline();
+ #endif
+ return 0;
+}
+
+void doFlash() {
+ DWORD fa; /* Flash address */
+ UINT br; /* Bytes read */
+ #if USE_LED
+ uint8_t i;
+ for(i=0;i<50;i++) { led_write_toggle();_delay_ms(100);} //Start Programming: Flash WRITE Wildly for 5 secs
+ #endif
+
+
+ for (fa = 0; fa < BOOT_ADR; fa += SPM_PAGESIZE) { /* Update all application pages */
+
+ memset(Buff, 0xFF, SPM_PAGESIZE); /* Clear buffer */
+ pf_read(Buff, SPM_PAGESIZE, &br); /* Load a page data */
+
+ if (pagecmp(fa, Buff)) { /* Only flash if page is changed */
+ #if USE_LED
+ led_write_off();
+ //led_power_on();
+ #endif
+ flash_erase(fa); /* Erase a page */
+ flash_write(fa, Buff); /* Write it if the data is available */
+
+ } else {
+
+ #if USE_LED
+ //led_power_off();
+ led_write_on();
+ #endif
+ }
+ }
+}
+
+void checkFile() {
+ uint8_t fresult;
+
+ fresult = pf_mount(&Fatfs); /* Initialize file system */
+
+ if (fresult != FR_OK) { /* File System could not be mounted */
+ #if USE_UART
+ UART_puts(PSTR("File not mounted"));
+ UART_newline();
+ #endif
+
+ #if USE_LED
+ //uint8_t i;
+ //led_write_on();
+ //for(i=0;i<2*fresult;i++) { led_power_toggle();_delay_ms(500);}//Give error number while Write led is on
+ //led_write_off();
+ #endif
+ return;
+ }
+/*
+
+ WORD flashver = eeprom_read_word((const uint16_t *)E2END - 1);
+ if (flashver > 999) {
+ flashver = 0;
+ }
+ BYTE y, tmp;
+ WORD x;
+ BYTE found = 0;
+
+ for (x = flashver+10; x > flashver; x--) {
+ y = x / 100;
+ filename[5] = y + 0x30;
+ tmp = x % 100;
+
+ y = tmp / 10;
+ filename[6] = y + 0x30;
+ tmp = x % 10;
+
+ filename[7] = tmp + 0x30;
+
+ if (pf_open(filename) == FR_OK) { // File opens normally
+ found = 1;
+ doProgram();
+ }
+ led_power_toggle();
+ }
+
+ if (found == 0) {*/
+
+ fresult = pf_open(filename);
+
+ if (fresult != FR_OK) { /* File could not be opened */
+
+ #if USE_UART
+ UART_puts(PSTR("File not open"));
+ UART_newline();
+ #endif
+ #if USE_LED
+ //uint8_t i;
+ //led_power_on();
+ //for(i=0;i<2*fresult;i++) { led_write_toggle();_delay_ms(500);}//Give error number while Power led is on
+ //led_power_off();
+ #endif
+ return;
+ }
+
+ doFlash();
+
+ #if USE_LED
+ led_write_off();
+ //led_power_off();
+ _delay_ms(2000);
+ uint8_t i;
+ //for(i=0;i<40;i++) { led_power_toggle();_delay_ms(50);}//SUCCESS FLASH WILDLY for 2 secs
+ for(i=0;i<40;i++) { led_write_toggle();_delay_ms(50);}//SUCCESS FLASH WILDLY for 2 secs
+ #endif
+
+}
+
+
+
+
+
+
+int main (void)
+{
+ #if USE_LED
+ init_leds();
+ uint8_t i=0;
+ #endif
+
+ #if USE_UART
+ UART_init();
+ UART_puts(PSTR("AVR_BOOT"));
+ UART_newline();
+ #endif
+ while (1) {
+ #if USE_LED
+ //led_power_on();_delay_ms(200);led_power_off(); //Test Power Led
+ led_write_on();_delay_ms(200);led_write_off(); //Test Write Led
+ #endif
+
+ checkFile();
+
+ if (pgm_read_word(0) != 0xFFFF) ((void(*)(void))0)(); //EXIT BOOTLOADER
+
+ #if USE_UART
+ UART_puts(PSTR("retry"));
+ UART_newline();
+ #endif
+ #if USE_LED
+ //for(i=0;i<10;i++) { led_power_toggle();_delay_ms(200);} //SOMETHING WENT WRONG: Flash Power LED
+ for(i=0;i<10;i++) { led_write_toggle();_delay_ms(200);} //SOMETHING WENT WRONG: Flash Write LED
+ #endif
+ _delay_ms(5000); // Retry
+ }
+}
diff --git a/bootloader_zevero_sd_m1284p_make/pff/doc/00index_p.html b/bootloader_zevero_sd_m1284p_make/pff/doc/00index_p.html
new file mode 100644
index 0000000..46847cd
--- /dev/null
+++ b/bootloader_zevero_sd_m1284p_make/pff/doc/00index_p.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+Petit FAT File System Module
+
+
+
+
Petit FAT File System Module
+
+
+
+
+
Petit FatFs is a sub-set of FatFs module for tiny 8-bit microcontrollers. It is written in compliance with ANSI C and completely separated from the disk I/O layer. It can be incorporated into the tiny microcontrollers with limited memory even if the RAM size is less than sector size. Also full featured FAT file system module is available here↗.
+
+
Features
+
+
Very small RAM consumption (44 bytes work area + certain stack).
Since the Petit FatFs module is completely separated from disk I/O layer, it requires following functions to lower layer to read data from storage device. The low level disk I/O module is not a part of Petit FatFs module and it must be provided by user. The sample drivers are also available in the resources.
The Petit FatFs module is a free software and is opened for education, research and development. You can use, modify and/or redistribute it for personal, non-profit or commercial use without any restriction under your responsibility. For further information, refer to the application note.
The FatFs module is assuming following conditions on portability.
+
+
ANSI C
+The FatFs module is a middleware written in ANSI C (C89). There is no platform dependence, so long as the compiler is in compliance with ANSI C.
+
Size of integer types
+The FatFs module assumes that size of char/short/long are 8/16/32 bit and int is 16 or 32 bit. These correspondence are defined in integer.h. This will not be a problem on most compilers. When any conflict with existing definitions is occured, you must resolve it with care.
+
+
+
+
+
Memory Usage (R0.03)
+
+
AVR
x86
+
Compiler
gcc(WinAVR)
VC6
+
_WORD_ACCESS
1
1
+
Code (default)
2100
1720
+
Code (!_USE_READ)
-444
-246
+
Code (_USE_DIR)
+1002
+420
+
Code (_USE_LSEEK)
+490
+228
+
Code (_USE_WRITE)
+518
+351
+
RAM (bss)
2
4
+
RAM (work)
42
44
+
+
This is the size of the Petit FatFs module itself. In addition to this, a low level disk I/O module will be required for a complete function. The size of MMC/SDC module on AVR becomes approximate 620 bytes without write function and 840 bytes with write function.
+
+
+
+
Module Size Reduction
+
Follwing table shows which function is removed by configuration options for the module size reduction.
+
+
Function
_USE_READ
_USE_DIR
_USE_LSEEK
_USE_WRITE
+
0
0
0
0
+
pf_mount
+
pf_open
+
pf_read
x
+
pf_lseek
x
+
pf_opendir
x
+
pf_readdir
x
+
pf_write
x
+
+
+
+
+
Performance effective file access
+
For good performance on reading a file on the small embedded system, application programmer should consider what process is done in the file system module.
+
The Petit FatFs reads the disk sectors without a sector buffer. This means the file system reads a part of the sector contains the required data every reference point even if they are in the same sector. However the generic storage device are not byte addressable so that the disk I/O layer will read the entire sector and pick up the data bytes from the read data steram.
+
When read 512 byte data from a file at a time, the data sector will be read only a time. When read that data in byte-by-byte, the data sector will be read 512 times. Therefore the byte-by-byte read request will drastically decrease the read performance. To avoid this stupid read controls, the file data should be read in long block as possible. Sector alignment access is not impotant on the Petit FatFs.
+
The tiny microcontrollers targeted by Petit FatFs has a limited size of RAM. It may not able to allocate a certain size of read buffer and most type of text processing will require byte-by-byte read operation. The Petit FatFs supports data forwarding feature for such purpose.
+
+
+
+
+
About FatFs License
+
Petit FatFs has being developped as a personal project of author, ChaN. It is free from the code anyone else wrote. Following code block shows a copy of the license document that included in the source files.
+
/*----------------------------------------------------------------------------/
+/ Petit FatFs - FAT file system module R0.03 (C)ChaN, 2014
+/-----------------------------------------------------------------------------/
+/ Petit FatFs module is a generic FAT file system module for small embedded
+/ systems. This is a free software that opened for education, research and
+/ commercial developments under license policy of following trems.
+/
+/ Copyright (C) 2014, ChaN, all right reserved.
+/
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/-----------------------------------------------------------------------------/
+
Therefore FatFs license is one of the BSD-style licenses but there is a significant feature. Because FatFs is for embedded projects, the conditions of redistributions in binary form, such as embedded code, hex file, binary library and any form without source code, are not specified in order to extend usability to commercial use. The documentation of the distributions need not include about Petit FatFs and its license document, and it may also. This is equivalent to the BSD 1-Clause License. Of course Petit FatFs is compatible with the projects under GNU GPL. When redistribute the Petit FatFs with any modification, the license can also be changed to GNU GPL or BSD-style license.
The disk_initialize function initializes the disk drive.
+
+DSTATUS disk_initialize (void)
+
+
+
+
+
Return Values
+
The disk status is returned in combination of following flags.
+
+
STA_NOINIT
+
Indicates that the disk drive has not been initialized. This flag is set on: system reset, disk removal and disk_initialize function failed, and cleared on: disk_initialize function succeeded.
+
STA_NODISK
+
Indicates that no medium in the drive. This is always cleared on fixed disk drive. This flag is not referred by Petit FatFs.
+
+
+
+
+
Description
+
The disk_initialize function initializes the storage device. If the function succeeded, STA_NOINIT flag in the return value is cleared.
The disk_readp function reads a partial sector of the device.
+
+DRESULT disk_readp (
+ BYTE* buff, /* [OUT] Pointer to the read buffer */
+ DWORD sector, /* [IN] Sector number */
+ UINT offset, /* [IN] Byte offset in the sector to start to read */
+ UINT count/* [IN] Number of bytes to read */
+);
+
+
+
+
+
Parameters
+
+
buff
+
Pointer to the read buffer to store the read data. If a NULL is given, read bytes will be forwarded to the outgoing stream instead of the memory.
+
sector
+
Specifies the sector number to be read in logical block address (LBA).
+
offset
+
Specifies the byte offset in the sector to start to read. The value can be 0 to 511.
+
count
+
Specifies number of bytes to read. The value can be 0 to 512 and offset + count must not exceed 512.
+
+
+
+
+
+
Return Value
+
+
RES_OK (0)
+
The function succeeded.
+
RES_ERROR
+
Any hard error occured during the disk read operation and could not recover it.
The disk_writep function writes data to the sector.
+
+DRESULT disk_writep (
+ BYTE* buff, /* [IN] Pointer to the data to be written */
+ DWORD sc, /* [IN] Sector number or Number of bytes to wtite */
+);
+
+
+
+
+
Parameters
+
+
buff
+
Pointer to the data to be written to the sector. If a NULL is given, the function initiate/finalize a write transaction to the sector.
+
sc
+
Specifies nubmer of bytes to write if buff is not a NULL. If buff is a NULL and sc is not a zero, the function initiates a write transactin to the sector. If buff and sc are zero, the function finalize the current sector write transactin.
+
+
+
+
+
+
Return Value
+
+
RES_OK (0)
+
The function succeeded.
+
RES_ERROR
+
Any hard error occured during the write operation and could not recover it or the medium is write protected.
+
RES_PARERR
+
Invalid parameter.
+
RES_NOTRDY
+
The device has not been initialized.
+
+
+
+
+
+
Description
+
A sector write operation is done in following sequence.
+
+
disk_writep(0, sector_number); Initiate a sector write transaction.
+
disk_writep(data, byte_to_write); Start to write data to the sector.
+
disk_writep(data, byte_to_write); And data can be written upto 512 bytes with one or more calls.
+
disk_writep(data, byte_to_write); ...
+
disk_writep(0, 0); Finalize the write transaction. If number of bytes sent is less than 512, left bytes in the sector is filled by zero.
+
+
If a write transaction is in progress, disk_readp() function will fail and disk_initialize() function finalize the current write transaction.
The path name format on the Petit FatFs module is similer to MS-DOS as follows.
+
"[/]directory/file"
+
The Petit FatFs module supports only 8.3 format file name. The sub-directories are separated with a /. The path name is terminated with a nul character, control character or white space. Heading spaces are ignored and skipped. When _USE_LCC == 1, lower case characters are allowed for the path name.
+
The Petit FatFs module does not have a concept of current directory like OS oriented file system. All objects on the volume are always specified in full path name following from the root directory. Heading separator is ignored and it can be exist or omitted.
The pf_lseek function moves the file read/write pointer of the open file.
+
+
+FRESULT pf_lseek (
+ DWORD ofs/* [IN] File offset in unit of byte */
+);
+
+
+
+
+
Parameters
+
+
ofs
+
Number of bytes where from start of the file
+
+
+
+
+
+
Return Values
+
+
FR_OK (0)
+
The function succeeded.
+
FR_DISK_ERR
+
The function failed due to an error in the disk function, a wrong FAT structure or an internal error.
+
FR_NOT_OPENED
+
The file has not been opened.
+
+
+
+
+
+
Description
+
The pf_lseek() function moves the file read/write pointer of the open file. The offset can be specified in only origin from top of the file.
+
+
+
+
+
Example
+
+ /* Move to offset of 5000 from top of the file */
+ res = pf_lseek(5000);
+
+ /* Forward 3000 bytes */
+ res = pf_lseek(fs.fptr + 3000);
+
+ /* Rewind 2000 bytes (take care on wraparound) */
+ res = pf_lseek(fs.fptr - 2000);
+
+FRESULT pf_mount (
+ FATFS* fs/* [IN] Pointer to the work area */
+);
+
+
+
+
+
Parameters
+
+
fs
+
Pointer to the work area (file system object) to be registered.
+
+
+
+
+
Return Values
+
+
FR_OK (0)
+
The function succeeded.
+
FR_NOT_READY
+
The drive could not be initialized due to a disk error or no medium.
+
FR_DISK_ERR
+
An error occured in the disk function.
+
FR_NO_FILESYSTEM
+
There is no valid FAT partition on the disk.
+
+
+
+
+
+
Description
+
The pf_mount() function registers a work area to the Petit FatFs module. The volume is mounted on registration. The volume must be mounted with this function prior to any other file function and after every media changes.
+FRESULT pf_open (
+ const char* path/* [IN] Pointer to the file neme */
+);
+
+
+
+
+
Parameters
+
+
path
+
Pointer to a null-terminated string that specifies the file name to open.
+
+
+
+
+
+
Return Values
+
+
FR_OK (0)
+
The function succeeded.
+
FR_NO_FILE
+
Could not find the file or path.
+
FR_DISK_ERR
+
The function failed due to a hard error in the disk function, a wrong FAT structure or an internal error.
+
FR_NOT_ENABLED
+
The volume has not been mounted.
+
+
+
+
+
+
Description
+
The file must be opend prior to use pf_read() and pf_lseek() function. The open file is valid until next open.
+
+
+
+
+
Example
+
+int main (void)
+{
+ FATFS fs; /* Work area (file system object) for the volume */
+ BYTE buff[16]; /* File read buffer */
+ UINT br; /* File read count */
+ FRESULT res; /* Petit FatFs function common result code */
+
+
+ /* Mount the volume */
+ pf_mount(&fs);
+ if (res) die(res);
+
+ /* Open a file */
+ res = pf_open("srcfile.dat");
+ if (res) die(res);
+
+ /* Read data to the memory */
+ res = pf_read(buff, 16, &br); /* Read data to the buff[] */
+ if (res) die(res); /* Check error */
+ if (br != 16) die(255); /* Check EOF */
+
+ ....
+
+ /* Forward data to the outgoing stream */
+ do
+ res = pf_read(0, 512, &br); /* Send data to the stream */
+ while (res || br != 512); /* Break on error or eof */
+
+ ....
+
+}
+
+FRESULT pf_opendir (
+ DIR* dp, /* [OUT] Pointer to the blank directory object structure */
+ const char* path/* [IN] Pointer to the directory name */
+);
+
+
+
+
+
Parameters
+
+
dp
+
Pointer to the blank directory object to be created.
+
path
+
Pinter to the null-terminated string that specifies the directory name to be opened.
+
+
+
+
+
+
Return Values
+
+
FR_OK (0)
+
The function succeeded and the directory object is created. It is used for subsequent calls to read the directory entries.
+
FR_NO_FILE
+
Could not find the path.
+
FR_NOT_READY
+
The disk drive cannot work due to no medium in the drive or any other reason.
+
FR_DISK_ERR
+
The function failed due to a hard error in the disk function, a wrong FAT structure or an internal error.
+
FR_NOT_ENABLED
+
The volume has no work area.
+
+
+
+
+
+
Description
+
The pf_opendir() function opens an exsisting directory and creates the directory object for subsequent calls. The directory object structure can be discarded at any time without any procedure.
+FRESULT pf_read (
+ void* buff, /* [OUT] Pointer to the read buffer */
+ UINT btr, /* [IN] Number of bytes to read */
+ UINT* br/* [OUT] Number of bytes read */
+);
+
+
+
+
+
Parameters
+
+
buff
+
Pointer to the buffer to store the read data. A NULL specifies the destination is an outgoing stream.
+
btr
+
Number of bytes to read.
+
br
+
Pointer to the variable to return number of bytes read.
+
+
+
+
+
+
Return Values
+
+
FR_OK (0)
+
The function succeeded.
+
FR_DISK_ERR
+
The function failed due to a hard error in the disk function, a wrong FAT structure or an internal error.
+
FR_NOT_OPENED
+
The file has not been opened.
+
FR_NOT_ENABLED
+
The volume has not been mounted.
+
+
+
+
+
+
Description
+
The file read/write pointer in the file system object advances in number of bytes read. After the function succeeded, *br should be checked to detect end of file. In case of *br < btr, it means the read pointer reached end of file during read operation.
+
If a NULL is given to the buff, the read bytes will be forwarded to the outgoing stream instead of the memory. The streaming function will be typically built-in the disk_readp() function.
+FRESULT pf_readdir (
+ DIR* dp, /* [IN] Pointer to the open directory object */
+ FILINFO* fno/* [OUT] Pointer to the file information structure */
+);
+
+
+
+
+
Parameters
+
+
dp
+
Pointer to the open directory object.
+
fno
+
Pointer to the file information structure to store the read item.
+
+
+
+
+
+
Return Values
+
+
FR_OK (0)
+
The function succeeded.
+
FR_DISK_ERR
+
The function failed due to an error in the disk function, a wrong FAT structure or an internal error.
+
FR_NOT_OPENED
+
The directory object has not been opened.
+
+
+
+
+
+
Description
+
The pf_readdir() function reads directory entries in sequence. All items in the directory can be read by calling this function repeatedly. When all directory entries have been read and no item to read, the function returns a null string into member f_name[] in the file information structure without error. When a null pointer is given to the fno, the read index of the directory object will be rewinded.
+
+
+
+
+
Sample Code
+
+FRESULT scan_files (char* path)
+{
+ FRESULT res;
+ FILINFO fno;
+ DIR dir;
+ int i;
+
+
+ res = pf_opendir(&dir, path);
+ if (res == FR_OK) {
+ i = strlen(path);
+ for (;;) {
+ res = pf_readdir(&dir, &fno);
+ if (res != FR_OK || fno.fname[0] == 0) break;
+ if (fno.fattrib & AM_DIR) {
+ sprintf(&path[i], "/%s", fno.fname);
+ res = scan_files(path);
+ if (res != FR_OK) break;
+ path[i] = 0;
+ } else {
+ printf("%s/%s\n", path, fno.fname);
+ }
+ }
+ }
+
+ return res;
+}
+
The FATFS structure holds dynamic work area of the logical drive and a file. It is given by application program and registerd/unregisterd to the Petit FatFs module with pf_mount function. There is no member that can be changed by application programs.
+
+typedef struct {
+ BYTE fs_type; /* FAT sub type */
+ BYTE csize; /* Number of sectors per cluster */
+ BYTE flag; /* File status flags */
+ BYTE pad1;
+ WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */
+ CLUST n_fatent; /* Number of FAT entries (= number of clusters + 2) */
+ DWORD fatbase; /* FAT start sector */
+ DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */
+ DWORD database; /* Data start sector */
+ DWORD fptr; /* File read/write pointer */
+ DWORD fsize; /* File size */
+ CLUST org_clust; /* File start cluster */
+ CLUST curr_clust; /* File current cluster */
+ DWORD dsect; /* File current data sector */
+} FATFS;
+
+FRESULT pf_write (
+ const void* buff, /* [IN] Pointer to the data to be written */
+ UINT btw, /* [IN] Number of bytes to write */
+ UINT* bw/* [OUT] Pointer to the variable to return number of bytes written */
+);
+
+
+
+
+
Parameters
+
+
buff
+
Pointer to the data to be wtitten. A NULL specifies to finalize the current write operation.
+
btw
+
Number of bytes to write.
+
bw
+
Pointer to the variable to return number of bytes read.
+
+
+
+
+
+
Return Values
+
+
FR_OK (0)
+
The function succeeded.
+
FR_DISK_ERR
+
The function failed due to a hard error in the disk function, write protected, a wrong FAT structure or an internal error.
+
FR_NOT_OPENED
+
The file has not been opened.
+
FR_NOT_ENABLED
+
The volume has not been mounted.
+
+
+
+
+
+
Description
+
The write function has some restrictions listed below:
+
+
Cannot create file. Only existing file can be written.
+
Cannot expand file size.
+
Cannot update time stamp of the file.
+
Write operation can start/stop on the sector boundary.
+
Read-only attribute of the file cannot block write operation.
+
+
File write operation must be done in following sequence.
+
+
pf_lseek(ofs); read/write pointer must be moved to sector bundary prior to initiate write operation or it will be rounded-down to the sector boundary.
+
pf_write(buff, btw, &bw); Initiate write operation. Write first data to the file.
+
pf_write(buff, btw, &bw); Write next data. Any other file function cannot be used while a write operation is in progress.
+
pf_write(0, 0, &bw); Finalize the write operation. If read/write pointer is not on the sector boundary, left bytes in the sector will be filled with zero.
+
+
The read/write pointer in the file system object advances in number of bytes written. After the function succeeded, *bw should be checked to detect end of file. In case of *bw < btw, it means the read/write pointer reached end of file during the write operation. Once a write operation is initiated, it must be finalized or the written data can be lost.