102 Commits
debug ... mmc

Author SHA1 Message Date
optixx
23efb8da74 change project 2009-08-24 20:27:28 +02:00
David Voswinkel
dade0ea275 add test dir loop 2009-08-18 09:11:07 +02:00
David Voswinkel
6edd54b092 switch file id to 32bit and get sram push working 2009-08-18 08:38:48 +02:00
David Voswinkel
dc8ed94279 add dir entry debug dump 2009-08-17 22:05:05 +02:00
David Voswinkel
7046230e31 push dir entry to sram 2009-08-17 21:44:38 +02:00
David Voswinkel
ed0a95cad5 fix file_entry struct 2009-08-17 20:39:38 +02:00
David Voswinkel
31768e2a41 Merge branch 'mmc' of git@github.com:optixx/quickdev16 into mmc 2009-08-12 21:19:18 +02:00
optixx
041cf089ad add header 2009-08-12 18:04:54 +02:00
optixx
cf090451df add dir ent to sram copy 2009-08-11 15:42:14 +02:00
David Voswinkel
51876b83ad cleanup 2009-08-10 19:46:45 +02:00
David Voswinkel
8d961dc446 Merge branch 'mmc' of git@github.com:optixx/quickdev16 into mmc
Conflicts:
	avr/usbload/fat.h
	avr/usbload/file.c
	avr/usbload/testing.c
2009-08-10 19:44:15 +02:00
David Voswinkel
9859b1fbc8 cleanup types: 2009-08-10 19:34:03 +02:00
David Voswinkel
8656beb769 code cleanup 2009-08-10 19:26:01 +02:00
optixx
f1f836bdc7 disable file write function and save 4kb progmem 2009-08-10 16:29:36 +02:00
David Voswinkel
4a0740dd02 replace mmc layer with old software spi stuff 2009-08-09 14:19:32 +02:00
David Voswinkel
d095867fe4 try to use irq for CS and use dedicated SS for hardware SPI 2009-08-09 13:12:44 +02:00
David Voswinkel
2aee210d13 switch to mmc-0.5.4 2009-08-09 12:15:06 +02:00
David Voswinkel
a27521b22b first tests 2009-08-09 10:37:51 +02:00
David Voswinkel
2132b572ff add mmc layer 2009-08-08 16:43:51 +02:00
David Voswinkel
dbff180a91 get sram restore working and make the switch to quickdev loader more
mature
2009-08-08 16:04:45 +02:00
David Voswinkel
df167b285e Merge branch 'master' of git@github.com:optixx/quickdev16 2009-08-08 15:06:35 +02:00
David Voswinkel
cd7ac81a2d add debug shm 2009-08-06 22:04:08 +02:00
David Voswinkel
f7dc5b3bd8 add upload progress 2009-08-06 22:03:50 +02:00
David Voswinkel
1f68465dc6 simplify mode swicthing 2009-08-06 21:26:16 +02:00
David Voswinkel
5e5df7e275 remove obsolte slow sram functions and depending higherlevel stuff 2009-08-06 21:25:24 +02:00
David Voswinkel
ba2ac254a7 remove sram_copy and sram_set 2009-08-06 21:18:11 +02:00
David Voswinkel
1282e93334 refactor testing code 2009-08-06 21:16:58 +02:00
David Voswinkel
decb810bcc move commands to own file and remove unsed usb methods 2009-08-06 21:10:25 +02:00
David Voswinkel
b6d5d1b571 add delya/irq switch for shared mem 2009-08-06 20:44:44 +02:00
optixx
406c884cfe add addr save and restore functions 2009-08-06 12:15:04 +02:00
optixx
6ef9989320 add sharedmem read 2009-08-06 11:22:14 +02:00
optixx
97962b8e89 split shared memroy access into tx and rx section 2009-08-06 10:52:44 +02:00
David Voswinkel
cf95b95723 make huffman optional 2009-08-05 20:15:28 +02:00
David Voswinkel
af45ed720b cleanup up and remove huffman stuff 2009-08-04 08:38:26 +02:00
David Voswinkel
92762d7f51 get new quickdevloader commands working 2009-08-03 21:44:23 +02:00
David Voswinkel
3e3fbe5bc4 optimze rle converter 2009-08-03 19:34:27 +02:00
David Voswinkel
570323f017 add convert and webpy 2009-08-02 16:30:01 +02:00
David Voswinkel
d1447db7b0 get shared mem working 2009-08-02 16:02:36 +02:00
David Voswinkel
1b45c2f325 add shared memory module to put loader status 2009-08-01 18:19:21 +02:00
David Voswinkel
1539ff6111 optimize size, and make debug and ftl stuff optional 2009-08-01 16:59:31 +02:00
David Voswinkel
c5e72c48eb tweak makefile 2009-08-01 15:21:32 +02:00
David Voswinkel
82a6edad50 split up image into c and header file 2009-08-01 15:16:55 +02:00
David Voswinkel
553ef0059a cleanup uploader code 2009-08-01 15:16:11 +02:00
David Voswinkel
01e41d36dd add header file for loader rom 2009-08-01 15:15:52 +02:00
David Voswinkel
3a85bb2ee5 change banner again 2009-08-01 13:29:52 +02:00
David Voswinkel
29fb976051 new project name 2009-07-28 08:38:28 +02:00
David Voswinkel
3e988eafe2 cleanup 2009-07-28 08:37:58 +02:00
David Voswinkel
7f84c8d97a add loader 2009-07-28 08:37:40 +02:00
David Voswinkel
1c8c3dc244 new header 2009-07-27 17:09:12 +02:00
David Voswinkel
170ef9f5c6 cleanup code 2009-07-27 16:55:48 +02:00
David Voswinkel
6cab377087 add rle encoded loader rom 2009-07-26 12:39:08 +02:00
David Voswinkel
8670300642 add reset line to snes 2009-07-21 22:57:21 +02:00
David Voswinkel
68d4ffc7f1 get bootloader working 2009-07-21 22:12:52 +02:00
david
31989233b4 add banner 2009-07-21 15:47:24 +02:00
david
b2bf789b85 startover again and port fd0's loader to the 644 2009-07-21 15:28:09 +02:00
David Voswinkel
e45b08a5fb change fuses , always watchdog and 2048 words bootloader section 2009-07-20 23:13:21 +02:00
David Voswinkel
9e1a9fffc5 port to atmega644 and reconfigure watchdog 2009-07-20 23:12:01 +02:00
David Voswinkel
8bee3f786f o update vusb 2009-07-20 23:11:37 +02:00
David Voswinkel
31687b3094 cleanup 2009-07-20 19:12:25 +02:00
David Voswinkel
cc2c7ab4dc add boot loader 2009-07-20 19:08:05 +02:00
David Voswinkel
a7270acdf1 o add monitor 2009-07-20 19:05:40 +02:00
David Voswinkel
56713860ac new fuses for bootloader 2009-07-15 17:22:10 +02:00
David Voswinkel
fbd05f2863 add bootloader 2009-07-15 17:21:13 +02:00
David Voswinkel
3a794947f0 add backup header 2009-07-12 15:16:19 +02:00
David Voswinkel
ed16c23002 Merge branch 'master' of git@github.com:optixx/snesram 2009-07-12 15:15:37 +02:00
David Voswinkel
446c3932ae disable irq stuff and add watchdog 2009-07-12 15:14:29 +02:00
David Voswinkel
8e2889212a do some irq testing 2009-07-12 15:11:27 +02:00
David Voswinkel
5a2bba0d33 get hi/lorom sniff working properly 2009-07-12 11:57:01 +02:00
david
8f0096eb5e add rom inject 2009-07-09 11:58:28 +02:00
david
18c4b45824 rename 2009-07-09 10:24:13 +02:00
David Voswinkel
0f9ebb146e add reset via usb and usb triggered avr/snes mode switching 2009-07-09 00:54:02 +02:00
David Voswinkel
d7b82e2503 add hirom support 2009-07-08 20:09:34 +02:00
David Voswinkel
ef14c4dcd8 add hirom support 2009-07-08 19:04:37 +02:00
David Voswinkel
d609954c8b add fink library path for os x build 2009-07-08 18:27:33 +02:00
David Voswinkel
05db3108a2 fix merge error 2009-07-08 18:25:41 +02:00
david
a518ff1e1e port upload code 2009-07-07 15:08:17 +02:00
david
e67e726743 cleanup code 2009-07-07 11:27:47 +02:00
david
ff6e13d8f0 fix 2009-07-07 11:24:12 +02:00
David Voswinkel
935b2a3557 add snesram dummmy uploader 2009-07-06 23:19:22 +02:00
David Voswinkel
2e84cf22d1 add snesram prototype 2009-07-06 22:54:45 +02:00
David Voswinkel
bcd3d802f0 skip rom header 2009-07-06 22:12:28 +02:00
David Voswinkel
fd1e5d890a tweak regdump stuff 2009-07-06 20:06:05 +02:00
David Voswinkel
5cb972e7f6 upload is wokring 2009-07-06 20:05:25 +02:00
David Voswinkel
21298fc63f cleanup test roms 2009-07-06 20:04:31 +02:00
David Voswinkel
f1b89eee83 remove address setting and tweak upload speed 2009-07-05 11:47:52 +02:00
David Voswinkel
10d435d2f9 cleanup dump 2009-07-05 11:37:42 +02:00
David Voswinkel
690bfd6502 add floating point timer and end address to bulk init 2009-07-05 11:29:52 +02:00
David Voswinkel
c55a66f90d add timer and more debug code 2009-07-05 10:49:32 +02:00
David Voswinkel
fef90c7f6e test disable irq 2009-07-05 10:49:01 +02:00
David Voswinkel
8d571d0c55 change makefile 2009-07-05 10:47:23 +02:00
David Voswinkel
c110d1132a do 32 banks crc check 2009-07-05 10:46:41 +02:00
David Voswinkel
30399e2d1c add padding script 2009-07-05 10:45:30 +02:00
David Voswinkel
78b77a1352 add sound test 2009-07-05 10:45:16 +02:00
David Voswinkel
b67de0308c add sound sample 2009-07-05 10:44:30 +02:00
David Voswinkel
9d707f612a add regdump 2009-07-05 10:44:00 +02:00
david
0a62ac52be add timer 2009-07-02 11:24:12 +02:00
David Voswinkel
7ef03b498f enable bulk sram transfers 2009-06-30 23:40:18 +02:00
David Voswinkel
656192fc14 crc checks working, simple uploads working 2009-06-30 23:04:24 +02:00
David Voswinkel
77d9418cee bank 0x00 upload working with crc 2009-06-29 21:48:24 +02:00
David Voswinkel
2ebd2b75aa fix new debug routing and start debugging sram bulk 2009-06-29 08:53:59 +02:00
David Voswinkel
f9724a3209 Merge branch 'debug' 2009-06-25 19:31:22 +02:00
David Voswinkel
6419623018 fix typo 2009-06-25 19:19:09 +02:00
284 changed files with 52683 additions and 2341 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "scripts/webpy"]
path = scripts/webpy
url = git://github.com/webpy/webpy.git

1
README
View File

@@ -1 +0,0 @@
o Test

78
avr/bootloader/Makefile Normal file
View File

@@ -0,0 +1,78 @@
# microcontroller and project specific settings
TARGET = bootloader
F_CPU = 20000000UL
MCU = atmega644
SRC = bootloader.c
ASRC = usbdrv/usbdrvasm.S interrupts.S
OBJECTS += $(patsubst %.c,%.o,${SRC})
OBJECTS += $(patsubst %.S,%.o,${ASRC})
HEADERS += $(shell echo *.h)
# CFLAGS += -Werror
LDFLAGS += -L/usr/local/avr/avr/lib
CFLAGS += -Iusbdrv -I.
CFLAGS += -DHARDWARE_REV=$(HARDWARE_REV)
CDEFS += -DF_CPU
ASFLAGS += -x assembler-with-cpp
ASFLAGS += -Iusbdrv -I.
# use own linkerscript, for special interrupt table handling
LDFLAGS += -T ./ldscripts/avr5.x
# no safe mode checks
AVRDUDE_FLAGS += -u
# set name for dependency-file
MAKEFILE = Makefile
# bootloader section start
# (see datasheet)
ifeq ($(MCU),atmega168)
# atmega168 with 1024 words bootloader:
# bootloader section starts at 0x1c00 (word-address) == 0x3800 (byte-address)
BOOT_SECTION_START = 0x3800
else ifeq ($(MCU),atmega88)
# atmega88 with 1024 words bootloader:
# bootloader section starts at 0xc00 (word-address) == 0x1800 (byte-address)
BOOT_SECTION_START = 0x1800
else ifeq ($(MCU),atmega644)
# atmega644 with 2048 words bootloader:
# bootloader section starts at 0x7800 (word-address) == 0xF000 (byte-address)
BOOT_SECTION_START = 0xf000
endif
LDFLAGS += -Wl,--section-start=.text=$(BOOT_SECTION_START) -Wl,-u,vfprintf
CFLAGS += -DBOOT_SECTION_START=$(BOOT_SECTION_START)
include avr.mk
.PHONY: all
all: $(TARGET).hex $(TARGET).lss
@echo "==============================="
@echo "$(TARGET) compiled for: $(MCU)"
@echo -n "size is: "
@$(SIZE) -A $(TARGET).hex | grep "\.sec1" | tr -s " " | cut -d" " -f2
@echo "==============================="
$(TARGET): $(OBJECTS) $(TARGET).o
%.o: $(HEADERS)
.PHONY: clean clean-$(TARGET)
clean: clean-$(TARGET)
clean-$(TARGET):
$(RM) $(TARGET) $(OBJECTS)
.PHONY: depend test
depend:
$(CC) $(CFLAGS) -M $(CDEFS) $(CINCS) $(SRC) >> $(MAKEFILE).dep
-include $(MAKEFILE).dep

View File

@@ -1,7 +1,7 @@
# Programmer used for In System Programming # Programmer used for In System Programming
ISP_PROG = dapa ISP_PROG = usbasp
# device the ISP programmer is connected to # device the ISP programmer is connected to
ISP_DEV = /dev/parport0 ISP_DEV =
# Programmer used for serial programming (using the bootloader) # Programmer used for serial programming (using the bootloader)
SERIAL_PROG = avr109 SERIAL_PROG = avr109
# device the serial programmer is connected to # device the serial programmer is connected to
@@ -15,7 +15,6 @@ AS = avr-as
CP = cp CP = cp
RM = rm -f RM = rm -f
AVRDUDE = avrdude AVRDUDE = avrdude
AVRDUDE_BAUDRATE = 19200
SIZE = avr-size SIZE = avr-size
-include $(CURDIR)/config.mk -include $(CURDIR)/config.mk
@@ -33,8 +32,12 @@ endif
ifeq ($(MCU),atmega168) ifeq ($(MCU),atmega168)
AVRDUDE_MCU=m168 AVRDUDE_MCU=m168
endif endif
ifeq ($(MCU),atmega644)
AVRDUDE_MCU=m644
endif
AVRDUDE_FLAGS += -p $(AVRDUDE_MCU) -b $(AVRDUDE_BAUDRATE)
AVRDUDE_FLAGS += -p $(AVRDUDE_MCU)
# flags for the compiler # flags for the compiler
CFLAGS += -g -Os -finline-limit=800 -mmcu=$(MCU) -DF_CPU=$(F_CPU) -std=gnu99 CFLAGS += -g -Os -finline-limit=800 -mmcu=$(MCU) -DF_CPU=$(F_CPU) -std=gnu99
@@ -62,27 +65,14 @@ $(OBJECTS):
clean: clean:
$(RM) *.hex *.eep.hex *.o *.lst *.lss $(RM) *.hex *.eep.hex *.o *.lst *.lss
interactive-isp:
$(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -t
interactive-serial:
$(AVRDUDE) $(AVRDUDE_FLAGS) -c $(SERIAL_PROG) -P $(SERIAL_DEV) -t
.PHONY: all clean interactive-isp interactive-serial launch-bootloader .PHONY: all clean interactive-isp interactive-serial launch-bootloader
program-isp-%: %.hex flash:
$(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U flash:w:$< $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -U flash:w:$<
program-isp-eeprom-%: %.eep.hex flash-eeprom-%: %.eep.hex
$(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U eeprom:w:$< $(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U eeprom:w:$<
program-serial-%: %.hex
$(AVRDUDE) $(AVRDUDE_FLAGS) -c $(SERIAL_PROG) -P $(SERIAL_DEV) -U flash:w:$<
program-serial-eeprom-%: %.eep.hex launch-bootloader
$(AVRDUDE) $(AVRDUDE_FLAGS) -c $(SERIAL_PROG) -P $(SERIAL_DEV) -U eeprom:w:$<
%.hex: % %.hex: %
$(OBJCOPY) -O ihex -R .eeprom $< $@ $(OBJCOPY) -O ihex -R .eeprom $< $@
@@ -94,6 +84,3 @@ program-serial-eeprom-%: %.eep.hex launch-bootloader
%-size: %.hex %-size: %.hex
$(SIZE) $< $(SIZE) $<
launch-bootloader:
launch-bootloader $(SERIAL_DEV) $(AVRDUDE_BAUDRATE)

534
avr/bootloader/bootloader.c Normal file
View File

@@ -0,0 +1,534 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* simple USBasp compatible bootloader by
* Alexander Neumann <alexander@lochraster.org>
* inspired by USBasploader by Christian Starkjohann,
* =====================================================================================
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/boot.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <string.h>
#include <avr/wdt.h>
#include "config.h"
#include "usbdrv/usbdrv.c"
/*
* USBasp requests, taken from the original USBasp sourcecode
*/
#define USBASP_FUNC_CONNECT 1
#define USBASP_FUNC_DISCONNECT 2
#define USBASP_FUNC_TRANSMIT 3
#define USBASP_FUNC_READFLASH 4
#define USBASP_FUNC_ENABLEPROG 5
#define USBASP_FUNC_WRITEFLASH 6
#define USBASP_FUNC_READEEPROM 7
#define USBASP_FUNC_WRITEEEPROM 8
#define USBASP_FUNC_SETLONGADDRESS 9
/*
* additional functions
*/
#define FUNC_ECHO 0x17
/*
* atmel isp commands
*/
#define ISP_CHIP_ERASE1 0xAC
#define ISP_CHIP_ERASE2 0x80
#define ISP_READ_SIGNATURE 0x30
#define ISP_READ_EEPROM 0xa0
#define ISP_WRITE_EEPROM 0xc0
#define LED_PORT PORTC
#define LED_DIR DDRC
#define LED_PIN PC7
#define DLED_ON {((LED_PORT &=~ (1 << LED_PIN)),\
(LED_DIR &=~ (1 << LED_PIN))); }
#define DLED_OFF {((LED_PORT &=~ (1 << LED_PIN)),\
(LED_DIR |= (1 << LED_PIN))); }
#define DLED_TGL {((LED_PORT &=~ (1 << LED_PIN)),\
(LED_DIR ^= (1 << LED_PIN)));}
/*
* some predefined signatures, taken from the original USBasp sourcecode
*/
static const uint8_t signature[4] = {
#ifdef SIGNATURE_BYTES
SIGNATURE_BYTES
#elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8HVA__)
0x1e, 0x93, 0x07, 0
#elif defined (__AVR_ATmega48__) || defined (__AVR_ATmega48P__)
0x1e, 0x92, 0x05, 0
#elif defined (__AVR_ATmega88__) || defined (__AVR_ATmega88P__)
0x1e, 0x93, 0x0a, 0
#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega168P__)
0x1e, 0x94, 0x06, 0
#elif defined (__AVR_ATmega328P__)
0x1e, 0x95, 0x0f, 0
#elif defined (__AVR_ATmega644__)
0x1e, 0x96, 0x09, 0
#else
# error "Device signature is not known, please edit config.h!"
#endif
};
#ifndef BOOT_SECTION_START
# error "BOOT_SECTION_START undefined!"
#endif
#if defined (__AVR_ATmega644__)
/*
* Due arvdude limitations we can't erase the whole progmem without running into an usb timeount on cleint side. So we we limit the
* erase section by 0x1000
*/
#define ERASE_SECTION 0xe000
#else
#define ERASE_SECTION BOOT_SECTION_START
#endif
#ifdef DEBUG_UART
static __attribute__ ((__noinline__))
void uart_putc(uint8_t data)
{
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = data;
}
#else
#define uart_putc(x)
#endif
#ifdef DEBUG_UART
static __attribute__ ((__noinline__))
void uart_puts(uint8_t * data)
{
while (*data) {
uart_putc(*data);
data++;
}
}
#else
#define uart_puts(x)
#endif
/*
* supply custom usbDeviceConnect() and usbDeviceDisconnect() macros which turn the interrupt on and off at the right times, and prevent
* the execution of an interrupt while the pullup resistor is switched off
*/
#ifdef USB_CFG_PULLUP_IOPORTNAME
#undef usbDeviceConnect
#define usbDeviceConnect() do { \
USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT); \
USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT); \
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); \
} while(0);
#undef usbDeviceDisconnect
#define usbDeviceDisconnect() do { \
USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); \
USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT); \
USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT); \
} while(0);
#endif
/*
* prototypes
*/
void __attribute__ ((__noreturn__, __noinline__,
__naked__)) leave_bootloader(void);
/*
* we just support flash sizes <= 64kb, for code size reasons if you need to program bigger devices, have a look at USBasploader:
* http://www.obdev.at/products/avrusb/usbasploader.html
*/
#if FLASHEND > 0xffff
# error "usbload only supports up to 64kb of flash!"
#endif
/*
* we are just checking the lower byte of flash_address, so make sure SPM_PAGESIZE is <= 256
*/
#if SPM_PAGESIZE > 256
# error "SPM_PAGESIZE is too big (just checking lower byte)"
#endif
/*
* start flash (byte address) read/write at this address
*/
usbWord_t flash_address;
uint8_t bytes_remaining;
uint8_t request;
uint8_t request_exit;
uint8_t timeout;
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *req = (void *) data;
uint8_t len = 0;
static uint8_t buf[4];
/*
* set global data pointer to local buffer
*/
usbMsgPtr = buf;
/*
* on enableprog just return one zero, which means success
*/
if (req->bRequest == USBASP_FUNC_ENABLEPROG) {
buf[0] = 0;
len = 1;
timeout = 255;
} else if (req->bRequest == USBASP_FUNC_CONNECT) {
/*
* turn on led
*/
DLED_ON;
} else if (req->bRequest == USBASP_FUNC_DISCONNECT) {
/*
* turn off led
*/
DLED_OFF;
request_exit = 1;
/*
* catch query for the devicecode, chip erase and eeprom byte requests
*/
} else if (req->bRequest == USBASP_FUNC_TRANSMIT) {
/*
* reset buffer with zeroes
*/
memset(buf, '\0', sizeof(buf));
/*
* read the address for eeprom operations
*/
usbWord_t address;
address.bytes[0] = data[4]; /* low byte is data[4] */
address.bytes[1] = data[3]; /* high byte is data[3] */
/*
* if this is a request to read the device signature, answer with the appropiate signature byte
*/
if (data[2] == ISP_READ_SIGNATURE) {
/*
* the complete isp data is reported back to avrdude, but we just need byte 4 bits 0 and 1 of byte 3 determine the signature
* byte address
*/
buf[3] = signature[data[4] & 0x03];
#ifdef ENABLE_CATCH_EEPROM_ISP
/*
* catch eeprom read
*/
} else if (data[2] == ISP_READ_EEPROM) {
buf[3] = eeprom_read_byte((uint8_t *) address.word);
/*
* catch eeprom write
*/
} else if (data[2] == ISP_WRITE_EEPROM) {
/*
* address is in data[4], data[3], and databyte is in data[5]
*/
eeprom_write_byte((uint8_t *) address.word, data[5]);
#endif
/*
* catch a chip erase
*/
} else if (data[2] == ISP_CHIP_ERASE1 && data[3] == ISP_CHIP_ERASE2) {
uart_puts("\n\rErase Flash");
for (flash_address.word = 0;
flash_address.word < ERASE_SECTION;
flash_address.word += SPM_PAGESIZE) {
/*
* wait and erase page
*/
boot_spm_busy_wait();
if (flash_address.word && flash_address.word % 1024 == 0)
uart_putc('.');
cli();
boot_page_erase(flash_address.word);
sei();
}
uart_puts("\n\r");
}
/*
* in case no data has been filled in by the if's above, just return zeroes
*/
len = 4;
#ifdef ENABLE_ECHO_FUNC
/*
* implement a simple echo function, for testing the usb connectivity
*/
} else if (req->bRequest == FUNC_ECHO) {
buf[0] = req->wValue.bytes[0];
buf[1] = req->wValue.bytes[1];
len = 2;
#endif
} else if (req->bRequest >= USBASP_FUNC_READFLASH) {
/*
* && req->bRequest <= USBASP_FUNC_SETLONGADDRESS
*/
/*
* extract address and length
*/
flash_address.word = req->wValue.word;
bytes_remaining = req->wLength.bytes[0];
request = req->bRequest;
/*
* hand control over to usbFunctionRead()/usbFunctionWrite()
*/
len = 0xff;
}
return len;
}
uchar usbFunctionWrite(uchar * data, uchar len)
{
if (len > bytes_remaining)
len = bytes_remaining;
bytes_remaining -= len;
if (request == USBASP_FUNC_WRITEEEPROM) {
for (uint8_t i = 0; i < len; i++)
eeprom_write_byte((uint8_t *) flash_address.word++, *data++);
} else {
/*
* data is handled wordwise, adjust len
*/
len /= 2;
len -= 1;
for (uint8_t i = 0; i <= len; i++) {
uint16_t *w = (uint16_t *) data;
cli();
boot_page_fill(flash_address.word, *w);
sei();
usbWord_t next_address;
next_address.word = flash_address.word;
next_address.word += 2;
data += 2;
/*
* write page if page boundary is crossed or this is the last page
*/
if (next_address.bytes[0] % SPM_PAGESIZE == 0 ||
(bytes_remaining == 0 && i == len)) {
cli();
boot_page_write(flash_address.word);
sei();
boot_spm_busy_wait();
cli();
boot_rww_enable();
sei();
}
flash_address.word = next_address.word;
}
}
/*
* flash led on activity
*/
DLED_TGL;
return (bytes_remaining == 0);
}
uchar usbFunctionRead(uchar * data, uchar len)
{
if (len > bytes_remaining)
len = bytes_remaining;
bytes_remaining -= len;
for (uint8_t i = 0; i < len; i++) {
if (request == USBASP_FUNC_READEEPROM)
*data = eeprom_read_byte((void *) flash_address.word);
else
*data = pgm_read_byte_near((void *) flash_address.word);
data++;
flash_address.word++;
}
/*
* flash led on activity
*/
DLED_TGL;
return len;
}
void (*jump_to_app) (void) = 0x0000;
void leave_bootloader(void)
{
cli();
/*
* disconnect usb
*/
usbDeviceDisconnect();
for (uint8_t i = 0; i < 50; i++)
_delay_ms(10); /* 0 means 0x10000, 38*1/f*0x10000 =~ 498ms */
/*
* enable watchdog to soft-reset the uC for clean startup of new application
*/
wdt_enable(WDTO_15MS);
/*
* let watchdog kick in and reset uC
*/
while (1);
}
int __attribute__ ((noreturn, OS_main)) main(void)
{
/*
* start bootloader
*/
#ifdef DEBUG_UART
/*
* init uart (115200 baud, at 20mhz)
*/
UBRR0L = 10;
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
UCSR0B = _BV(TXEN0);
#endif
uint8_t reset = MCUSR;
uint16_t delay = 0;
timeout = TIMEOUT;
uart_puts("Snesram Bootloader v0.1\n\r");
/*
* if power-on reset, quit bootloader via watchdog reset
*/
if (reset & _BV(PORF)) {
uart_puts("Found power on reset\n\r");
MCUSR = 0;
leave_bootloader();
}
/*
* if watchdog reset, disable watchdog and jump to app
*/
else if (reset & _BV(WDRF)) {
uart_puts("Found watchdog reset\n\r");
MCUSR = 0;
wdt_disable();
DLED_TGL;
_delay_ms(500);
DLED_TGL;
_delay_ms(500);
uart_puts("Jump to main\n\r");
jump_to_app();
}
uart_puts("Enter programming mode\n\r");
/*
* else: enter programming mode
*/
/*
* clear external reset flags
*/
MCUSR = 0;
/*
* init exit request state
*/
request_exit = 0;
/*
* move interrupts to boot section
*/
MCUCR = (1 << IVCE);
MCUCR = (1 << IVSEL);
/*
* enable interrupts
*/
sei();
/*
* initialize usb pins
*/
usbInit();
/*
* disconnect for ~500ms, so that the host re-enumerates this device
*/
usbDeviceDisconnect();
for (uint8_t i = 0; i < 50; i++)
_delay_ms(10); /* 0 means 0x10000, 38*1/f*0x10000 =~ 498ms */
usbDeviceConnect();
uart_puts("Wait for firmware");
while (1) {
usbPoll();
delay++;
/*
* do some led blinking, so that it is visible that the bootloader is still running
*/
if (delay == 0) {
uart_putc('.');
DLED_TGL;
if (timeout < 255)
timeout--;
}
if (request_exit || timeout == 0) {
uart_puts("\n\rExit\n\r");
_delay_ms(10);
leave_bootloader();
}
}
}

View File

@@ -15,4 +15,8 @@
//#define ENABLE_ECHO_FUNC //#define ENABLE_ECHO_FUNC
/* uncomment this for debug information via uart */ /* uncomment this for debug information via uart */
//#define DEBUG_UART #define DEBUG_UART
#define DEBUG 1
#define DEBUG_USB 2

View File

@@ -5,5 +5,5 @@
/* micro-jumptable, we are using just reset and int0 vectors */ /* micro-jumptable, we are using just reset and int0 vectors */
exit: exit:
__vector_default: __vector_default:
rjmp __init jmp __init
rjmp __vector_1 jmp __vector_1

View File

@@ -231,40 +231,3 @@ Scroll down to the bottom to see the most recent changes.
- Added 20 MHz module contributed by Jeroen Benschop. - Added 20 MHz module contributed by Jeroen Benschop.
* Release 2008-05-13 * Release 2008-05-13
- Fixed bug in libs-host/hiddata.c function usbhidGetReport(): length
was not incremented, pointer to length was incremented instead.
- Added code to command line tool(s) which claims an interface. This code
is disabled by default, but may be necessary on newer Linux kernels.
- Added usbconfig.h option "USB_CFG_CHECK_DATA_TOGGLING".
- New header "usbportability.h" prepares ports to other development
environments.
- Long transfers (above 254 bytes) did not work when usbFunctionRead() was
used to supply the data. Fixed this bug. [Thanks to Alexander Neumann!]
- In hiddata.c (example code for sending/receiving data over HID), use
USB_RECIP_DEVICE instead of USB_RECIP_INTERFACE for control transfers so
that we need not claim the interface.
- in usbPoll() loop 20 times polling for RESET state instead of 10 times.
This accounts for the higher clock rates we now support.
- Added a module for 12.8 MHz RC oscillator with PLL in receiver loop.
- Added hook to SOF code so that oscillator can be tuned to USB frame clock.
- Added timeout to waitForJ loop. Helps preventing unexpected hangs.
- Added example code for oscillator tuning to libs-device (thanks to
Henrik Haftmann for the idea to this routine).
- Implemented option USB_CFG_SUPPRESS_INTR_CODE.
* Release 2008-10-22
- Fixed libs-device/osctune.h: OSCCAL is memory address on ATMega88 and
similar, not offset of 0x20 needs to be added.
- Allow distribution under GPLv3 for those who have to link against other
code distributed under GPLv3.
* Release 2008-11-26
- Removed libusb-win32 dependency for hid-data example in Makefile.windows.
It was never required and confused many people.
- Added extern uchar usbRxToken to usbdrv.h.
- Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser.
* Release 2009-03-23

View File

@@ -1,5 +1,5 @@
AVR-USB Driver Software License Agreement AVR-USB Driver Software License Agreement
Version 2008-10-07 Version 2008-04-15
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
@@ -26,11 +26,11 @@ and host side software examples and libraries.
code of AVR-USB. code of AVR-USB.
2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the 2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the
non-exclusive right to use, copy and distribute AVR-USB with your hardware non-exclusive right to use and distribute AVR-USB with your hardware
product(s), restricted by the limitations in section 3 below. product(s), restricted by the limitations in section 3 below.
2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify 2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify
the source code and your copy of AVR-USB according to your needs. your copy of AVR-USB according to your needs.
2.4 USB IDs. OBJECTIVE DEVELOPMENT grants you the exclusive rights to use 2.4 USB IDs. OBJECTIVE DEVELOPMENT grants you the exclusive rights to use
USB Product ID(s) sent to you in e-mail after receiving your payment in USB Product ID(s) sent to you in e-mail after receiving your payment in

View File

@@ -1,8 +1,6 @@
OBJECTIVE DEVELOPMENT GmbH's AVR-USB driver software is distributed under the OBJECTIVE DEVELOPMENT GmbH's AVR-USB driver software is distributed under the
terms and conditions of the GNU GPL version 2 or the GNU GPL version 3. It is terms and conditions of the GNU GPL version 2, see the text below. In addition
your choice whether you apply the terms of version 2 or version 3. The full to the requirements in the GPL, we STRONGLY ENCOURAGE you to do the following:
text of GPLv2 is included below. In addition to the requirements in the GPL,
we STRONGLY ENCOURAGE you to do the following:
(1) Publish your entire project on a web site and drop us a note with the URL. (1) Publish your entire project on a web site and drop us a note with the URL.
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission. Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.

View File

@@ -33,7 +33,7 @@ The driver consists of the following files:
defined to a value greater than 0. Link this module defined to a value greater than 0. Link this module
to your code! to your code!
oddebug.h .............. Interface definitions of the debug module. oddebug.h .............. Interface definitions of the debug module.
usbportability.h ....... Header with compiler-dependent stuff. iarcompat.h ............ Compatibility definitions for IAR C-compiler.
usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this
module instead of usbdrvasm.S when you assembler module instead of usbdrvasm.S when you assembler
with IAR's tools. with IAR's tools.
@@ -47,10 +47,9 @@ The driver consists of the following files:
CPU CORE CLOCK FREQUENCY CPU CORE CLOCK FREQUENCY
======================== ========================
We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz, We supply assembler modules for clock frequencies of 12 MHz, 15 MHz, 16 MHz and
16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The 16.5 MHz. Other clock rates are not supported. The actual clock rate must be
actual clock rate must be configured in usbdrv.h unless you use the default configured in usbdrv.h unless you use the default 12 MHz.
12 MHz.
12 MHz Clock 12 MHz Clock
This is the traditional clock rate of AVR-USB because it's the lowest clock This is the traditional clock rate of AVR-USB because it's the lowest clock
@@ -68,29 +67,19 @@ if you need the slightly higher clock rate for performance reasons. Since
16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code 16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
is somewhat tricky and has to insert a leap cycle every third byte. is somewhat tricky and has to insert a leap cycle every third byte.
12.8 MHz and 16.5 MHz Clock 16.5 MHz Clock
The assembler modules for these clock rates differ from the other modules The assembler module for this clock rate differs from the other modules because
because they have been built for an RC oscillator with only 1% precision. The it has been built for an RC oscillator with only 1% precision. The receiver
receiver code inserts leap cycles to compensate for clock deviations. 1% is code inserts leap cycles to compensate for clock deviations. 1% is also the
also the precision which can be achieved by calibrating the internal RC precision which can be achieved by calibrating the internal RC oscillator of
oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL the AVR. Please note that only AVRs with internal 64 MHz PLL oscillator can be
oscillator can reach 16.5 MHz with the RC oscillator. This includes the very used since the 8 MHz RC oscillator cannot be trimmed up to 16.5 MHz. This
popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost includes the very popular ATTiny25, ATTiny45, ATTiny85 series as well as the
all AVRs can reach 12.8 MHz, although this is outside the specified range. ATTiny26.
See the EasyLogger example at http://www.obdev.at/avrusb/easylogger.html for See the EasyLogger example at http://www.obdev.at/avrusb/easylogger.html for
code which calibrates the RC oscillator based on the USB frame clock. code which calibrates the RC oscillator based on the USB frame clock.
18 MHz Clock
This module is closer to the USB specification because it performs an on the
fly CRC check for incoming packets. Packets with invalid checksum are
discarded as required by the spec. If you also implement checks for data
PID toggling on application level (see option USB_CFG_CHECK_DATA_TOGGLING
in usbconfig.h for more info), this ensures data integrity. Due to the CRC
tables and alignment requirements, this code is bigger than modules for other
clock rates. To activate this module, you must define USB_CFG_CHECK_CRC to 1
and USB_CFG_CLOCK_KHZ to 18000 in usbconfig.h.
20 MHz Clock 20 MHz Clock
This module is for people who won't do it with less than the maximum. Since This module is for people who won't do it with less than the maximum. Since
20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code 20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
@@ -126,11 +115,10 @@ usbdrv.c because this module has been deliberately optimized for gcc.
USING AVR-USB FOR FREE USING AVR-USB FOR FREE
====================== ======================
The AVR firmware driver is published under the GNU General Public License The AVR firmware driver is published under the GNU General Public License
Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is Version 2 (GPL2). See the file "License.txt" for details.
your choice whether you apply the terms of version 2 or version 3.
If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the If you decide for the free GPL2, we STRONGLY ENCOURAGE you to do the following
following things IN ADDITION to the obligations from the GPL: things IN ADDITION to the obligations from the GPL2:
(1) Publish your entire project on a web site and drop us a note with the URL. (1) Publish your entire project on a web site and drop us a note with the URL.
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission. Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
@@ -151,7 +139,7 @@ to your modifications for our commercial license offerings.
COMMERCIAL LICENSES FOR AVR-USB COMMERCIAL LICENSES FOR AVR-USB
=============================== ===============================
If you don't want to publish your source code under the terms of the GPL, If you don't want to publish your source code under the terms of the GPL2,
you can simply pay money for AVR-USB. As an additional benefit you get you can simply pay money for AVR-USB. As an additional benefit you get
USB PIDs for free, licensed exclusively to you. See the file USB PIDs for free, licensed exclusively to you. See the file
"CommercialLicense.txt" for details. "CommercialLicense.txt" for details.

View File

@@ -4,7 +4,7 @@
* Creation Date: 2007-11-05 * Creation Date: 2007-11-05
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id$ * Revision: $Id$
*/ */
@@ -103,11 +103,8 @@ sofError:
reti reti
handleData: handleData:
#if USB_CFG_CHECK_CRC lds token, usbCurrentTok;[18]
CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error tst token ;[20]
#endif
lds shift, usbCurrentTok;[18]
tst shift ;[20]
breq doReturn ;[21] breq doReturn ;[21]
lds x2, usbRxLen ;[22] lds x2, usbRxLen ;[22]
tst x2 ;[24] tst x2 ;[24]
@@ -116,11 +113,8 @@ handleData:
; recognized if usbPoll() was called less frequently than once every 4 ms. ; recognized if usbPoll() was called less frequently than once every 4 ms.
cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack
brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP
#if USB_CFG_CHECK_DATA_TOGGLING
sts usbCurrentDataToken, token ; store for checking by C code
#endif
sts usbRxLen, cnt ;[28] store received data, swap buffers sts usbRxLen, cnt ;[28] store received data, swap buffers
sts usbRxToken, shift ;[30] sts usbRxToken, token ;[30]
lds x2, usbInputBufOffset;[32] swap buffers lds x2, usbInputBufOffset;[32] swap buffers
ldi cnt, USB_BUFSIZE ;[34] ldi cnt, USB_BUFSIZE ;[34]
sub cnt, x2 ;[35] sub cnt, x2 ;[35]
@@ -137,11 +131,7 @@ handleIn:
ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
#if USB_CFG_HAVE_INTRIN_ENDPOINT #if USB_CFG_HAVE_INTRIN_ENDPOINT
andi x3, 0xf ;[35] x3 contains endpoint andi x3, 0xf ;[35] x3 contains endpoint
#if USB_CFG_SUPPRESS_INTR_CODE
brne sendNakAndReti ;[36]
#else
brne handleIn1 ;[36] brne handleIn1 ;[36]
#endif
#endif #endif
lds cnt, usbTxLen ;[37] lds cnt, usbTxLen ;[37]
sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set
@@ -160,7 +150,7 @@ handleIn:
; RAM this way and avoid potential problems with endless retries. The rest of ; RAM this way and avoid potential problems with endless retries. The rest of
; the driver assumes error-free transfers anyway. ; the driver assumes error-free transfers anyway.
#if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */ #if USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
handleIn1: ;[38] handleIn1: ;[38]
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint ; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
@@ -174,8 +164,9 @@ handleIn1: ;[38]
ldi YL, lo8(usbTxBuf1) ;[46] ldi YL, lo8(usbTxBuf1) ;[46]
ldi YH, hi8(usbTxBuf1) ;[47] ldi YH, hi8(usbTxBuf1) ;[47]
rjmp usbSendAndReti ;[48] 50 + 12 = 62 until SOP rjmp usbSendAndReti ;[48] 50 + 12 = 62 until SOP
#endif
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 #if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_HAVE_INTRIN_ENDPOINT3
handleIn3: handleIn3:
lds cnt, usbTxLen3 ;[41] lds cnt, usbTxLen3 ;[41]
sbrc cnt, 4 ;[43] sbrc cnt, 4 ;[43]
@@ -185,4 +176,3 @@ handleIn3:
ldi YH, hi8(usbTxBuf3) ;[48] ldi YH, hi8(usbTxBuf3) ;[48]
rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP
#endif #endif
#endif

View File

@@ -4,8 +4,8 @@
* Creation Date: 2006-03-01 * Creation Date: 2006-03-01
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
* License: Proprietary, free under certain conditions. See Documentation. * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id$ * This Revision: $Id: iarcompat.h 533 2008-02-28 15:35:25Z cs $
*/ */
/* /*
@@ -33,11 +33,6 @@ Thanks to Oleg Semyonov for his help with the IAR tools port!
#endif #endif
#define __attribute__(arg) #define __attribute__(arg)
#define IAR_SECTION(section) @ section
#ifndef USB_BUFFER_SECTION
# define USB_BUFFER_SECTION "TINY_Z" /* if user has not selected a named section */
#endif
#ifdef __IAR_SYSTEMS_ASM__ #ifdef __IAR_SYSTEMS_ASM__
# define __ASSEMBLER__ # define __ASSEMBLER__
@@ -58,6 +53,13 @@ Thanks to Oleg Semyonov for his help with the IAR tools port!
#define sei() __enable_interrupt() #define sei() __enable_interrupt()
#define wdt_reset() __watchdog_reset() #define wdt_reset() __watchdog_reset()
/* Depending on the device you use, you may get problems with the way usbdrv.h
* handles the differences between devices. Since IAR does not use #defines
* for MCU registers, we can't check for the existence of a particular
* register with an #ifdef. If the autodetection mechanism fails, include
* definitions for the required USB_INTR_* macros in your usbconfig.h. See
* usbconfig-prototype.h and usbdrv.h for details.
*/
#endif /* defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__ */ #endif /* defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__ */
#endif /* __iarcompat_h_INCLUDED__ */ #endif /* __iarcompat_h_INCLUDED__ */

View File

@@ -4,8 +4,8 @@
* Creation Date: 2005-01-16 * Creation Date: 2005-01-16
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: oddebug.c 692 2008-11-07 15:07:40Z cs $ * This Revision: $Id: oddebug.c 275 2007-03-20 09:58:28Z cs $
*/ */
#include "oddebug.h" #include "oddebug.h"

View File

@@ -4,8 +4,8 @@
* Creation Date: 2005-01-16 * Creation Date: 2005-01-16
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: oddebug.h 692 2008-11-07 15:07:40Z cs $ * This Revision: $Id: oddebug.h 275 2007-03-20 09:58:28Z cs $
*/ */
#ifndef __oddebug_h_included__ #ifndef __oddebug_h_included__
@@ -29,7 +29,10 @@ the output and a memory block to dump in hex ('data' and 'len').
#endif #endif
/* make sure we have the UART defines: */ /* make sure we have the UART defines: */
#include "usbportability.h" #include "iarcompat.h"
#ifndef __IAR_SYSTEMS_ICC__
# include <avr/io.h>
#endif
#ifndef uchar #ifndef uchar
# define uchar unsigned char # define uchar unsigned char

View File

@@ -4,8 +4,8 @@
* Creation Date: 2005-04-01 * Creation Date: 2005-04-01
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbconfig-prototype.h 734 2009-03-23 11:10:07Z cs $ * This Revision: $Id: usbconfig-prototype.h 600 2008-05-13 10:34:56Z cs $
*/ */
#ifndef __usbconfig_h_included__ #ifndef __usbconfig_h_included__
@@ -44,18 +44,12 @@ section at the end of this file).
* markers every millisecond.] * markers every millisecond.]
*/ */
#define USB_CFG_CLOCK_KHZ (F_CPU/1000) #define USB_CFG_CLOCK_KHZ (F_CPU/1000)
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, /* Clock rate of the AVR in MHz. Legal values are 12000, 15000, 16000, 16500
* 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no * and 20000. The 16.5 MHz version of the code requires no crystal, it
* crystal, they tolerate +/- 1% deviation from the nominal frequency. All * tolerates +/- 1% deviation from the nominal frequency. All other rates
* other rates require a precision of 2000 ppm and thus a crystal! * require a precision of 2000 ppm and thus a crystal!
* Default if not specified: 12 MHz * Default if not specified: 12 MHz
*/ */
#define USB_CFG_CHECK_CRC 0
/* Define this to 1 if you want that the driver checks integrity of incoming
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
* currently only available for 18 MHz crystal clock. You must choose
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
*/
/* ----------------------- Optional Hardware Config ------------------------ */ /* ----------------------- Optional Hardware Config ------------------------ */
@@ -100,14 +94,6 @@ section at the end of this file).
* it is required by the standard. We have made it a config option because it * it is required by the standard. We have made it a config option because it
* bloats the code considerably. * bloats the code considerably.
*/ */
#define USB_CFG_SUPPRESS_INTR_CODE 0
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
* want to send any data over them. If this macro is defined to 1, functions
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
* you need the interrupt-in endpoints in order to comply to an interface
* (e.g. HID), but never want to send any data. This option saves a couple
* of bytes in flash memory and the transmit buffers in RAM.
*/
#define USB_CFG_INTR_POLL_INTERVAL 10 #define USB_CFG_INTR_POLL_INTERVAL 10
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll /* If you compile a version with endpoint 1 (interrupt-in), this is the poll
* interval. The value is in milliseconds and must not be less than 10 ms for * interval. The value is in milliseconds and must not be less than 10 ms for
@@ -170,33 +156,6 @@ section at the end of this file).
* counts SOF packets. This feature requires that the hardware interrupt is * counts SOF packets. This feature requires that the hardware interrupt is
* connected to D- instead of D+. * connected to D- instead of D+.
*/ */
/* #ifdef __ASSEMBLER__
* macro myAssemblerMacro
* in YL, TCNT0
* sts timer0Snapshot, YL
* endm
* #endif
* #define USB_SOF_HOOK myAssemblerMacro
* This macro (if defined) is executed in the assembler module when a
* Start Of Frame condition is detected. It is recommended to define it to
* the name of an assembler macro which is defined here as well so that more
* than one assembler instruction can be used. The macro may use the register
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
* immediately after an SOF pulse may be lost and must be retried by the host.
* What can you do with this hook? Since the SOF signal occurs exactly every
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
* designs running on the internal RC oscillator.
* Please note that Start Of Frame detection works only if D- is wired to the
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
*/
#define USB_CFG_CHECK_DATA_TOGGLING 0
/* define this macro to 1 if you want to filter out duplicate data packets
* sent by the host. Duplicates occur only as a consequence of communication
* errors, when the host does not receive an ACK. Please note that you need to
* implement the filtering yourself in usbFunctionWriteOut() and
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
* for each control- and out-endpoint to check for duplicate packets.
*/
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 #define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
/* define this macro to 1 if you want the function usbMeasureFrameLength() /* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator. * compiled in. This function can be used to calibrate the AVR's RC oscillator.
@@ -284,9 +243,7 @@ section at the end of this file).
* no properties are defined or if they are 0, the default descriptor is used. * no properties are defined or if they are 0, the default descriptor is used.
* Possible properties are: * Possible properties are:
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched * + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is * at runtime via usbFunctionDescriptor().
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
* you want RAM pointers.
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found * + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
* in static memory is in RAM, not in flash memory. * in static memory is in RAM, not in flash memory.
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), * + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
@@ -318,12 +275,6 @@ section at the end of this file).
* USB_CFG_DESCR_PROPS_HID_REPORT * USB_CFG_DESCR_PROPS_HID_REPORT
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) * USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
* *
* Note about string descriptors: String descriptors are not just strings, they
* are Unicode strings prefixed with a 2 byte header. Example:
* int serialNumberDescriptor[] = {
* USB_STRING_DESCRIPTOR_HEADER(6),
* 'S', 'e', 'r', 'i', 'a', 'l'
* };
*/ */
#define USB_CFG_DESCR_PROPS_DEVICE 0 #define USB_CFG_DESCR_PROPS_DEVICE 0

View File

@@ -4,11 +4,15 @@
* Creation Date: 2004-12-29 * Creation Date: 2004-12-29
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.c 721 2009-03-16 19:03:19Z cs $ * This Revision: $Id: usbdrv.c 591 2008-05-03 20:21:19Z cs $
*/ */
#include "usbportability.h" #include "iarcompat.h"
#ifndef __IAR_SYSTEMS_ICC__
# include <avr/io.h>
# include <avr/pgmspace.h>
#endif
#include "usbdrv.h" #include "usbdrv.h"
#include "oddebug.h" #include "oddebug.h"
@@ -34,15 +38,12 @@ uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbT
#if USB_COUNT_SOF #if USB_COUNT_SOF
volatile uchar usbSofCount; /* incremented by assembler module every SOF */ volatile uchar usbSofCount; /* incremented by assembler module every SOF */
#endif #endif
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE #if USB_CFG_HAVE_INTRIN_ENDPOINT
usbTxStatus_t usbTxStatus1; usbTxStatus_t usbTxStatus1;
# if USB_CFG_HAVE_INTRIN_ENDPOINT3 # if USB_CFG_HAVE_INTRIN_ENDPOINT3
usbTxStatus_t usbTxStatus3; usbTxStatus_t usbTxStatus3;
# endif # endif
#endif #endif
#if USB_CFG_CHECK_DATA_TOGGLING
uchar usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */
#endif
/* USB status registers / not shared with asm code */ /* USB status registers / not shared with asm code */
uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */ uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
@@ -55,7 +56,7 @@ static uchar usbMsgFlags; /* flag values see below */
/* /*
optimizing hints: optimizing hints:
- do not post/pre inc/dec integer values in operations - do not post/pre inc/dec integer values in operations
- assign value of USB_READ_FLASH() to register variables and don't use side effects in arg - assign value of PRG_RDB() to register variables and don't use side effects in arg
- use narrow scope for variables which should be in X/Y/Z register - use narrow scope for variables which should be in X/Y/Z register
- assign char sized expressions to variables to force 8 bit arithmetics - assign char sized expressions to variables to force 8 bit arithmetics
*/ */
@@ -194,9 +195,18 @@ PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* We don't use prog_int or prog_int16_t for compatibility with various libc
* versions. Here's an other compatibility hack:
*/
#ifndef PRG_RDB
#define PRG_RDB(addr) pgm_read_byte(addr)
#endif
/* ------------------------------------------------------------------------- */
static inline void usbResetDataToggling(void) static inline void usbResetDataToggling(void)
{ {
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE #if USB_CFG_HAVE_INTRIN_ENDPOINT
USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */ USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
# if USB_CFG_HAVE_INTRIN_ENDPOINT3 # if USB_CFG_HAVE_INTRIN_ENDPOINT3
USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */ USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
@@ -216,7 +226,6 @@ static inline void usbResetStall(void)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#if !USB_CFG_SUPPRESS_INTR_CODE
#if USB_CFG_HAVE_INTRIN_ENDPOINT #if USB_CFG_HAVE_INTRIN_ENDPOINT
static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus) static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus)
{ {
@@ -254,7 +263,6 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
usbGenericSetInterrupt(data, len, &usbTxStatus3); usbGenericSetInterrupt(data, len, &usbTxStatus3);
} }
#endif #endif
#endif /* USB_CFG_SUPPRESS_INTR_CODE */
/* ------------------ utilities for code following below ------------------- */ /* ------------------ utilities for code following below ------------------- */
@@ -400,7 +408,7 @@ uchar index = rq->wIndex.bytes[0];
usbResetStall(); usbResetStall();
SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */ SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */
len = 1; len = 1;
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE #if USB_CFG_HAVE_INTRIN_ENDPOINT
SWITCH_CASE(USBRQ_SET_INTERFACE) /* 11 */ SWITCH_CASE(USBRQ_SET_INTERFACE) /* 11 */
usbResetDataToggling(); usbResetDataToggling();
usbResetStall(); usbResetStall();
@@ -428,7 +436,7 @@ usbRequest_t *rq = (void *)data;
* 0xe1 11100001 (USBPID_OUT: data phase of setup transfer) * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer)
* 0...0x0f for OUT on endpoint X * 0...0x0f for OUT on endpoint X
*/ */
DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */ DBG2(0x10 + (usbRxToken & 0xf), data, len); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
USB_RX_USER_HOOK(data, len) USB_RX_USER_HOOK(data, len)
#if USB_CFG_IMPLEMENT_FN_WRITEOUT #if USB_CFG_IMPLEMENT_FN_WRITEOUT
if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */ if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */
@@ -451,13 +459,9 @@ usbRequest_t *rq = (void *)data;
} }
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */ if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */
/* do some conditioning on replyLen, but on IN transfers only */ /* do some conditioning on replyLen */
if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){ if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){
if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */ replyLen = rq->wLength.bytes[0]; /* IN transfers only */
replyLen = rq->wLength.bytes[0];
}else{
replyLen = rq->wLength.word;
}
} }
usbMsgFlags = USB_FLG_USE_USER_RW; usbMsgFlags = USB_FLG_USE_USER_RW;
}else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */ }else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */
@@ -501,7 +505,7 @@ static uchar usbDeviceRead(uchar *data, uchar len)
uchar i = len, *r = usbMsgPtr; uchar i = len, *r = usbMsgPtr;
if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
do{ do{
uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */ uchar c = PRG_RDB(r); /* assign to char size variable to enforce byte ops */
*data++ = c; *data++ = c;
r++; r++;
}while(--i); }while(--i);
@@ -588,17 +592,17 @@ uchar i;
usbBuildTxBlock(); usbBuildTxBlock();
} }
} }
for(i = 20; i > 0; i--){ for(i = 10; i > 0; i--){
uchar usbLineStatus = USBIN & USBMASK; uchar usbLineStatus = USBIN & USBMASK;
if(usbLineStatus != 0) /* SE0 has ended */ if(usbLineStatus != 0) /* SE0 has ended */
goto isNotReset; break;
} }
/* RESET condition, called multiple times during reset */ if(i == 0){ /* RESET condition, called multiple times during reset */
usbNewDeviceAddr = 0; usbNewDeviceAddr = 0;
usbDeviceAddr = 0; usbDeviceAddr = 0;
usbResetStall(); usbResetStall();
DBG1(0xff, 0, 0); DBG1(0xff, 0, 0);
isNotReset: }
usbHandleResetHook(i); usbHandleResetHook(i);
} }
@@ -614,7 +618,7 @@ USB_PUBLIC void usbInit(void)
#endif #endif
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
usbResetDataToggling(); usbResetDataToggling();
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE #if USB_CFG_HAVE_INTRIN_ENDPOINT
usbTxLen1 = USBPID_NAK; usbTxLen1 = USBPID_NAK;
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
usbTxLen3 = USBPID_NAK; usbTxLen3 = USBPID_NAK;

View File

@@ -4,14 +4,14 @@
* Creation Date: 2004-12-29 * Creation Date: 2004-12-29
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.h 738 2009-03-23 11:13:24Z cs $ * This Revision: $Id: usbdrv.h 607 2008-05-13 15:57:28Z cs $
*/ */
#ifndef __usbdrv_h_included__ #ifndef __usbdrv_h_included__
#define __usbdrv_h_included__ #define __usbdrv_h_included__
#include "usbconfig.h" #include "usbconfig.h"
#include "usbportability.h" #include "iarcompat.h"
/* /*
Hardware Prerequisites: Hardware Prerequisites:
@@ -34,8 +34,8 @@ usbDeviceConnect() and usbDeviceDisconnect() further down in this file.
Please adapt the values in usbconfig.h according to your hardware! Please adapt the values in usbconfig.h according to your hardware!
The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz The device MUST be clocked at exactly 12 MHz, 15 MHz or 16 MHz
or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details. or at 16.5 MHz +/- 1%. See usbconfig-prototype.h for details.
Limitations: Limitations:
@@ -122,7 +122,7 @@ USB messages, even if they address another (low-speed) device on the same bus.
/* --------------------------- Module Interface ---------------------------- */ /* --------------------------- Module Interface ---------------------------- */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#define USBDRV_VERSION 20090323 #define USBDRV_VERSION 20080513
/* This define uniquely identifies a driver version. It is a decimal number /* This define uniquely identifies a driver version. It is a decimal number
* constructed from the driver's release date in the form YYYYMMDD. If the * constructed from the driver's release date in the form YYYYMMDD. If the
* driver's behavior or interface changes, you can use this constant to * driver's behavior or interface changes, you can use this constant to
@@ -273,8 +273,6 @@ USB_PUBLIC uchar usbFunctionRead(uchar *data, uchar len);
* to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. * to 1 in usbconfig.h and return 0xff in usbFunctionSetup()..
*/ */
#endif /* USB_CFG_IMPLEMENT_FN_READ */ #endif /* USB_CFG_IMPLEMENT_FN_READ */
extern uchar usbRxToken; /* may be used in usbFunctionWriteOut() below */
#if USB_CFG_IMPLEMENT_FN_WRITEOUT #if USB_CFG_IMPLEMENT_FN_WRITEOUT
USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len); USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len);
/* This function is called by the driver when data is received on an interrupt- /* This function is called by the driver when data is received on an interrupt-
@@ -341,12 +339,6 @@ extern volatile uchar usbSofCount;
* the macro USB_COUNT_SOF is defined to a value != 0. * the macro USB_COUNT_SOF is defined to a value != 0.
*/ */
#endif #endif
#if USB_CFG_CHECK_DATA_TOGGLING
extern uchar usbCurrentDataToken;
/* This variable can be checked in usbFunctionWrite() and usbFunctionWriteOut()
* to ignore duplicate packets.
*/
#endif
#define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8)) #define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8))
/* This macro builds a descriptor header for a string descriptor given the /* This macro builds a descriptor header for a string descriptor given the
@@ -390,9 +382,7 @@ extern volatile schar usbRxLen;
*/ */
#define USB_PROP_IS_DYNAMIC (1 << 14) #define USB_PROP_IS_DYNAMIC (1 << 14)
/* If this property is set for a descriptor, usbFunctionDescriptor() will be /* If this property is set for a descriptor, usbFunctionDescriptor() will be
* used to obtain the particular descriptor. Data directly returned via * used to obtain the particular descriptor.
* usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to
* return RAM data.
*/ */
#define USB_PROP_IS_RAM (1 << 15) #define USB_PROP_IS_RAM (1 << 15)
/* If this property is set for a descriptor, the data is read from RAM /* If this property is set for a descriptor, the data is read from RAM
@@ -556,10 +546,6 @@ int usbDescriptorStringSerialNumber[];
#define USB_CFG_EP3_NUMBER 3 #define USB_CFG_EP3_NUMBER 3
#endif #endif
#ifndef USB_CFG_HAVE_INTRIN_ENDPOINT3
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
#endif
#define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */ #define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */
/* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */ /* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */
@@ -572,15 +558,8 @@ int usbDescriptorStringSerialNumber[];
# endif # endif
#endif #endif
#ifndef USB_INTR_CFG_SET /* allow user to override our default */ #ifndef USB_INTR_CFG_SET /* allow user to override our default */
# if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK)
# define USB_INTR_CFG_SET (1 << ISC01) /* cfg for falling edge */
/* If any SOF logic is used, the interrupt must be wired to D- where
* we better trigger on falling edge
*/
# else
# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */ # define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */
#endif #endif
#endif
#ifndef USB_INTR_CFG_CLR /* allow user to override our default */ #ifndef USB_INTR_CFG_CLR /* allow user to override our default */
# define USB_INTR_CFG_CLR 0 /* no bits to clear */ # define USB_INTR_CFG_CLR 0 /* no bits to clear */
#endif #endif

View File

@@ -4,8 +4,8 @@
* Creation Date: 2007-06-13 * Creation Date: 2007-06-13
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm.S 722 2009-03-16 19:03:57Z cs $ * Revision: $Id$
*/ */
/* /*
@@ -15,8 +15,15 @@ general code (preprocessor acrobatics and CRC computation) and then includes
the file appropriate for the given clock rate. the file appropriate for the given clock rate.
*/ */
#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */ #include "iarcompat.h"
#include "usbportability.h" #ifndef __IAR_SYSTEMS_ASM__
/* configs for io.h */
# define __SFR_OFFSET 0
# define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */
# include <avr/io.h> /* for CPU I/O register definitions and vectors */
# define macro .macro /* GNU Assembler macro definition */
# define endm .endm /* End of GNU Assembler macro definition */
#endif /* __IAR_SYSTEMS_ASM__ */
#include "usbdrv.h" /* for common defs */ #include "usbdrv.h" /* for common defs */
/* register names */ /* register names */
@@ -26,14 +33,24 @@ the file appropriate for the given clock rate.
#define cnt r19 #define cnt r19
#define x3 r20 #define x3 r20
#define x4 r21 #define x4 r21
#define x5 r22 #define bitcnt r22
#define bitcnt x5
#define phase x4 #define phase x4
#define leap x4 #define leap x4
/* Some assembler dependent definitions and declarations: */ /* Some assembler dependent definitions and declarations: */
#ifdef __IAR_SYSTEMS_ASM__ #ifdef __IAR_SYSTEMS_ASM__
# define nop2 rjmp $+2 /* jump to next instruction */
# define XL r26
# define XH r27
# define YL r28
# define YH r29
# define ZL r30
# define ZH r31
# define lo8(x) LOW(x)
# define hi8(x) (((x)>>8) & 0xff) /* not HIGH to allow XLINK to make a proper range check */
extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
extern usbTxBuf, usbTxStatus1, usbTxStatus3 extern usbTxBuf, usbTxStatus1, usbTxStatus3
@@ -56,6 +73,8 @@ the file appropriate for the given clock rate.
#else /* __IAR_SYSTEMS_ASM__ */ #else /* __IAR_SYSTEMS_ASM__ */
# define nop2 rjmp .+0 /* jump to next instruction */
# ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */ # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
# define USB_INTR_VECTOR SIG_INTERRUPT0 # define USB_INTR_VECTOR SIG_INTERRUPT0
# endif # endif
@@ -280,17 +299,8 @@ usbMFTimeout:
# define USB_CFG_CLOCK_KHZ 12000 # define USB_CFG_CLOCK_KHZ 12000
#endif #endif
#if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */
# if USB_CFG_CLOCK_KHZ == 18000
# include "usbdrvasm18-crc.inc"
# else
# error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
# endif
#else /* USB_CFG_CHECK_CRC */
#if USB_CFG_CLOCK_KHZ == 12000 #if USB_CFG_CLOCK_KHZ == 12000
# include "usbdrvasm12.inc" # include "usbdrvasm12.inc"
# elif USB_CFG_CLOCK_KHZ == 12800
# include "usbdrvasm128.inc"
#elif USB_CFG_CLOCK_KHZ == 15000 #elif USB_CFG_CLOCK_KHZ == 15000
# include "usbdrvasm15.inc" # include "usbdrvasm15.inc"
#elif USB_CFG_CLOCK_KHZ == 16000 #elif USB_CFG_CLOCK_KHZ == 16000
@@ -300,6 +310,5 @@ usbMFTimeout:
#elif USB_CFG_CLOCK_KHZ == 20000 #elif USB_CFG_CLOCK_KHZ == 20000
# include "usbdrvasm20.inc" # include "usbdrvasm20.inc"
#else #else
# error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!" # error "USB_CFG_CLOCK_KHZ is not one of the supported rates!"
#endif #endif
#endif /* USB_CFG_CHECK_CRC */

View File

@@ -4,7 +4,7 @@
* Creation Date: 2006-03-01 * Creation Date: 2006-03-01
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id$ * This Revision: $Id$
*/ */

View File

@@ -4,8 +4,8 @@
* Creation Date: 2004-12-29 * Creation Date: 2004-12-29
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm12.inc 692 2008-11-07 15:07:40Z cs $ * This Revision: $Id: usbdrvasm12.inc 483 2008-02-05 15:05:32Z cs $
*/ */
/* Do not link this file! Link usbdrvasm.S instead, which includes the /* Do not link this file! Link usbdrvasm.S instead, which includes the
@@ -48,13 +48,10 @@ USB_INTR_VECTOR:
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops ;sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern. ;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ: waitForJ:
inc YL sbis USBIN, USBMINUS ;1 [40] wait for D- == 1
sbis USBIN, USBMINUS rjmp waitForJ ;2
brne waitForJ ; just make sure we have ANY timeout
waitForK: waitForK:
;The following code results in a sampling window of 1/4 bit which meets the spec. ;The following code results in a sampling window of 1/4 bit which meets the spec.
sbis USBIN, USBMINUS sbis USBIN, USBMINUS
@@ -72,9 +69,6 @@ waitForK:
inc YL inc YL
sts usbSofCount, YL sts usbSofCount, YL
#endif /* USB_COUNT_SOF */ #endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError rjmp sofError
foundK: foundK:
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
@@ -269,16 +263,25 @@ macro POP_RETI ; 5 cycles
; Transmitting data ; Transmitting data
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
txByteLoop: bitstuff0: ;1 (for branch taken)
txBitloop: eor x1, x4 ;1
stuffN1Delay: ; [03] ldi x2, 0 ;1
ror shift ;[-5] [11] [59] out USBOUT, x1 ;1 <-- out
brcc doExorN1 ;[-4] [60] rjmp didStuff0 ;2 branch back 2 cycles earlier
subi x4, 1 ;[-3] bitstuff1: ;1 (for branch taken)
brne commonN1 ;[-2] eor x1, x4 ;1
lsl shift ;[-1] compensate ror after rjmp stuffDelay rjmp didStuff1 ;2 we know that C is clear, jump back to do OUT and ror 0 into x2
nop ;[00] stuffing consists of just waiting 8 cycles bitstuff2: ;1 (for branch taken)
rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear eor x1, x4 ;1
rjmp didStuff2 ;2 jump back 4 cycles earlier and do out and ror 0 into x2
bitstuff3: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff3 ;2 jump back earlier and ror 0 into x2
bitstuff4: ;1 (for branch taken)
eor x1, x4 ;1
ldi x2, 0 ;1
out USBOUT, x1 ;1 <-- out
rjmp didStuff4 ;2 jump back 2 cycles earlier
sendNakAndReti: ;0 [-19] 19 cycles until SOP sendNakAndReti: ;0 [-19] 19 cycles until SOP
ldi x3, USBPID_NAK ;1 [-18] ldi x3, USBPID_NAK ;1 [-18]
@@ -303,91 +306,122 @@ usbSendX3: ;0 [-16]
;usbSend: ;usbSend:
;pointer to data in 'Y' ;pointer to data in 'Y'
;number of bytes in 'cnt' -- including sync byte ;number of bytes in 'cnt' -- including sync byte
;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt] ;uses: x1...x4, shift, cnt, Y
;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) ;Numbers in brackets are time since first bit of sync pattern is sent
usbSendAndReti: usbSendAndReti: ;0 [-13] timing: 13 cycles until SOP
in x2, USBDDR ;[-12] 12 cycles until SOP in x2, USBDDR ;1 [-12]
ori x2, USBMASK ;[-11] ori x2, USBMASK ;1 [-11]
sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) sbi USBOUT, USBMINUS;2 [-9] prepare idle state; D+ and D- must have been 0 (no pullups)
out USBDDR, x2 ;[-8] <--- acquire bus in x1, USBOUT ;1 [-8] port mirror for tx loop
in x1, USBOUT ;[-7] port mirror for tx loop out USBDDR, x2 ;1 [-7] <- acquire bus
ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror) ; need not init x2 (bitstuff history) because sync starts with 0
ldi x2, USBMASK ;[-5] push x4 ;2 [-5]
push x4 ;[-4] ldi x4, USBMASK ;1 [-4] exor mask
doExorN1: ldi shift, 0x80 ;1 [-3] sync byte is first byte sent
eor x1, x2 ;[-2] [06] [62] txLoop: ; [62]
ldi x4, 6 ;[-1] [07] [63] sbrs shift, 0 ;1 [-2] [62]
commonN1: eor x1, x4 ;1 [-1] [63]
stuffN2Delay: out USBOUT, x1 ;1 [0] <-- out bit 0
out USBOUT, x1 ;[00] [08] [64] <--- set bit ror shift ;1 [1]
ror shift ;[01] ror x2 ;1 [2]
brcc doExorN2 ;[02] didStuff0:
subi x4, 1 ;[03] cpi x2, 0xfc ;1 [3]
brne commonN2 ;[04] brsh bitstuff0 ;1 [4]
lsl shift ;[05] compensate ror after rjmp stuffDelay sbrs shift, 0 ;1 [5]
rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear eor x1, x4 ;1 [6]
doExorN2: ror shift ;1 [7]
eor x1, x2 ;[04] [12] didStuff1:
ldi x4, 6 ;[05] [13] out USBOUT, x1 ;1 [8] <-- out bit 1
commonN2: ror x2 ;1 [9]
nop ;[06] [14] cpi x2, 0xfc ;1 [10]
subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1 brsh bitstuff1 ;1 [11]
out USBOUT, x1 ;[08] [16] <--- set bit sbrs shift, 0 ;1 [12]
brcs txBitloop ;[09] [25] [41] eor x1, x4 ;1 [13]
ror shift ;1 [14]
stuff6Delay: didStuff2:
ror shift ;[42] [50] ror x2 ;1 [15]
brcc doExor6 ;[43] out USBOUT, x1 ;1 [16] <-- out bit 2
subi x4, 1 ;[44] cpi x2, 0xfc ;1 [17]
brne common6 ;[45] brsh bitstuff2 ;1 [18]
lsl shift ;[46] compensate ror after rjmp stuffDelay sbrs shift, 0 ;1 [19]
nop ;[47] stuffing consists of just waiting 8 cycles eor x1, x4 ;1 [20]
rjmp stuff6Delay ;[48] after ror, C bit is reliably clear ror shift ;1 [21]
doExor6: didStuff3:
eor x1, x2 ;[45] [53] ror x2 ;1 [22]
ldi x4, 6 ;[46] cpi x2, 0xfc ;1 [23]
common6: out USBOUT, x1 ;1 [24] <-- out bit 3
stuff7Delay: brsh bitstuff3 ;1 [25]
ror shift ;[47] [55] nop2 ;2 [27]
out USBOUT, x1 ;[48] <--- set bit ld x3, y+ ;2 [29]
brcc doExor7 ;[49] sbrs shift, 0 ;1 [30]
subi x4, 1 ;[50] eor x1, x4 ;1 [31]
brne common7 ;[51] out USBOUT, x1 ;1 [32] <-- out bit 4
lsl shift ;[52] compensate ror after rjmp stuffDelay ror shift ;1 [33]
rjmp stuff7Delay ;[53] after ror, C bit is reliably clear ror x2 ;1 [34]
doExor7: didStuff4:
eor x1, x2 ;[51] [59] cpi x2, 0xfc ;1 [35]
ldi x4, 6 ;[52] brsh bitstuff4 ;1 [36]
common7: sbrs shift, 0 ;1 [37]
ld shift, y+ ;[53] eor x1, x4 ;1 [38]
tst cnt ;[55] ror shift ;1 [39]
out USBOUT, x1 ;[56] <--- set bit didStuff5:
brne txByteLoop ;[57] out USBOUT, x1 ;1 [40] <-- out bit 5
ror x2 ;1 [41]
cpi x2, 0xfc ;1 [42]
brsh bitstuff5 ;1 [43]
sbrs shift, 0 ;1 [44]
eor x1, x4 ;1 [45]
ror shift ;1 [46]
didStuff6:
ror x2 ;1 [47]
out USBOUT, x1 ;1 [48] <-- out bit 6
cpi x2, 0xfc ;1 [49]
brsh bitstuff6 ;1 [50]
sbrs shift, 0 ;1 [51]
eor x1, x4 ;1 [52]
ror shift ;1 [53]
didStuff7:
ror x2 ;1 [54]
cpi x2, 0xfc ;1 [55]
out USBOUT, x1 ;1 [56] <-- out bit 7
brsh bitstuff7 ;1 [57]
mov shift, x3 ;1 [58]
dec cnt ;1 [59]
brne txLoop ;1/2 [60/61]
;make SE0: ;make SE0:
cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles] cbr x1, USBMASK ;1 [61] prepare SE0 [spec says EOP may be 15 to 18 cycles]
lds x2, usbNewDeviceAddr;[59] pop x4 ;2 [63]
lsl x2 ;[61] we compare with left shifted address ;brackets are cycles from start of SE0 now
subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3 out USBOUT, x1 ;1 [0] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
sbci YH, 0 ;[63]
out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
;set address only after data packet was sent, not after handshake ;set address only after data packet was sent, not after handshake
breq skipAddrAssign ;[01] lds x2, usbNewDeviceAddr;2 [2]
lsl x2; ;1 [3] we compare with left shifted address
subi YL, 20 + 2 ;1 [4] Only assign address on data packets, not ACK/NAK in x3
sbci YH, 0 ;1 [5]
breq skipAddrAssign ;2 [7]
sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
skipAddrAssign: skipAddrAssign:
;end of usbDeviceAddress transfer ;end of usbDeviceAddress transfer
ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag ldi x2, 1<<USB_INTR_PENDING_BIT;1 [8] int0 occurred during TX -- clear pending flag
USB_STORE_PENDING(x2) ;[04] USB_STORE_PENDING(x2) ;1 [9]
ori x1, USBIDLE ;[05] ori x1, USBIDLE ;1 [10]
in x2, USBDDR ;[06] in x2, USBDDR ;1 [11]
cbr x2, USBMASK ;[07] set both pins to input cbr x2, USBMASK ;1 [12] set both pins to input
mov x3, x1 ;[08] mov x3, x1 ;1 [13]
cbr x3, USBMASK ;[09] configure no pullup on both pins cbr x3, USBMASK ;1 [14] configure no pullup on both pins
pop x4 ;[10] out USBOUT, x1 ;1 [15] <-- out J (idle) -- end of SE0 (EOP signal)
nop2 ;[12] out USBDDR, x2 ;1 [16] <-- release bus now
nop2 ;[14] out USBOUT, x3 ;1 [17] <-- ensure no pull-up resistors are active
out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
out USBDDR, x2 ;[17] <-- release bus now
out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
rjmp doReturn rjmp doReturn
bitstuff5: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff5 ;2 same trick as in bitstuff1...
bitstuff6: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff6 ;2 same trick as above...
bitstuff7: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff7 ;2 same trick as above...

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm128.inc /* Name: usbdrvasm128.inc
* Project: AVR USB driver * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann * Author: Christian Starkjohann
* Creation Date: 2008-10-11 * Creation Date: 2008-10-11
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm128.inc 692 2008-11-07 15:07:40Z cs $ * This Revision: $Id: usbdrvasm128.inc 740 2009-04-13 18:23:31Z cs $
*/ */
/* Do not link this file! Link usbdrvasm.S instead, which includes the /* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -4,8 +4,8 @@
* Creation Date: 2007-08-06 * Creation Date: 2007-08-06
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm15.inc 692 2008-11-07 15:07:40Z cs $ * Revision: $Id: usbdrvasm15.inc 607 2008-05-13 15:57:28Z cs $
*/ */
/* Do not link this file! Link usbdrvasm.S instead, which includes the /* Do not link this file! Link usbdrvasm.S instead, which includes the
@@ -43,13 +43,11 @@ USB_INTR_VECTOR:
; ;
; sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] ; sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
; sync up with J to K edge during sync pattern -- use fastest possible loops ; sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern. ; first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to ;-------------------------------------------------------------------------------
;waitForJ, ensure that this prerequisite is met. waitForJ: ;-
waitForJ: sbis USBIN, USBMINUS ;1 <-- sample: wait for D- == 1
inc YL rjmp waitForJ ;2
sbis USBIN, USBMINUS
brne waitForJ ; just make sure we have ANY timeout
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; The following code results in a sampling window of < 1/4 bit ; The following code results in a sampling window of < 1/4 bit
; which meets the spec. ; which meets the spec.
@@ -72,9 +70,6 @@ waitForK: ;-
inc YL inc YL
sts usbSofCount, YL sts usbSofCount, YL
#endif /* USB_COUNT_SOF */ #endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError rjmp sofError
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for ; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for

View File

@@ -4,8 +4,8 @@
* Creation Date: 2007-06-15 * Creation Date: 2007-06-15
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm16.inc 692 2008-11-07 15:07:40Z cs $ * Revision: $Id: usbdrvasm16.inc 607 2008-05-13 15:57:28Z cs $
*/ */
/* Do not link this file! Link usbdrvasm.S instead, which includes the /* Do not link this file! Link usbdrvasm.S instead, which includes the
@@ -41,13 +41,10 @@ USB_INTR_VECTOR:
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops ;sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern. ;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ: waitForJ:
inc YL sbis USBIN, USBMINUS ;[-18] wait for D- == 1
sbis USBIN, USBMINUS rjmp waitForJ
brne waitForJ ; just make sure we have ANY timeout
waitForK: waitForK:
;The following code results in a sampling window of < 1/4 bit which meets the spec. ;The following code results in a sampling window of < 1/4 bit which meets the spec.
sbis USBIN, USBMINUS ;[-15] sbis USBIN, USBMINUS ;[-15]
@@ -67,9 +64,6 @@ waitForK:
inc YL inc YL
sts usbSofCount, YL sts usbSofCount, YL
#endif /* USB_COUNT_SOF */ #endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError rjmp sofError
foundK: ;[-12] foundK: ;[-12]
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]

View File

@@ -4,8 +4,8 @@
* Creation Date: 2007-04-22 * Creation Date: 2007-04-22
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm165.inc 692 2008-11-07 15:07:40Z cs $ * Revision: $Id: usbdrvasm165.inc 607 2008-05-13 15:57:28Z cs $
*/ */
/* Do not link this file! Link usbdrvasm.S instead, which includes the /* Do not link this file! Link usbdrvasm.S instead, which includes the
@@ -46,13 +46,10 @@ USB_INTR_VECTOR:
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops ;sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern. ;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ: waitForJ:
inc YL sbis USBIN, USBMINUS ;[-18] wait for D- == 1
sbis USBIN, USBMINUS rjmp waitForJ
brne waitForJ ; just make sure we have ANY timeout
waitForK: waitForK:
;The following code results in a sampling window of < 1/4 bit which meets the spec. ;The following code results in a sampling window of < 1/4 bit which meets the spec.
sbis USBIN, USBMINUS ;[-15] sbis USBIN, USBMINUS ;[-15]
@@ -72,9 +69,6 @@ waitForK:
inc YL inc YL
sts usbSofCount, YL sts usbSofCount, YL
#endif /* USB_COUNT_SOF */ #endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError rjmp sofError
foundK: ;[-12] foundK: ;[-12]
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm18.inc /* Name: usbdrvasm18.inc
* Project: AVR USB driver * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Lukas Schrittwieser (based on 20 MHz usbdrvasm20.inc by Jeroen Benschop) * Author: Lukas Schrittwieser (based on 20 MHz usbdrvasm20.inc by Jeroen Benschop)
* Creation Date: 2009-01-20 * Creation Date: 2009-01-20
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm18-crc.inc 734 2009-03-23 11:10:07Z cs $ * Revision: $Id: usbdrvasm18-crc.inc 740 2009-04-13 18:23:31Z cs $
*/ */
/* Do not link this file! Link usbdrvasm.S instead, which includes the /* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -5,8 +5,8 @@
* Creation Date: 2008-03-05 * Creation Date: 2008-03-05
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm20.inc 692 2008-11-07 15:07:40Z cs $ * Revision: $Id: usbdrvasm20.inc 607 2008-05-13 15:57:28Z cs $
*/ */
/* Do not link this file! Link usbdrvasm.S instead, which includes the /* Do not link this file! Link usbdrvasm.S instead, which includes the
@@ -57,13 +57,10 @@ USB_INTR_VECTOR:
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops ;sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern. ;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ: waitForJ:
inc YL sbis USBIN, USBMINUS ;[-21] wait for D- == 1
sbis USBIN, USBMINUS rjmp waitForJ
brne waitForJ ; just make sure we have ANY timeout
waitForK: waitForK:
;The following code results in a sampling window of < 1/4 bit which meets the spec. ;The following code results in a sampling window of < 1/4 bit which meets the spec.
sbis USBIN, USBMINUS ;[-19] sbis USBIN, USBMINUS ;[-19]
@@ -89,9 +86,6 @@ waitForK:
inc YL inc YL
sts usbSofCount, YL sts usbSofCount, YL
#endif /* USB_COUNT_SOF */ #endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError rjmp sofError
foundK: ;[-16] foundK: ;[-16]
;{3, 5} after falling D- edge, average delay: 4 cycles ;{3, 5} after falling D- edge, average delay: 4 cycles

View File

@@ -1,11 +1,11 @@
/* Name: usbportability.h /* Name: usbportability.h
* Project: AVR USB driver * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann * Author: Christian Starkjohann
* Creation Date: 2008-06-17 * Creation Date: 2008-06-17
* Tabsize: 4 * Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbportability.h 692 2008-11-07 15:07:40Z cs $ * This Revision: $Id: usbportability.h 740 2009-04-13 18:23:31Z cs $
*/ */
/* /*

View File

@@ -1,45 +1,58 @@
# =====================================================================================
#
# ________ .__ __ ________ ____ ________
# \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
# / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
# / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
# \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
# \__> \/ \/ \/ \/ \/
# www.optixx.org
#
#
# Version: 1.0
# Created: 07/21/2009 03:32:16 PM
# Author: david@optixx.org
# Based on: custom-class, a basic USB example
# Author: Christian Starkjohann
# =====================================================================================
DEBUG = 1
TTY = /dev/tty.PL2303-00002126 TTY = /dev/tty.PL2303-00002126
DEVICE = atmega644 DEVICE = atmega644
F_CPU = 20000000 # in Hz F_CPU = 20000000 # in Hz
FUSE_L = 0xf7 TARGET = main
FUSE_H = 0xd9
AVRDUDE = avrdude -c usbasp -p $(DEVICE) AVRDUDE = avrdude -c usbasp -p $(DEVICE)
SIZE = avr-size
ifeq ($(DEBUG),1)
LDFLAGS = -Wl,-u,vfprintf -lprintf_flt
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0 CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0
#-std=gnu99 OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o \
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o dump.o main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o \
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE) dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o \
command.o mmc.o fat.o file.o dir.o testing.o
else
LDFLAGS = -Wl,-u
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0 -DNO_DEBUG -DNO_INFO
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o \
uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o rle.c loader.o \
info.o shared_memory.o command.o
endif
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)
############################################################################## ##############################################################################
# Fuse values for particular devices # Fuse values for particular devices
############################################################################## ##############################################################################
# If your device is not listed here, go to # http://www.engbedded.com/fusecalc/
# http://palmavr.sourceforge.net/cgi-bin/fc.cgi FUSE_L = 0xf7
# and choose options for external crystal clock and no clock divider FUSE_H = 0xda
#
################################## ATMega644 ##################################
# ATMega644 FUSE_L (Fuse low byte):
# 0xf7 = 1 1 1 1 0 1 1 1
# ^ ^ \ / \--+--/
# | | | +------- CKSEL 3..0 (external >8M crystal)
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
# | +------------------ BODEN (BrownOut Detector enabled)
# +-------------------- BODLEVEL (2.7V)
# ATMega644 FUSE_H (Fuse high byte): all: hex
# 0xd9 = 1 1 0 1 1 0 0 1
# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0
# | | | | | +-------- BOOTSZ1
# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase)
# | | | +-------------- CKOPT (full output swing)
# | | +---------------- SPIEN (allow serial programming)
# | +------------------ WDTON (WDT not always on)
# symbolic targets:
help: help:
@echo "This Makefile has no default rule. Use one of the following:" @echo "This Makefile has no default rule. Use one of the following:"
@echo "make hex ....... to build main.hex" @echo "make hex ....... to build main.hex"
@@ -48,9 +61,12 @@ help:
@echo "make flash ..... to flash the firmware (use this on metaboard)" @echo "make flash ..... to flash the firmware (use this on metaboard)"
@echo "make clean ..... to delete objects and hex file" @echo "make clean ..... to delete objects and hex file"
all: hex
hex: main.hex hex: main.hex
@echo "==============================="
@echo "$(TARGET) compiled for: $(DEVICE)"
@echo -n "size is: "
@$(SIZE) -A $(TARGET).hex | grep "\.sec1" | tr -s " " | cut -d" " -f2
@echo "==============================="
program: flash fuse program: flash fuse
@@ -60,48 +76,36 @@ fuse:
{ echo "*** Edit Makefile and choose values for FUSE_L and FUSE_H!"; exit 1; } { echo "*** Edit Makefile and choose values for FUSE_L and FUSE_H!"; exit 1; }
$(AVRDUDE) -U hfuse:w:$(FUSE_H):m -U lfuse:w:$(FUSE_L):m $(AVRDUDE) -U hfuse:w:$(FUSE_H):m -U lfuse:w:$(FUSE_L):m
# rule for uploading firmware:
flash: main.hex flash: main.hex
$(AVRDUDE) -U flash:w:main.hex:i $(AVRDUDE) -U flash:w:main.hex:i
# rule for deleting dependent files (those which can be built by Make):
clean:
rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s
# Generic rule for compiling C files:
.c.o: .c.o:
$(COMPILE) -c $< -o $@ $(COMPILE) -c $< -o $@
# Generic rule for assembling Assembler source files:
.S.o: .S.o:
$(COMPILE) -x assembler-with-cpp -c $< -o $@ $(COMPILE) -x assembler-with-cpp -c $< -o $@
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.
# Generic rule for compiling C to assembler, used for debugging only.
.c.s: .c.s:
$(COMPILE) -S $< -o $@ $(COMPILE) -S $< -o $@
# file targets:
# Since we don't want to ship the driver multipe times, we copy it into this project:
usbdrv: usbdrv:
cp -r ../../../usbdrv . cp -r ../../../usbdrv .
main.elf: usbdrv $(OBJECTS) # usbdrv dependency only needed because we copy it main.elf: usbdrv $(OBJECTS) # usbdrv dependency only needed because we copy it
$(COMPILE) -o main.elf $(OBJECTS) $(COMPILE) -o main.elf $(OBJECTS) $(LDFLAGS)
main.hex: main.elf main.hex: main.elf
rm -f main.hex main.eep.hex rm -f main.hex main.eep.hex
avr-objcopy -j .text -j .data -O ihex main.elf main.hex avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avr-size main.hex avr-size main.hex
# debugging targets:
disasm: main.elf disasm: main.elf
avr-objdump -d main.elf avr-objdump -d main.elf
cpp: cpp:
$(COMPILE) -E main.c $(COMPILE) -E main.c
clean:
rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s

61
avr/usbload/command.c Normal file
View File

@@ -0,0 +1,61 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "config.h"
#include "requests.h"
#include "sram.h"
#include "info.h"
extern uint32_t req_bank_size;
void send_reset()
{
info("Reset Snes\n");
snes_reset_on();
snes_reset_lo();
_delay_ms(2);
snes_reset_hi();
snes_reset_off();
}
void send_irq()
{
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
}
void set_rom_mode()
{
if (req_bank_size == 0x8000) {
snes_lorom();
info("Set Snes lowrom \n");
} else {
snes_hirom();
info("Set Snes hirom \n");
}
}

29
avr/usbload/command.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __COMMAND_H__
#define __COMMAND_H__
void send_reset();
void send_irq();
void set_rom_mode();
#endif

View File

@@ -1,15 +1,25 @@
/* /*
* Name: opendevice.c Project: V-USB host-side library Author: Christian * =====================================================================================
* Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c) 2008 by *
* OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see License.txt), * ________ .__ __ ________ ____ ________
* GNU GPL v3 or proprietary (CommercialLicense.txt) This Revision: $Id: * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* opendevice.c 740 2009-04-13 18:23:31Z cs $ * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
* Based on: custom-class, a basic USB example
* Author: Christian Starkjohann
* =====================================================================================
*/ */
/*
* General Description: The functions in this module can be used to find and
* open a device based on libusb or libusb-win32.
*/
#include <stdio.h> #include <stdio.h>

View File

@@ -1,25 +1,25 @@
/* Name: opendevice.h
* Project: V-USB host-side library
* Author: Christian Starkjohann
* Creation Date: 2008-04-10
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: opendevice.h 740 2009-04-13 18:23:31Z cs $
*/
/* /*
General Description: * =====================================================================================
This module offers additional functionality for host side drivers based on *
libusb or libusb-win32. It includes a function to find and open a device * ________ .__ __ ________ ____ ________
based on numeric IDs and textual description. It also includes a function to * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
obtain textual descriptions from a device. * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
To use this functionality, simply copy opendevice.c and opendevice.h into your * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
project and add them to your Makefile. You may modify and redistribute these * \__> \/ \/ \/ \/ \/
files according to the GNU General Public License (GPL) version 2 or 3. *
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
* Based on: custom-class, a basic USB example
* Author: Christian Starkjohann
* =====================================================================================
*/ */
#ifndef __OPENDEVICE_H_INCLUDED__ #ifndef __OPENDEVICE_H_INCLUDED__
#define __OPENDEVICE_H_INCLUDED__ #define __OPENDEVICE_H_INCLUDED__

Binary file not shown.

View File

@@ -1,31 +1,35 @@
/* /*
* Name: set-led.c Project: custom-class, a basic USB example Author: * =====================================================================================
* Christian Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c) *
* 2008 by OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see * ________ .__ __ ________ ____ ________
* License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) This * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* Revision: $Id: set-led.c 692 2008-11-07 15:07:40Z cs $ * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
* Based on: custom-class, a basic USB example
* Author: Christian Starkjohann
* =====================================================================================
*/ */
/*
* General Description: This is the host-side driver for the custom-class
* example device. It searches the USB for the LEDControl device and sends the
* requests understood by this device. This program must be linked with libusb
* on Unix and libusb-win32 on Windows. See http://libusb.sourceforge.net/ or
* http://libusb-win32.sourceforge.net/ respectively.
*/
#define READ_BUFFER_SIZE 1024
#define SEND_BUFFER_SIZE 0x200
#define BUFFER_CRC (1024 * 32)
#define BANK_SIZE (1<<15)
#define BANK_SIZE_SHIFT 15 #define BANK_SIZE_SHIFT 15
#define BANK_SIZE (1<<BANK_SIZE_SHIFT)
#define READ_BUFFER_SIZE (1<<BANK_SIZE_SHIFT)
#define SEND_BUFFER_SIZE 128
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <usb.h> /* this is libusb */ #include <usb.h> /* this is libusb */
#include "opendevice.h" /* common code moved to separate module */ #include "opendevice.h" /* common code moved to separate module */
#include "../requests.h" /* custom request numbers */ #include "../requests.h" /* custom request numbers */
@@ -119,20 +123,22 @@ int main(int argc, char **argv)
USB_CFG_DEVICE_ID}; USB_CFG_DEVICE_ID};
char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = { char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = {
USB_CFG_DEVICE_NAME, 0}; USB_CFG_DEVICE_NAME, 0};
int cnt, int cnt, vid, pid;
vid,
pid;
int cnt_crc = 0;
uint8_t *read_buffer; uint8_t *read_buffer;
uint8_t *crc_buffer; uint8_t *crc_buffer;
uint8_t *ptr;
uint32_t addr = 0; uint32_t addr = 0;
uint16_t addr_lo = 0; uint16_t addr_lo = 0;
uint16_t addr_hi = 0; uint16_t addr_hi = 0;
uint16_t step = 0; uint32_t step = 0;
uint16_t crc = 0; uint16_t crc = 0;
uint8_t bank = 0; uint8_t bank = 0;
FILE *fp; uint8_t bank_cnt = 0;
uint32_t file_size = 0;
uint32_t file_offset = 0;
FILE *fp;
usb_init(); usb_init();
if (argc < 2) { /* we need at least one argument */ if (argc < 2) { /* we need at least one argument */
usage(argv[0]); usage(argv[0]);
@@ -166,59 +172,107 @@ int main(int argc, char **argv)
fprintf(stderr, "Cannot open file %s ", argv[2]); fprintf(stderr, "Cannot open file %s ", argv[2]);
exit(1); exit(1);
} }
fseek (fp, 0, SEEK_END);
file_size = ftell (fp);
file_offset = 512;
if (strstr(argv[2],".smc") || strstr(argv[2],".swc")){
printf("Skip 512 Byte header\n");
file_size -= 512;
fseek (fp, 512, SEEK_SET);
} else {
fseek (fp, 0, SEEK_SET);
}
bank_cnt = file_size / BANK_SIZE;
printf("Transfer '%s' %i Bytes, %i Banks\n",argv[2],file_size,bank_cnt);
read_buffer = (unsigned char *) malloc(READ_BUFFER_SIZE); read_buffer = (unsigned char *) malloc(READ_BUFFER_SIZE);
crc_buffer = (unsigned char *) malloc(BUFFER_CRC); crc_buffer = (unsigned char *) malloc(0x1000);
memset(crc_buffer, 0, BUFFER_CRC); memset(crc_buffer, 0, 0x1000);
addr = 0x000000; addr = 0x000000;
usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
USB_UPLOAD_INIT, BANK_SIZE_SHIFT , 0, NULL, 0, 5000);
while ((cnt = fread(read_buffer, READ_BUFFER_SIZE, 1, fp)) > 0) {
for (step = 0; step <= READ_BUFFER_SIZE; step += SEND_BUFFER_SIZE) {
addr_lo = addr & 0xffff;
addr_hi = (addr >> 16) & 0xff;
cnt = usb_control_msg(handle, cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_UPLOAD_ADDR, addr_hi, USB_ENDPOINT_OUT, USB_MODE_AVR, 0, 0, NULL,
addr_lo, (char *) read_buffer + step, 0, 5000);
SEND_BUFFER_SIZE, 5000);
if (addr%0x1000==0){
printf ("bank=0x%02x addr=0x%08x\n", bank, addr);
} cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
USB_BULK_UPLOAD_INIT, BANK_SIZE_SHIFT , bank_cnt, NULL, 0, 5000);
if (cnt < 0) { if (cnt < 0) {
fprintf(stderr, "USB error: %s\n", usb_strerror()); fprintf(stderr, "USB error: %s\n", usb_strerror());
usb_close(handle);
exit(-1); exit(-1);
} }
ptr = crc_buffer;
while ((cnt = fread(read_buffer, READ_BUFFER_SIZE, 1, fp)) > 0) {
ptr = crc_buffer;
for (step = 0; step < READ_BUFFER_SIZE; step += SEND_BUFFER_SIZE) {
addr_lo = addr & 0xffff;
addr_hi = (addr >> 16) & 0x00ff;
if (addr == 0x000000){
cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_BULK_UPLOAD_ADDR, addr_hi,
addr_lo, (char *) read_buffer + step,
SEND_BUFFER_SIZE, 5000);
} else {
cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_BULK_UPLOAD_NEXT, addr_hi,
addr_lo, (char *) read_buffer + step,
SEND_BUFFER_SIZE, 5000);
}
if (cnt < 0) {
fprintf(stderr, "USB error: %s\n", usb_strerror());
usb_close(handle);
exit(-1);
}
memcpy(ptr, read_buffer + step, SEND_BUFFER_SIZE);
addr += SEND_BUFFER_SIZE; addr += SEND_BUFFER_SIZE;
} ptr += SEND_BUFFER_SIZE;
dump_packet(0x00000,READ_BUFFER_SIZE, read_buffer); if ( addr % BANK_SIZE == 0){
memcpy(crc_buffer + cnt_crc, read_buffer, READ_BUFFER_SIZE); crc = do_crc(crc_buffer, 0x1000);
cnt_crc += READ_BUFFER_SIZE; printf ("bank=0x%02x addr=0x%08x addr=0x%08x crc=0x%04x\n", bank, addr - 0x1000, addr, crc);
if (cnt_crc >= READ_BUFFER_SIZE) { ptr = crc_buffer;
crc = do_crc(crc_buffer, BANK_SIZE); if ( addr % BANK_SIZE == 0) {
printf ("bank=0x%02x crc=0x%04x\n", bank, crc);
memset(crc_buffer, 0, BUFFER_CRC);
bank++; bank++;
cnt_crc = 0;
}
break;
}
/*
}
}
}
}
bank = 0;
cnt = usb_control_msg(handle, cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_CRC, addr_hi, addr_lo, NULL, USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
0, 5000); 0, 5000);
*/
fseek(fp, file_offset, SEEK_SET);
while ((cnt = fread(read_buffer, READ_BUFFER_SIZE, 1, fp)) > 0) {
printf ("bank=0x%02x crc=0x%04x\n", bank++,
do_crc(read_buffer, READ_BUFFER_SIZE));
}
fclose(fp);
cnt = usb_control_msg(handle, cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_SNES_BOOT, 0, 0, NULL, USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
0, 5000); 0, 5000);

View File

@@ -1,20 +1,43 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __CONFIH_H__ #ifndef __CONFIH_H__
#define __CONFIH_H__ #define __CONFIH_H__
#define DEBUG 1 #define DEBUG 1
#define DEBUG_USB 2 #define DEBUG_USB 2
#define DEBUG_USB_TRANS 4 #define DEBUG_USB_TRANS 4
#define DEBUG_SRAM 8 #define DEBUG_SRAM 8
#define DEBUG_SRAM_RAW 16 #define DEBUG_SRAM_RAW 16
#define DEBUG_SREG 32 #define DEBUG_FAT 32
#define DEBUG_CRC 64
#define DEBUG_SHM 128
#define REQ_STATUS_IDLE 0x01 #define REQ_STATUS_IDLE 0x01
#define REQ_STATUS_UPLOAD 0x02 #define REQ_STATUS_UPLOAD 0x02
#define REQ_STATUS_BULK_UPLOAD 0x03 #define REQ_STATUS_BULK_UPLOAD 0x03
#define REQ_STATUS_BULK_NEXT 0x04 #define REQ_STATUS_BULK_NEXT 0x04
#define REQ_STATUS_CRC 0x05 #define REQ_STATUS_CRC 0x05
#define REQ_STATUS_BOOT 0x06 #define REQ_STATUS_SNES 0x06
#define REQ_STATUS_AVR 0x07
#define USB_MAX_TRANS 0xff #define USB_MAX_TRANS 0xff
#define USB_CRC_CHECK 0x01 #define USB_CRC_CHECK 0x01

View File

@@ -1,3 +1,24 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@@ -5,6 +26,8 @@
#include "uart.h" #include "uart.h"
#include "config.h" #include "config.h"
#include "sram.h" #include "sram.h"
#include "debug.h"
#include "info.h"
extern FILE uart_stdout; extern FILE uart_stdout;
@@ -27,6 +50,7 @@ uint16_t do_crc(uint8_t * data, uint16_t size)
uint16_t i; uint16_t i;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
crc = crc_xmodem_update(crc, data[i]); crc = crc_xmodem_update(crc, data[i]);
} }
return crc; return crc;
} }
@@ -41,15 +65,16 @@ uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size)
} }
void crc_check_bulk_memory(uint32_t bottom_addr,uint32_t top_addr) uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t top_addr, uint32_t bank_size)
{ {
uint16_t crc = 0; uint16_t crc = 0;
uint32_t addr = 0; uint32_t addr = 0;
uint8_t req_bank = 0; uint8_t req_bank = 0;
sram_bulk_read_start(bottom_addr); sram_bulk_read_start(bottom_addr);
for (addr = bottom_addr; addr < top_addr; addr++) { for (addr = bottom_addr; addr < top_addr; addr++) {
if (addr && addr % 0x8000 == 0) { if (addr && addr % bank_size == 0) {
printf("crc_check_bulk: bank=0x%02x addr=0x%08lx crc=0x%04x\n", debug(DEBUG_CRC,"crc_check_bulk_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
req_bank,addr,crc); req_bank,addr,crc);
req_bank++; req_bank++;
crc = 0; crc = 0;
@@ -57,40 +82,22 @@ void crc_check_bulk_memory(uint32_t bottom_addr,uint32_t top_addr)
crc = crc_xmodem_update(crc, sram_bulk_read()); crc = crc_xmodem_update(crc, sram_bulk_read());
sram_bulk_read_next(); sram_bulk_read_next();
} }
sram_bulk_read_end();
if (addr % 0x8000 == 0) if (addr % 0x8000 == 0)
printf("crc_check_bulk: bank=0x%02x addr=0x%08lx crc=0x%04x\n", debug(DEBUG_CRC,"crc_check_bulk_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
req_bank,addr,crc); req_bank,addr,crc);
sram_bulk_read_end();
return crc;
} }
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint8_t *buffer)
{
uint16_t crc = 0;
uint32_t addr;
uint8_t req_bank = 0;
for (addr = bottom_addr; addr < top_addr; addr += TRANSFER_BUFFER_SIZE) {
if (addr && addr % 0x8000 == 0) {
printf("crc_check_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
req_bank,addr,crc);
req_bank++;
crc = 0;
}
sram_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE);
}
}
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer) uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer)
{ {
uint16_t crc = 0; uint16_t crc = 0;
uint32_t addr; uint32_t addr;
for (addr = start_addr; addr < start_addr + size; addr += TRANSFER_BUFFER_SIZE) { for (addr = start_addr; addr < start_addr + size; addr += TRANSFER_BUFFER_SIZE) {
sram_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE); sram_bulk_read_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE); crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE);
} }
return crc; return crc;

View File

@@ -1,3 +1,23 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __CRC_H__ #ifndef __CRC_H__
#define __CRC_H__ #define __CRC_H__
@@ -9,8 +29,7 @@
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data); uint16_t crc_xmodem_update(uint16_t crc, uint8_t data);
uint16_t do_crc(uint8_t * data,uint16_t size); uint16_t do_crc(uint8_t * data,uint16_t size);
uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size); uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size);
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint8_t *buffer);
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer); uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer);
void crc_check_bulk_memory(uint32_t bottom_addr,uint32_t top_addr); uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t bank_size,uint32_t top_addr);
#endif #endif

View File

@@ -1,3 +1,23 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@@ -5,25 +25,25 @@
#include "uart.h" #include "uart.h"
extern FILE uart_stdout; extern FILE uart_stdout;
extern int debug_level; /* the higher, the more messages... */ extern int debug_level; /* the higher, the more messages... */
#if defined(NO_DEBUG) && defined(__GNUC__) #if defined(NO_DEBUG) && defined(__GNUC__)
/* Nothing. debug has been "defined away" in debug.h already. */
#else #else
void debug(int level, char* format, ...) { void debug(int level, char* format, ...) {
#ifdef NO_DEBUG #ifdef NO_DEBUG
/* Empty body, so a good compiler will optimise calls
to pmesg away */
#else #else
va_list args; va_list args;
if (!(debug_level & level)) if (!(debug_level & level))
return; return;
va_start(args, format); va_start(args, format);
printf(format, args); vprintf(format, args);
va_end(args); va_end(args);
#endif /* NDEBUG */ #endif
#endif /* NDEBUG && __GNUC__ */
} }
#endif

View File

@@ -1,3 +1,25 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __DEBUG_H__ #ifndef __DEBUG_H__
#define __DEBUG_H__ #define __DEBUG_H__

96
avr/usbload/dir.c Normal file
View File

@@ -0,0 +1,96 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include "dir.h"
#include "file.h"
#include "fat.h"
#include "debug.h"
#include "sram.h"
#include "config.h"
#include <string.h>
uint16_t position = 0;
extern struct File file;
void dir_entry_start(){
position = 0;
}
void dir_entry_dump(uint32_t addr, dir_ent_t* ent){
debug(DEBUG_FAT,"dir_entry_dump: addr=0x%06lx id=%li name=%s size=%li attr=%i\n", addr, ent->id, ent->file_name,
ent->file_size, ent->file_attr);
}
void dir_entry_add(uint32_t id, uint8_t* file_name,uint32_t file_size,uint8_t file_attr){
uint32_t addr;
dir_ent_t ent;
strncpy(ent.file_name,file_name,13);
ent.id = id;
ent.file_size = file_size;
ent.file_attr = file_attr;
addr = DIR_ENTRY_LOC + (position << DIR_ENTRY_SIZE_SHIFT );
sram_bulk_copy(addr, (uint8_t *) &ent, DIR_ENTRY_SIZE );
dir_entry_dump(addr, &ent);
position++;
}
void dir_entry_header(uint16_t idx, uint8_t * header){
uint32_t addr;
addr = DIR_ENTRY_LOC + ( idx << DIR_ENTRY_SIZE_SHIFT ) + DIR_ENTRY_HEADER_OFF;
sram_bulk_copy(addr, (uint8_t *) header, DIR_ENTRY_HEADER_SIZE);
}
uint32_t dir_entry_get(uint32_t idx, dir_ent_t* ent){
uint32_t addr;
addr = DIR_ENTRY_LOC + ( idx << DIR_ENTRY_SIZE_SHIFT );
sram_bulk_read_buffer( addr, (uint8_t *) ent, DIR_ENTRY_SIZE);
return addr;
}
void dir_entry_loop(){
uint8_t i;
uint8_t j;
uint32_t addr;
dir_ent_t ent;
for (i=0; i< position; i++){
addr = dir_entry_get(i,&ent);
dir_entry_dump(addr,&ent);
ffopen( ent.file_name );
if (file.length != 524288){
ffclose();
continue;
}
//ffseek(0x7fc0);
for (j=0; j< 64; j++)
printf ("0x%02x " ,ffread());
printf("\n");
ffclose();
}
}

64
avr/usbload/dir.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __DIR_H__
#define __DIR_H__
#include <stdlib.h>
#include <stdint.h>
#define DIR_ENTRY_LOC 0x010000
#define DIR_ENTRY_SIZE 64
#define DIR_ENTRY_SIZE_SHIFT 6
#define DIR_ENTRY_HEADER_SIZE 44
#define DIR_ENTRY_HEADER_OFF 20
typedef struct {
uint32_t id; // 4
uint8_t file_name[13]; // 8.3 = 12 + 1 = 13
uint32_t file_size; // 4
uint8_t file_attr; // 1
uint8_t snes_header[41]; // 41
} dir_ent_t; // 64
void dir_entry_start();
void dir_entry_add(uint32_t id, uint8_t* file_name,uint32_t file_size,uint8_t file_attr);
void dir_entry_header(uint16_t position, uint8_t * header);
/*
lo:
0x7fc0
0x7fc0 + 0x200
hi:
0xffc0
0xffc0 + 0x200
emulated reset vector MSB must be set
sei
clc
xce
*/
#endif

View File

@@ -1,7 +1,29 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include "debug.h" #include "debug.h"
#include "info.h"
#include "uart.h" #include "uart.h"
#include "sram.h" #include "sram.h"
@@ -25,36 +47,36 @@ void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet)
continue; continue;
} }
if (clear) { if (clear) {
printf("*\n"); info("*\n");
clear = 0; clear = 0;
} }
printf("%08lx:", addr + i); info("%08lx:", addr + i);
for (j = 0; j < 16; j++) { for (j = 0; j < 16; j++) {
printf(" %02x", packet[i + j]); info(" %02x", packet[i + j]);
} }
printf(" |"); info(" |");
for (j = 0; j < 16; j++) { for (j = 0; j < 16; j++) {
if (packet[i + j] >= 33 && packet[i + j] <= 126) if (packet[i + j] >= 33 && packet[i + j] <= 126)
printf("%c", packet[i + j]); info("%c", packet[i + j]);
else else
printf("."); info(".");
} }
printf("|\n"); info("|\n");
} }
} }
void dump_memoryt(uint32_t bottom_addr, uint32_t top_addr) void dump_memory(uint32_t bottom_addr, uint32_t top_addr)
{ {
uint32_t addr; uint32_t addr;
uint8_t byte; uint8_t byte;
sram_bulk_read_start(bottom_addr); sram_bulk_read_start(bottom_addr);
printf("%08lx:", bottom_addr);
for ( addr = bottom_addr; addr < top_addr; addr++) { for ( addr = bottom_addr; addr < top_addr; addr++) {
if (addr%0x16 == 0) if (addr%0x10 == 0)
printf("\n%08lx:", bottom_addr); info("\n%08lx:", addr);
byte = sram_bulk_read(); byte = sram_bulk_read();
sram_bulk_read_next(); sram_bulk_read_next();
printf(" %02x", byte); info(" %02x", byte);
} }
info("\n");
sram_bulk_read_end(); sram_bulk_read_end();
} }

View File

@@ -1,3 +1,24 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __DUMP_H__ #ifndef __DUMP_H__
#define __DUMP_H__ #define __DUMP_H__
@@ -5,8 +26,9 @@
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
void dump_memory(uint32_t bottom_addr, uint32_t top_addr);
void dump_packet(uint32_t addr,uint32_t len,uint8_t *packet); void dump_packet(uint32_t addr,uint32_t len,uint8_t *packet);
void dump_memoryt(uint32_t bottom_addr, uint32_t top_addr);
#endif #endif

668
avr/usbload/fat.c Normal file
View File

@@ -0,0 +1,668 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "fat.h"
#include "file.h"
#include "mmc.h"
#include "config.h"
struct Fat fat; // wichtige daten/variablen der fat
struct File file; // wichtige dateibezogene daten/variablen
#if (WRITE==1)
// ***************************************************************************************************************
// schreibt sektor nummer:sec auf die karte (puffer:sector) !!
// setzt bufferFlag=0 da puffer nicht dirty sein kann nach schreiben !
// ***************************************************************************************************************
uint8_t fat_writeSector(uint32_t sec)
{
fat.bufferDirty = 0; // buffer kann nicht dirty sein weil wird geschrieben
return (mmc_write_sector(sec, fat.sector)); // schreiben von sektor puffer
}
#endif
// ***************************************************************************************************************
// umrechnung cluster auf 1.sektor des clusters (möglicherweise mehrere sektoren/cluster) !
// ***************************************************************************************************************
uint32_t fat_clustToSec(uint32_t clust)
{
return (fat.dataDirSec + 2 + ((clust - 2) * fat.secPerClust)); // errechnet den 1. sektor der sektoren des clusters
}
// ***************************************************************************************************************
// umrechnung sektor auf cluster (nicht die position im cluster selber!!)
// ***************************************************************************************************************
uint32_t fat_secToClust(uint32_t sec)
{
return ((sec - fat.dataDirSec - 2 + 2 * fat.secPerClust) / fat.secPerClust); // umkerhrfunktion von fat_clustToSec
}
// ***************************************************************************************************************
// läd sektor:sec auf puffer:sector zum bearbeiten im ram !
// setzt currentSectorNr auf richtigen wert (also den sektor der gepuffert ist). es wird geprüft
// ob der gepufferte sektor geändert wurde, wenn ja muss erst geschrieben werden, um diese daten nicht zu verlieren !
// ***************************************************************************************************************
uint8_t fat_loadSector(uint32_t sec)
{
if (sec != fat.currentSectorNr) { // nachladen nötig
#if (WRITE==1)
if (fat.bufferDirty == 1)
fat_writeSector(fat.currentSectorNr); // puffer diry, also vorher schreiben
#endif
mmc_read_sector(sec, fat.sector); // neuen sektor laden
fat.currentSectorNr = sec; // aktualisiert sektor nummer (nummer des gepufferten sektors)
return (0);
}
else
return (0); // alles ok, daten sind schon da (sec==fat.currentSectorNr)
return (1); // fehler
}
// datei lesen funktionen:
// fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir -> fat_loadFileDataFromDir -> fat_cd
// "daten chain"
// ***************************************************************************************************************
// läd die reihe:row des gepufferten sektors auf das struct:file. dort stehen dann
// alle wichgigen daten wie: 1.cluster,länge bei dateien, name des eintrags, reihen nummer (im sektor), attribut use...
// ***************************************************************************************************************
uint8_t fat_loadRowOfSector(uint16_t row)
{
uint8_t i;
row = row << 5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 usw).
void *vsector; // void, damit man schoen umbiegen kann :)
for (i = 0; i < 11; i++)
file.name[i] = fat.sector[row + i]; // datei name, ersten 10 bytes vom 32 byte eintrag.
file.attrib = fat.sector[row + 11]; // datei attribut, byte 11.
vsector = &fat.sector[row + 26]; // low word von fist.cluster
file.firstCluster = *(uint16_t *) vsector;
vsector = &fat.sector[row + 20]; // high word von first.cluster
file.firstCluster |= (*(uint16_t *) vsector) << 16;
vsector = &fat.sector[row + 28]; // 4 byte von file.length
file.length = *(uint32_t *) vsector;
return (0);
}
// ***************************************************************************************************************
// geht reihen weise durch sektoren des clusters mit dem startsektor:sec, und sucht nach der datei mit dem
// namen:name. es werden die einzelnen sektoren nachgeladen auf puffer:sector vor dem bearbeiten.
// wird die datei in dem cluster gefunden ist return 0 , sonst return1.
// ***************************************************************************************************************
uint8_t fat_loadFileDataFromCluster(uint32_t sec, char name[])
{
uint8_t r;
uint8_t s = 0;
do { // sektoren des clusters prüfen
r = 0; // neuer sektor, dann reihen von 0 an.
mmc_read_sector(sec + s, fat.sector); // läd den sektor sec auf den puffer fat.sector
fat.currentSectorNr = sec + s; // setzen des aktuellen sektors
do { // reihen des sektors prüfen
fat_loadRowOfSector(r); // zeile 0-15 auf struct file laden
if (file.name[0] == 0) { // wenn man auf erste 0 stößt müsste der rest auch leer sein!
file.row = r; // zeile sichern.
return (1);
}
if (0 == strncmp((char *) file.name, name, 10)) { // zeile r ist gesuchte
file.row = r; // zeile sichern.
return (0);
}
r++;
} while (r < 16); // zählt zeilennummer (16(zeilen) * 32(spalten) == 512 bytes des sektors)
s++;
} while (s < fat.secPerClust); // geht durch sektoren des clusters
return (1); // fehler (datei nicht gefunden, oder fehler beim lesen)
}
// ***************************************************************************************************************
// wenn dir == 0 dann wird das root direktory durchsucht, wenn nicht wird der ordner cluster-chain gefolgt, um
// die datei zu finden. es wird das komplette directory in dem man sich befindet durchsucht.
// bei fat16 wird der rootDir berreich durchsucht, bei fat32 die cluster chain des rootDir.
// ***************************************************************************************************************
uint8_t fat_loadFileDataFromDir(char name[])
{
uint16_t s;
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
// rootDir sektoren).
if (0 == fat_loadFileDataFromCluster(fat.rootDir + s, name))
return (0); // sucht die datei, wenn da, läd daten (1.cluster usw)
}
}
else {
uint32_t i;
if (fat.dir == 0 && fat.fatType == 32)
i = fat.rootDir; // IM ROOTDIR. fat32
else
i = fat.dir; // NICHT ROOTDIR
while (!((i == 0xfffffff && fat.fatType == 32) || (i == 0xffff && fat.fatType == 16))) { // prüft ob weitere sektoren zum
// lesen da sind (fat32||fat16)
if (0 == fat_loadFileDataFromCluster(fat_clustToSec(i), name))
return (0); // lät die daten der datei auf struct:file. datei gefunden (umrechnung auf absoluten sektor)
i = fat_getNextCluster(i); // liest nächsten cluster des dir-eintrags (unterverzeichniss größer 16 einträge)
}
}
return (1); // datei/verzeichniss nicht gefunden
}
#if (SMALL_FILE_SYSTEM==0)
// ***************************************************************************************************************
// start immer im root Dir. start in root dir (dir==0).
// es MUSS in das direktory gewechselt werden, in dem die datei zum lesen/anhängen ist (außer root, da startet mann)!
// ***************************************************************************************************************
uint8_t fat_cd(char name[])
{
if (name[0] == 0) { // ZUM ROOTDIR FAT16/32
fat.dir = 0; // root dir
return (0);
}
if (0 == fat_loadFileDataFromDir(name)) { // NICHT ROOTDIR (fat16/32)
fat.dir = file.firstCluster; // zeigt auf 1.cluster des dir (fat16/32)
return (0);
}
return (1); // dir nicht gewechselt (nicht da?) !!
}
#endif
#if (WRITE==1)
// datei anlegen funktionen :
// ***************************************************************************************************************
// sucht leeren eintrag (zeile) im cluster mit dem startsektor:secStart.
// wird dort kein freier eintrag gefunden ist return (1).
// wird ein freier eintrag gefunden, ist die position der freien reihe auf file.row abzulesen und return (0).
// der sektor mit der freien reihe ist auf dem puffer:sector gepuffert.
// ****************************************************************************************************************
uint8_t fat_getFreeRowOfCluster(unsigned long secStart)
{
uint16_t b; // zum durchgenen der sektor bytes
uint8_t s = 0; // sektoren des clusters.
do {
file.row = 0; // neuer sektor(oder 1.sektor), reihen von vorne.
if (0 == fat_loadSector(secStart + s)) { // laed sektor auf puffer fat.sector
for (b = 0; b < 512; b = b + 32) { // zaehlt durch zeilen (0-15).
if (fat.sector[b] == 0x00 || fat.sector[b] == 0xE5)
return (0); // prueft auf freihen eintrag (leer oder geloescht == OK!).
file.row++; // zählt reihe hoch (nächste reihe im sektor).
}
}
s++; // sektoren des clusters ++ weil einen geprüft.
} while (s < fat.secPerClust); // geht die sektoren des clusters durch (moeglicherweise auch nur 1. sektor).
return (1); // nicht gefunden in diesem cluster (== nicht OK!).
}
// ***************************************************************************************************************
// sucht leeren eintrag (zeile) im directory mit dem startcluster:dir.
// geht die cluster chain des direktories durch. dabei werden auch alle sektoren der cluster geprüft.
// wird dort kein freier eintrag gefunden, wird ein neuer leerer cluster gesucht, verkettet und der
// 1. sektor des freien clusters geladen. die reihe wird auf den ersten eintrag gesetzt, da frei.
// anhand der reihe kann man nun den direktory eintrag vornehmen, und auf die karte schreiben.
// ****************************************************************************************************************
void fat_getFreeRowOfDir(uint32_t dir)
{
uint32_t start = dir;
// solange bis ende cluster chain.
while (!
((dir == 0xfffffff && fat.fatType == 32)
|| (dir == 0xffff && fat.fatType == 16))) {
if (0 == fat_getFreeRowOfCluster(fat_clustToSec(dir)))
return; // freien eintrag in clustern, des dir gefunden !!
start = dir;
dir = fat_getNextCluster(dir);
} // wenn aus schleife raus, kein freier eintrag da -> neuer cluster nötig.
dir = fat_secToClust(fat.startSectors); // dir ist jetzt neuer cluster zum verketten !
fat_setCluster(start, dir); // cluster-chain mit neuem cluster verketten
fat_setCluster(dir, 0x0fffffff); // cluster-chain ende markieren
// es muessen neue gesucht werden, weil der bekannte aus file.c ja grade verkettet wurden. datei eintrag passte nicht mehr ins dir...
fat_getFreeClustersInRow(2); // neue freie cluster suchen, für datei.
file.firstCluster = fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster = fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat.currentSectorNr = fat_clustToSec(dir); // setzen des richtigen sektors, also auf den 1. der neu verketteten
uint16_t j = 511;
do {
fat.sector[j] = 0x00; // schreibt puffer fat.sector voll mit 0x00==leer
} while (j--);
uint8_t i = 1; // ab 1 weil der 1.sektor des clusters eh noch beschrieben wird...
do {
fat_writeSector(fat.currentSectorNr + i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls,
i++;
} while (i < fat.secPerClust);
file.row = 0; // erste reihe frei, weil grad neuen cluster verkettet !
}
// ***************************************************************************************************************
// erstellt 32 byte eintrag einer datei, oder verzeichnisses im puffer:sector.
// erstellt eintrag in reihe:row, mit namen:name usw... !!
// muss noch auf die karte geschrieben werden ! nicht optimiert auf geschwindigkeit.
// ***************************************************************************************************************
void fat_makeRowDataEntry(uint16_t row, char name[], uint8_t attrib,
uint32_t cluster, uint32_t length)
{
fat.bufferDirty = 1; // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
row = row << 5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile
// 15=480)
uint8_t i; // byte zähler in reihe von sektor (32byte eintrag)
uint8_t *bytesOfSec = &fat.sector[row]; // zeiger auf sector bytes
void *vsector;
for (i = 0; i < 11; i++)
*bytesOfSec++ = name[i]; // namen schreiben
*bytesOfSec++ = attrib; // attrib schreiben
vsector = &fat.sector[row + 12];
*(uint32_t *) vsector++ = 0x01010101; // unnoetige felder beschreiben
*(uint32_t *) vsector = 0x01010101;
vsector = &fat.sector[row + 20];
*(uint16_t *) vsector = (cluster & 0xffff0000) >> 16; // low word von cluster
vsector = &fat.sector[row + 22];
*(uint32_t *) vsector = 0x01010101; // unnoetige felder beschreiben
vsector = &fat.sector[row + 26];
*(uint16_t *) vsector = (cluster & 0x0000ffff); // high word von cluster
vsector = &fat.sector[row + 28];
*(uint32_t *) vsector = length; // laenge
}
// ***************************************************************************************************************
// macht den datei eintrag im jetzigen verzeichniss (fat.dir).
// file.row enthält die reihen nummer des leeren eintrags, der vorher gesucht wurde, auf puffer:sector ist der gewünschte
// sektor gepuffert. für fat16 im root dir muss andere funktion genutzt werden, als fat_getFreeRowOfDir (durchsucht nur dirs).
// fat.rootDir enthält bei fat32 den start cluster des directory, bei fat16 den 1. sektor des rootDir bereichs!
// ***************************************************************************************************************
void fat_makeFileEntry(char name[], uint8_t attrib,
uint32_t length)
{
uint16_t s; // zähler für root dir sektoren fat16
if (fat.dir == 0 && fat.fatType == 32)
fat_getFreeRowOfDir(fat.rootDir); // IM ROOT DIR (fat32)
else if (fat.dir == 0 && fat.fatType == 16) { // IM ROOT DIR (fat16)
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
// rootDir sektoren).
if (0 == fat_getFreeRowOfCluster(fat.rootDir + s))
break; // geht durch sektoren des root dir.
}
}
else
fat_getFreeRowOfDir(fat.dir); // NICHT ROOT DIR fat32/fat16
fat_makeRowDataEntry(file.row, name, attrib, file.firstCluster, length); // schreibt file eintrag auf puffer
fat_writeSector(fat.currentSectorNr); // schreibt puffer auf karte
}
#endif
// fat funktionen:
// ***************************************************************************************************************
// sucht nötige folge Cluster aus der fat !
// erster daten cluster = 2, ende einer cluster chain 0xFFFF (fat16) oder 0xFFFFFFF, 0xFFFFFF8 (fat32),
// stelle des clusters in der fat, hat als wert, den nächsten cluster. (1:1 gemapt)!
// ***************************************************************************************************************
uint32_t fat_getNextCluster(uint32_t oneCluster)
{
// FAT 16**************FAT 16
if (fat.fatType == 16) {
uint32_t i = oneCluster >> 8;; // (i=oneCluster/256)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
uint32_t j = (oneCluster << 1) - (i << 9); // (j=(oneCluster-256*i)*2 == 2*oneCluster-512*i)errechnet das low byte von
// oneCluster
if (0 == fat_loadSector(i + fat.fatSec)) { // ob neu laden nötig, wird von fat_loadSector geprüft
void *bytesOfSec = &fat.sector[j]; // zeiger auf puffer
return *(uint16_t *) bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
}
}
// FAT 32**************FAT 32
else {
uint32_t i = oneCluster >> 7; // (i=oneCluster/128)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
uint32_t j = (oneCluster << 2) - (i << 9); // (j=(oneCluster-128*i)*4 == oneCluster*4-512*i)errechnet das low byte von
// oneCluster
if (0 == fat_loadSector(i + fat.fatSec)) { // ob neu laden nötig wird von fat_loadSector geprüft
void *bytesOfSec = &fat.sector[j]; // zeiger auf puffer
return *(uint32_t *) bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
}
}
return (0);
}
// ***************************************************************************************************************
// sucht verkettete cluster einer datei, die in einer reihe liegen. worst case: nur ein cluster.
// sieht in der fat ab dem cluster offsetCluster nach. sucht die anzahl von MAX_CLUSTERS_IN_ROW,
// am stück,falls möglich. prüft ob der cluster neben offsetCluster dazu gehört...
// setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
// ***************************************************************************************************************
void fat_getFatChainClustersInRow(uint32_t offsetCluster)
{
uint16_t i = 0;
fat.startSectors = fat_clustToSec(offsetCluster); // setzen des 1. sektors der datei
fat.endSectors = fat.startSectors;
do {
if ((offsetCluster + 1 + i) == fat_getNextCluster(offsetCluster + i))
fat.endSectors += fat.secPerClust; // zählen der zusammenhängenden sektoren
else {
file.lastCluster = offsetCluster + i; // cluster daneben gehört nicht dazu, somit ist offset+i der letzte bekannte
break;
}
} while (i++ < MAX_CLUSTERS_IN_ROW);
fat.endSectors += fat.secPerClust - 1;
}
#if (WRITE==1)
// ***************************************************************************************************************
// sucht freie zusammenhängende cluster aus der fat. maximal MAX_CLUSTERS_IN_ROW am stück.
// erst wir der erste frei cluster gesucht, ab offsetCluster(iklusive) und dann wird geschaut, ob der
// daneben auch frei ist. setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
// ***************************************************************************************************************
void fat_getFreeClustersInRow(uint32_t offsetCluster)
{
uint16_t i = 1; // variable für anzahl der zu suchenden sektoren
while (fat_getNextCluster(offsetCluster))
offsetCluster++; // suche des 1. freien clusters
fat.startSectors = fat_clustToSec(offsetCluster); // setzen des startsektors der freien sektoren (umrechnen von cluster zu sektoren)
fat.endSectors = fat.startSectors;
do { // suche der nächsten freien
if (0 == fat_getNextCluster(offsetCluster + i))
fat.endSectors += fat.secPerClust; // zählen der zusammenhängenden sektoren
else
break; // cluster daneben ist nicht frei
} while (i++ < MAX_CLUSTERS_IN_ROW);
fat.endSectors += fat.secPerClust - 1; // -1 weil der erste sektor schon mit zählt z.b. [95,98] = 4 sektoren
}
// ***************************************************************************************************************
// verkettet ab startCluster bis einschließlich endCluster. verkettet auch den letzten bekannten mit den neu übergebenen !
// es ist wegen der fragmentierung der fat nötig, sich den letzten bekannten cluster zu merken,
// damit man bei weiteren cluster in einer reihe die alten cluster noch dazu verketten kann (so sind lücken im verketten möglich).
// ***************************************************************************************************************
void fat_setClusterChain(uint32_t startCluster,
uint16_t endCluster)
{
fat_setCluster(file.lastCluster, startCluster); // ende der chain setzen, bzw verketten der ketten
while (startCluster != endCluster) {
startCluster++;
fat_setCluster(startCluster - 1, startCluster); // verketten der cluster der neuen kette
}
fat_setCluster(startCluster, 0xfffffff); // ende der chain setzen
file.lastCluster = endCluster; // ende cluster der kette updaten
fat_writeSector(fat.currentSectorNr); // schreiben des fat sektors auf die karte
}
// ***************************************************************************************************************
// setzt den cluster inhalt. errechnet den sektor der fat in dem cluster ist, errechnet das low byte von
// cluster und setzt dann byteweise den inhalt:content.
// prüft ob buffer dirty (zu setztender cluster nicht in jetzt gepuffertem).
// prüfung erfolgt in fat_loadSector, dann wird alter vorher geschrieben, sonst gehen dort daten verloren !!
// ***************************************************************************************************************
void fat_setCluster(uint32_t cluster, uint32_t content)
{
// FAT 16**************FAT 16
if (fat.fatType == 16) {
uint32_t i = cluster >> 8; // (i=cluster/256)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
uint32_t j = (cluster << 1) - (i << 9); // (j=(cluster-256*i)*2 == 2*cluster-512*i)errechnet das low byte von
// cluster
if (0 == fat_loadSector(i + fat.fatSec)) { // neu laden (fat_loadSector prüft ob schon gepuffert)
void *bytesOfSec = &fat.sector[j]; // init des zeigers auf unterste adresse
*(uint16_t *) bytesOfSec = content; // weil ram auch little endian geht das so :)
fat.bufferDirty = 1; // zeigt an, dass im aktuellen sector geschrieben wurde
}
}
// FAT 32**************FAT 32
else {
uint32_t i = cluster >> 7; // (i=cluster/128)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
uint32_t j = (cluster << 2) - (i << 9); // (j=(cluster-128*i)*4 == cluster*4-512*i)errechnet das low byte von
// cluster
if (0 == fat_loadSector(i + fat.fatSec)) { // neu laden (fat_loadSector prüft ob schon gepuffert)
void *bytesOfSec = &fat.sector[j]; // init des zeigers auf unterste adresse
*(uint32_t *) bytesOfSec = content; // weil ram auch little endian geht das so :)
fat.bufferDirty = 1; // zeigt an, dass im aktuellen sector geschrieben wurde
}
}
}
// ***************************************************************************************************************
// löscht cluster chain, beginnend ab dem startCluster.
// sucht cluster, setzt inhalt usw.. abschließend noch den cluster-chain ende markierten cluster löschen.
// ***************************************************************************************************************
void fat_delClusterChain(uint32_t startCluster)
{
uint32_t nextCluster = startCluster; // tmp variable, wegen verketteter cluster..
do {
startCluster = nextCluster;
nextCluster = fat_getNextCluster(startCluster);
fat_setCluster(startCluster, 0x00000000);
} while (!
((nextCluster == 0xfffffff && fat.fatType == 32)
|| (nextCluster == 0xffff && fat.fatType == 16)));
fat_writeSector(fat.currentSectorNr);
}
#endif
// ***************************************************************************************************************
// Initialisiert die Fat(16/32) daten, wie: root directory sektor, daten sektor, fat sektor...
// siehe auch Fatgen103.pdf. ist NICHT auf performance optimiert!
// byte/sector, byte/cluster, anzahl der fats, sector/fat ... (halt alle wichtigen daten zum lesen ders datei systems!)
// *****************************************************************<**********************************************
uint8_t fat_loadFatData(uint32_t sec)
{
// offset,size
uint16_t rootEntCnt; // 17,2 größe die eine fat belegt
uint16_t fatSz16; // 22,2 sectors occupied by one fat16
uint32_t fatSz32; // 36,4 sectors occupied by one fat32
void *vsector;
if (0 == mmc_read_sector(sec, fat.sector)) { // lesen von fat sector und bestimmen der wichtigen berreiche
fat.bufferDirty = 0; // init wert des flags
fat.secPerClust = fat.sector[13]; // fat.secPerClust, 13 only (power of 2)
vsector = &fat.sector[14];
fat.fatSec = *(uint16_t *) vsector;
vsector = &fat.sector[17];
rootEntCnt = *(uint16_t *) vsector;
vsector = &fat.sector[22];
fatSz16 = *(uint16_t *) vsector;
fat.rootDir = (((rootEntCnt << 5) + 512) / 512) - 1; // ist 0 bei fat 32, sonst der root dir sektor
if (fat.rootDir == 0) { // FAT32 spezifisch (die prüfung so, ist nicht spezifikation konform !).
vsector = &fat.sector[36];
fatSz32 = *(uint32_t *) vsector;
vsector = &fat.sector[44];
fat.rootDir = *(uint32_t *) vsector;
fat.dataDirSec = fat.fatSec + (fatSz32 * fat.sector[16]); // data sector (beginnt mit cluster 2)
fat.fatType = 32; // fat typ
}
else { // FAT16 spezifisch
fat.dataDirSec = fat.fatSec + (fatSz16 * fat.sector[16]) + fat.rootDir; // data sektor (beginnt mit cluster 2)
fat.rootDir = fat.dataDirSec - fat.rootDir; // root dir sektor, da nicht im datenbereich (cluster)
fat.rootDir += sec; // addiert den startsektor auf "
fat.fatType = 16; // fat typ
}
fat.fatSec += sec; // addiert den startsektor auf
fat.dataDirSec += sec; // addiert den startsektor auf (umrechnung von absolut auf real)
fat.dataDirSec -= 2; // zeigt auf 1. cluster
fat.dir = 0; // dir auf '0'==root dir, sonst 1.Cluster des dir
return (0);
}
return (1); // sector nicht gelesen, fat nicht initialisiert!!
}
// ************************************************************************************************<<***************
// int fat sucht den 1. cluster des dateisystems (fat16/32) auch VBR genannt,
// ************************************************************************************************<<***************
uint8_t fat_initfat(void)
{
uint32_t secOfFirstPartition = 0; // ist 1. sektor der 1. partition aus dem MBR
if (0 == mmc_read_sector(0, fat.sector)) {
void *vsector = &fat.sector[454]; // startsektor bestimmen
secOfFirstPartition = *(uint32_t *) vsector;
// prüfung ob man schon im VBR gelesen hat (0x6964654d = "Medi")
if (secOfFirstPartition == 0x6964654d)
return fat_loadFatData(0); // ist superfloppy
else {
return fat_loadFatData(secOfFirstPartition);
} // ist partitioniert...
}
return (1);
}
#if (SMALL_FILE_SYSTEM==0)
// *****************************************************************************************************************
// bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann.
// wandelt z.b. "t.txt" -> "T TXT" oder "main.c" in "MAIN C " => also immer 8.3 und upper case letter
// VORSICHT es werden keine Prüfungen gemacht !
// *****************************************************************************************************************
char *fat_str(char *str)
{
uint8_t i;
uint8_t j = 0;
uint8_t c;
char tmp[12]; // tmp string zum einfacheren umwandeln
strcpy(tmp, str);
for (i = 0; i < 11; i++)
str[i] = ' '; // als vorbereitung alles mit leerzeichen füllen
str[11] = '\0';
i = 0;
do {
c = toupper(tmp[j]);
if (c == '\0')
return str;
if (c != '.')
str[i] = c;
else
i = 7;
i++;
j++;
} while (i < 12);
return str;
}
#endif

78
avr/usbload/fat.h Normal file
View File

@@ -0,0 +1,78 @@
#ifndef _FAT_H
#define _FAT_H
// **************************************************************************************************************************
// WICHTIGE SCHLATER: -> hier kann die code größe angepasst werden, zu lasten der funktionalität !
// die fat nicht fragmentiert ist !
#define SMALL_FILE_SYSTEM 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung !
#define WRITE 0 // wenn 1 dann ist write an, wenn 0 dann read only !
#define OVER_WRITE 0 // wenn 1 dann kann ffwrite dateien überschreiben (nicht performant), wenn 0 dann nur normales schreiben !
#define MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
// 1. fat_getFreeRowOfCluster -> fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector "eintrag gemacht !!"
// 2. fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir (-> fat_cd) "daten chain"
// **************************************************************************************************************************
// funktionen
extern uint32_t fat_clustToSec(uint32_t); // rechnet cluster zu 1. sektor des clusters um
extern uint32_t fat_secToClust(uint32_t sec); // rechnet sektor zu cluster um!
extern uint32_t fat_getNextCluster(uint32_t oneCluster); // fat auf nächsten, verketteten cluster durchsuchen
extern uint8_t fat_initfat(void); // initalisierung (durchsucht MBR oder nicht)
extern uint8_t fat_writeSector(uint32_t sec); // schreibt sektor auf karte
extern void fat_setCluster(uint32_t cluster, uint32_t content); // setzt cluster inhalt in der fat
extern void fat_delClusterChain(uint32_t startCluster); // löscht cluster-chain in der fat
extern void fat_getFreeRowOfDir(uint32_t dir); // durchsucht directory nach feiem eintrag
extern void fat_makeFileEntry(char name[], uint8_t attrib,
uint32_t length);
extern uint8_t fat_loadSector(uint32_t sec); // läd übergebenen absoluten sektor
extern uint8_t fat_loadFileDataFromDir(char name[]); // durchsucht das aktuelle directory
extern uint8_t fat_cd(char *); // wechselt directory (start im rootDir)
extern uint8_t fat_loadFatData(uint32_t); // läd fat daten
extern uint8_t fat_getFreeRowOfCluster(unsigned long secStart); // durchsucht cluster nach freiem eintrag
extern void fat_getFreeClustersInRow(uint32_t offsetCluster); // sucht zusammenhängende freie cluster aus der fat
extern void fat_getFatChainClustersInRow(uint32_t offsetCluster); // sucht fat-chain cluster die zusammenhängen
extern void fat_makeRowDataEntry(uint16_t row, char name[],
uint8_t attrib,
uint32_t cluster,
uint32_t length);
extern uint8_t fat_loadRowOfSector(uint16_t); // läd reihe des geladen sektors auf struct:file
extern uint8_t fat_loadFileDataFromCluster(uint32_t sec, char name[]); // durchsucht die reihen des geladenen sektors
extern void fat_setClusterChain(uint32_t newOffsetCluster,
uint16_t length);
extern char *fat_str(char *str); // wandelt einen string so, dass er der fat konvention entspricht !
// **************************************************************************************************************************
// variablen
extern struct Fat { // fat daten (1.cluster, root-dir, dir usw.)
uint8_t sector[512]; // der puffer für sektoren !
uint8_t bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird
uint32_t currentSectorNr; // aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder
// bei fat operationen im gleichen sektor
uint32_t dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root)
uint32_t rootDir; // Sektor(f16)/Cluster(f32) nr root directory
uint32_t dataDirSec; // Sektor nr data area
uint32_t fatSec; // Sektor nr fat area
uint32_t startSectors; // der erste sektor in einer reihe (freie oder verkettete)
uint32_t endSectors;
uint8_t secPerClust; // anzahl der sektoren pro cluster
uint8_t fatType; // fat16 oder fat32 (16 oder 32)
} fat;
extern struct File { // datei infos
uint16_t cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors
uint8_t name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS uint8_t weil E5)
uint8_t attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag
uint8_t row; // reihe im sektor in der die datei infos stehen (reihe 0-15)
uint32_t firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte)
uint32_t length; // 28,4 datei Länge (4-byte)
uint32_t lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette
uint32_t seek; // schreib position in der datei
} file;
#endif

View File

@@ -1,3 +1,25 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include "fifo.h" #include "fifo.h"
void fifo_init(fifo_t * f, uint8_t * buffer, const uint8_t size) void fifo_init(fifo_t * f, uint8_t * buffer, const uint8_t size)

View File

@@ -1,3 +1,22 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __FIFO_H__ #ifndef __FIFO_H__
#define __FIFO_H__ #define __FIFO_H__

525
avr/usbload/file.c Normal file
View File

@@ -0,0 +1,525 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mmc.h"
#include "fat.h"
#include "file.h"
#include "dir.h"
#include "config.h"
// *******************************************************************************************************************************
// 2 möglichkeiten beim öffnen, datei existiert(return 1) oder muss angelegt werden(return 2)
// zuerst wird geprüft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geöffnet wird oder angelegt.
// -beim offnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf
// den puffer fat.sector geladen. jetzt kann man ffread lesen...
// -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefüllt.
// danach wird der dateieintrag gemacht(auf karte). dort wird auch geprüft ob genügend platz im aktuellen verzeichniss existiert.
// möglicherweise wird der 1. cluster der datei nochmal geändert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden.
//*******************************************************************************************************************************
unsigned char ffopen(char name[]){
unsigned char file_flag=fat_loadFileDataFromDir(name); //prüfung ob datei vorhanden und evetuelles laden des file struct
if( file_flag==0 ){ /** Datei existiert, anlegen nicht nötig! **/
fat_getFatChainClustersInRow( file.firstCluster ); // verkettete cluster aus der fat-chain suchen.
fat_loadSector( fat_clustToSec(file.firstCluster) ); // lät die ersten 512 bytes der datei auf puffer:sector.
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
return 1;
}
#if (WRITE==1) // anlegen ist schreiben !
else{ /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/
fat_getFreeClustersInRow(2); // leere cluster suchen, ab cluster 2.
strcpy((char*)file.name,(char*)name); // --- füllen des file struct, zum abschließenden schreiben.
file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster=file.firstCluster;//fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
file.attrib=32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !!
file.length=0; // damit da nix drin steht ^^
fat_makeFileEntry((char *)file.name,file.attrib,0); // DATEI ANLEGEN auf karte
fat.currentSectorNr=fat_clustToSec(file.firstCluster); // setzen des ersten sektors
return 2;
}
#endif
}
//*******************************************************************************************************************************
// schließt die datei operation ab. eigentlich nur nötig wenn geschrieben wurde. es gibt 2 möglichkeiten :
// 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben.
// 2. die datei wird geschlossen und man war innerhalb der datei größe, dann muss nur der aktuelle sektor geschrieben werden.
// der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten
// und die neue datei länge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder
// der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ).
// *******************************************************************************************************************************
uint8_t ffclose(void)
{
#if (WRITE==1) /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/
if (file.length < (file.seek + file.cntOfBytes))
fileUpdate(); /** 1.) es wurde über die alte datei größe hinaus geschrieben **/
else if (fat.bufferDirty == 1)
fat_writeSector(fat.currentSectorNr); /** 2.) nicht über alte datei länge hinaus **/
#endif
file.cntOfBytes = 0; // init werte der nötigen zähler
file.seek = 0;
return (0);
}
// *******************************************************************************************************************************
// updatet datei eintrag auf der karte und verkettet die dazugehörigen fat cluster.
// füllt den aktuell beschriebenen sektor mit 0x00, da sonst die datei nicht richtig angezeigt wird.
// darf nur während schreibe operationen aufgerufen werden !
// *******************************************************************************************************************************
#if (WRITE==1)
void fileUpdate(void){
unsigned int comp_cntOfBytes=file.cntOfBytes; // sicher nötig wegen schleife...
while( comp_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen
fat.sector[comp_cntOfBytes]=0x00; // beschreibt ungenutzte bytes mit 0x00
comp_cntOfBytes++;
}
char name[13]; // zum sichern des dateinamens
unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und verändert !
strcpy(name,(char *)file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert !
fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster
fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file!
fat_makeRowDataEntry(file.row,name,32,file.firstCluster,save_length); // macht eintrag im puffer
fat_writeSector(fat.currentSectorNr);
}
#endif
// *******************************************************************************************************************************
// offset byte wird übergeben. es wird durch die sektoren der datei gespult (gerechnet), bis der sektor mit dem offset byte erreicht
// ist, dann wird der sektor geladen und der zähler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist,
// die "vorgesucht" wurden, müssen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors).
// *******************************************************************************************************************************
void ffseek(unsigned long int offset){
#if (WRITE==1)
#if (OVER_WRITE==1) // man muss den dateieintrag updaten, um die daten zu retten !!
if( file.seek > file.length ) fileUpdate(); // fat verketten und datei update auf der karte !
#endif
#endif
fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus !
unsigned long int sec=fat.startSectors; // sektor variable zum durchgehen durch die sektoren
file.seek=0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
while(offset>=512){ /** suchen des sektors in dem offset ist **/
sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden
offset-=512; // ein sektor weniger in dem das byte sein kann
file.seek+=512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt
if ( sec > fat.endSectors ){ // es müssen mehr sektoren der datei gesucht werden
fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) ); // nachladen von clustern in der chain
sec=fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen !
}
}
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat_loadSector(sec); // sektor mit offset byte laden
file.cntOfBytes = offset; // setzen des lese zählers
}
#if (SMALL_FILE_SYSTEM==0)
// *******************************************************************************************************************************
// wechselt verzeichniss. start immer im root Dir.
// MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist !
// *******************************************************************************************************************************
uint8_t ffcd(char name[])
{
return (fat_cd(name));
}
// *******************************************************************************************************************************
// zeigt reihen eines clusters an, wird für ffls benötigt !
// es wird ab dem start sektor start_sec, der dazugehörige cluster angezeigt. geprüft wird ob es ein richtiger
// eintrag in der reihe ist (nicht gelöscht, nicht frei usw). die sektoren des clusters werden nachgeladen.
// die dateien werden mit namen und datei größe angezeigt.
// *******************************************************************************************************************************
void lsRowsOfClust(uint32_t start_sec)
{
uint8_t row; // reihen
uint8_t sec = 0; // sektoren
do {
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for (row = 0; row < 16; row++) { // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if ((file.name[0] != 0xE5 && file.name[0] != 0x00)) {
if (file.attrib == 0x20)
printf("Name: %s Size:%li\n", file.name, file.length);
if (file.attrib == 0x10)
printf("Dir: %s\n", file.name);
}
}
} while (++sec < fat.secPerClust);
}
void ffls(void)
{
uint32_t clust; // cluster
uint16_t s; // fat16 root dir sektoren
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
lsRowsOfClust(fat.rootDir + s); // zeigt reihen eines root dir clust an
}
printf("Fat16\n");
} else {
if (fat.dir == 0 && fat.fatType == 32)
clust = fat.rootDir; // IM ROOTDIR. fat32
else
clust = fat.dir; // NICHT ROOT DIR
while (!((clust == 0xfffffff && fat.fatType == 32) || (clust == 0xffff && fat.fatType == 16))) { // prüft ob weitere
lsRowsOfClust(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust = fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
printf("Fat32\n");
}
}
void lsRowsOfClust_smc(uint32_t start_sec)
{
uint8_t row; // reihen
uint8_t sec = 0; // sektoren
do {
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for (row = 0; row < 16; row++) { // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if ((file.name[0] != 0xE5 && file.name[0] != 0x00)) {
if (file.attrib == 0x20)
dir_entry_add(file.firstCluster, file.name, file.length ,file.attrib);
}
}
} while (++sec < fat.secPerClust);
}
void ffls_smc(void)
{
uint32_t clust; // cluster
uint16_t s; // fat16 root dir sektoren
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (uint16_t) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
lsRowsOfClust_smc(fat.rootDir + s); // zeigt reihen eines root dir clust an
}
printf("Fat16\n");
} else {
if (fat.dir == 0 && fat.fatType == 32)
clust = fat.rootDir; // IM ROOTDIR. fat32
else
clust = fat.dir; // NICHT ROOT DIR
while (!((clust == 0xfffffff && fat.fatType == 32) || (clust == 0xffff && fat.fatType == 16))) { // prüft ob weitere
lsRowsOfClust_smc(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust = fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
printf("Fat32\n");
}
}
// *******************************************************************************************************************************
// wechselt in das parent verzeichniss (ein verzeichniss zurück !)
// die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
// kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
// *******************************************************************************************************************************
uint8_t ffcdLower(void)
{
if (fat.dir == 0)
return (1); // im root dir, man kann nicht höher !
fat_loadSector(fat_clustToSec(fat.dir)); // läd 1. sektor des aktuellen direktory.
fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
fat.dir = file.firstCluster; // dir setzen
return (0);
}
#ifndef __AVR_ATmega8__
// *******************************************************************************************************************************
// erstellt einen dir eintrag im aktuellen verzeichniss.
// prüft ob es den den dir-namen schon gibt, dann wird nichts angelegt.
// wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben.
// dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthält den "." und ".." eintrag.
// der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
// ein dir wird immer mit 0x00 initialisiert ! also alle einträge der sektoren des clusters ( bis auf . und .. einträge)!
// *******************************************************************************************************************************
#if (WRITE==1)
void ffmkdir(char name[]){
unsigned char i;
unsigned int j;
if(0==fat_loadFileDataFromDir(name))return ; // prüft ob dirname im dir schon vorhanden, wenn ja, abbruch !
// cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
fat_getFreeClustersInRow(2); // holt neue freie cluster, ab cluster 2 ...
fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
file.firstCluster=fat_secToClust(fat.startSectors); // dammit fat_makeFileEntry den cluster richtig setzen kann
fat_makeFileEntry(name,0x10,0); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
// aufbereiten des puffers
j=511;
do{
fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer
}while(j--);
// aufbereiten des clusters
for(i=1;i<fat.secPerClust;i++){ // ein dir cluster muss mit 0x00 initialisiert werden !
fat_writeSector(fat.startSectors+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls!
}
// aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
fat_makeRowDataEntry(0,". ",0x10,file.firstCluster,0); // macht "." eintrag des dirs
fat_makeRowDataEntry(1,".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs
fat_writeSector(fat_clustToSec(file.firstCluster)); // schreibt einträge auf karte !
}
#endif //WRITE
#endif // ffmkdir wegen atmega8
#endif
#if (WRITE==1)
// *******************************************************************************************************************************
// löscht datei/ordner aus aktuellem verzeichniss, wenn es die datei gibt.
// löscht dateien und ordner rekursiv !
// *******************************************************************************************************************************
uint8_t ffrm(char name[])
{
if (0 == fat_loadFileDataFromDir(name)) { // datei oder ordner ist vorhanden, nur dann lösch operation
if (file.attrib != 0x10) { // ist datei.
fat.sector[file.row << 5] = 0xE5; // datei gelöscht markieren (file.row*32, damit man auf reihen anfang kommt)
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor ?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht.
}
fat.bufferDirty = 1; // eintrag in puffer gemacht.
if (0 == fat_getNextCluster(file.firstCluster))
return (0); // 1.cluster ist leer ?!?
fat_delClusterChain(file.firstCluster); // löscht die zu der datei gehörige cluster-chain aus der fat.
return (0);
}
// TODO noch nicht optimal. zu viele schreib vorgänge beim löschen von datei einträgen. max bis zu 16/sektor !
else { // ist ordner, dann rekursiv löschen !!
#ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität....
uint32_t parent;
uint32_t own;
uint32_t clustsOfDir; // um durch die cluster chain eines dirs zu gehen.
uint8_t cntSecOfClust = 0;
uint8_t i = 0;
fat.sector[file.row << 5] = 0xE5; // löscht dir eintrag
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor (langer datei eintrag)?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht
}
fat.bufferDirty = 1; // puffer eintrag gemacht
parent = fat.dir; // der ordner in dem der zu löschende ordner ist.
own = file.firstCluster; // der 1. cluster des ordners der zu löschen ist.
clustsOfDir = file.firstCluster; // die "cluster" des zu löschenden ordners
do { // geht durch cluster des dirs
fat_loadSector(fat_clustToSec(clustsOfDir)); // sektor des dirs laden
do { // geht durch sektoren des clusters
do { // geht durch reihen des sektors
fat_loadRowOfSector(i);
if (file.attrib != 0x10 && file.attrib != 0x00 && file.name[0] != 0xE5) { // ist kein ordner,noch nicht
// gelöscht, kein freier eintrag
fat.sector[i << 5] = 0xE5; // erster eintrag der reihe als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
if (file.attrib == 0x20) { // ist datei!
fat_delClusterChain(file.firstCluster); // ist datei, dann cluster-chain der datei löschen
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // sektor neu laden, weil löschen der
// chain, den puffer nutzt.
}
}
if (file.attrib == 0x10 && file.name[0] == '.') { // "." oder ".." eintrag erkannt, löschen !
fat.sector[i << 5] = 0xE5; // eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
}
if (file.attrib == 0x10 && file.name[0] != '.' && file.name[0] != 0xE5 && file.name[0] != 0) { // ordner erkannt !
fat.sector[i << 5] = 0xE5; // dir eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
fat_loadSector(fat_clustToSec(file.firstCluster)); // sektor des dirs laden
clustsOfDir = file.firstCluster; // eigenes dir ist file.firstCluster
own = file.firstCluster; // eigener start cluster/dir
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
if (file.name[0] == 0x00) { // ende des dirs erreicht, wenn nicht voll !!
if (parent == fat.dir) { // erfolgreich alles gelöscht
fat_delClusterChain(own); // cluster chain des ordners löschen
return (0);
}
fat_delClusterChain(own); // cluster chain des ordners löschen
clustsOfDir = parent; // parent ist jetzt wieder arbeisverzeichniss.
own = parent; // arbeitsverzeichniss setzten
fat_loadSector(fat_clustToSec(own)); // sektor des dirs laden
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
i++;
} while (i < 16); // geht durch reihen des sektors.
i = 0; // neuer sektor -> reihen von vorne.
cntSecOfClust++;
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // läd sektoren des clusters nach
} while (cntSecOfClust < fat.secPerClust); // geht durch sektoren des clusters.
cntSecOfClust = 0; // neuer cluster -> sektoren von vorne.
clustsOfDir = fat_getNextCluster(clustsOfDir); // sucht neuen cluster der cluster-chain.
} while (!((clustsOfDir == 0xfffffff && fat.fatType == 32) || (clustsOfDir == 0xffff && fat.fatType == 16))); // geht
// durch
// cluster
// des
// dirs.
fat_delClusterChain(own); // hier landet man, wenn der ordner voll war (auf cluster "ebene")!!
#endif
}
}
return (1); // fehler, nicht gefunden?
}
#endif
// *******************************************************************************************************************************
// liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genügend verkettete
// sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen...
// *******************************************************************************************************************************
inline uint8_t ffread(void)
{
if (file.cntOfBytes == 512) { /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/
file.cntOfBytes = 0; // byte zähler zurück setzen
if (fat.currentSectorNr == fat.endSectors) { /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)**/
fat_getFatChainClustersInRow(fat_getNextCluster(fat_secToClust(fat.endSectors))); // nachladen von clustern in der chain
fat.currentSectorNr = fat.startSectors - 1; // setzen des nächsten sektors um weiter lesen zu können..
}
fat_loadSector(fat.currentSectorNr + 1); /** 2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)**/
}
return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! )
}
#if (WRITE==1)
#if (OVER_WRITE==0) // nicht überschreibende write funktion
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend
// zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten
// einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
// *******************************************************************************************************************************
inline void ffwrite(uint8_t c)
{
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben **/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen
fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren.
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
}
}
#endif
#if (OVER_WRITE==1) // überschreibende write funktion, nicht performant, weil immer auch noch ein sektor geladen werden muss
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genügend zusammenhängende
// sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten einer
// kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
// es ist beim überschreiben nötig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten
// hat. das ist blöd, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an
// geschwindigkeit.
// *******************************************************************************************************************************
inline void ffwrite(uint8_t c)
{
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers.
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben**/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben.
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
if (file.seek > file.length) { // außerhalb der datei !!
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen.
fat_getFreeClustersInRow(file.lastCluster); // neue leere sektoren benötigt, also suchen.
} else {
fat_getFatChainClustersInRow(fat_getNextCluster(file.lastCluster)); // noch innerhalb der datei, deshlab verkettete
// suchen.
}
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
mmc_read_sector(fat.currentSectorNr, fat.sector); // wegen überschreiben, muss der zu beschreibende sektor geladen werden...
}
}
#endif
// *******************************************************************************************************************************
// schreibt string auf karte, siehe ffwrite()
// *******************************************************************************************************************************
inline void ffwrites(const char *s)
{
while (*s)
ffwrite(*s++);
}
#endif

33
avr/usbload/file.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef _FILE_H
#define _FILE_H
// **************************************************************************************************************************
// funktionen
extern inline uint8_t ffread(void); // liest byte-weise aus der datei (puffert immer 512 bytes zwischen)
extern inline void ffwrite(uint8_t c); // schreibt ein byte in die geöffnete datei
extern inline void ffwrites(const char *s); // schreibt string auf karte
extern uint8_t ffopen(char name[]); // kann immer nur 1 datei bearbeiten.
extern uint8_t ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird.
extern void ffseek(uint32_t offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei.
extern uint8_t ffcd(char name[]); // wechselt direktory
extern void ffls(void); // zeigt direktory inhalt an
extern void ffls_smc(void); // zeigt direktory inhalt an
extern uint8_t ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory)
extern uint8_t ffrm(char name[]); // löscht datei aus aktuellem verzeichniss.
extern void ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an.
void lsRowsOfClust(uint32_t start_sec); // zeigt reihen eines clusters an, ab start_sec
void fileUpdate(void); // updatet datei eintrag auf karte
// **************************************************************************************************************************//
// #######################################################################################################################
#endif

12
avr/usbload/hardware.h Executable file
View File

@@ -0,0 +1,12 @@
#ifndef _HARDWARE_H
/*
hier sind die beiden hardware abhängigen bibliotheken zu includen !
welchen umfang diese haben müssen (an funktionen), muss man in den bibliotheken nachsehen.
*/
#define _HARDWARE_H
#include "uart.h"
#include "mmc.h"
#endif

49
avr/usbload/info.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h>
#include <stdint.h>
#include "info.h"
#include "uart.h"
extern FILE uart_stdout;
#if defined(NO_INFO) && defined(__GNUC__)
#define info(format, args...) ((void)0)
#else
void info(char* format, ...) {
#ifdef NO_INFO
#else
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
#endif
}
#endif

42
avr/usbload/info.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __INFO_H__
#define __INFO_H__
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#if defined(NO_INFO) && defined(__GNUC__)
/* gcc's cpp has extensions; it allows for macros with a variable number of
arguments. We use this extension here to preprocess pmesg away. */
#define info(format, args...) ((void)0)
#else
void info(char *format, ...);
/* print a message, if it is considered significant enough.
Adapted from [K&R2], p. 174 */
#endif
#endif

1953
avr/usbload/loader.c Normal file

File diff suppressed because it is too large Load Diff

9
avr/usbload/loader.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef __FIFO_H__
#define __FIFO_H__
#define ROM_BUFFER_SIZE 31091
#define ROM_HUFFMAN_SIZE 0
#define ROM_RLE_SIZE 31091
#endif

View File

@@ -1,29 +1,67 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> /* for sei() */ #include <avr/interrupt.h>
#include <util/delay.h> /* for _delay_ms() */ #include <util/delay.h>
#include <stdlib.h> #include <stdlib.h>
#include <avr/pgmspace.h> /* required by usbdrv.h */ #include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "usbdrv.h" #include "usbdrv.h"
#include "oddebug.h" /* This is also an example for using debug #include "oddebug.h"
* macros */
#include "config.h" #include "config.h"
#include "requests.h" /* The custom request numbers we use */ #include "requests.h"
#include "uart.h" #include "uart.h"
#include "sram.h" #include "sram.h"
#include "debug.h" #include "debug.h"
#include "info.h"
#include "dump.h"
#include "crc.h" #include "crc.h"
#include "usb_bulk.h" #include "usb_bulk.h"
#include "timer.h"
#include "watchdog.h"
#include "rle.h"
#include "loader.h"
#include "command.h"
#include "shared_memory.h"
#include "testing.h"
extern const char _rom[] PROGMEM;
extern FILE uart_stdout; extern FILE uart_stdout;
uint8_t debug_level = ( DEBUG | DEBUG_USB ); uint8_t debug_level = (DEBUG | DEBUG_USB | DEBUG_CRC | DEBUG_FAT);
uint8_t read_buffer[TRANSFER_BUFFER_SIZE]; uint8_t read_buffer[TRANSFER_BUFFER_SIZE];
uint32_t req_addr = 0; uint32_t req_addr = 0;
uint32_t req_addr_end = 0;
uint32_t req_size; uint32_t req_size;
uint8_t req_bank; uint8_t req_bank;
uint16_t req_bank_size; uint32_t req_bank_size;
uint16_t req_bank_cnt;
uint8_t req_percent;
uint8_t req_percent_last;
uint8_t req_state = REQ_STATUS_IDLE; uint8_t req_state = REQ_STATUS_IDLE;
uint8_t rx_remaining = 0; uint8_t rx_remaining = 0;
uint8_t tx_remaining = 0; uint8_t tx_remaining = 0;
@@ -33,123 +71,113 @@ uint8_t data_buffer[4];
uint32_t addr; uint32_t addr;
uint16_t crc = 0; uint16_t crc = 0;
usbMsgLen_t usbFunctionSetup(uchar data[8]) usbMsgLen_t usbFunctionSetup(uchar data[8])
{ {
usbRequest_t *rq = (void *) data; usbRequest_t *rq = (void *) data;
uint8_t ret_len = 0; uint8_t ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
if (rq->bRequest == USB_UPLOAD_INIT) {
if (req_state != REQ_STATUS_IDLE){ if (rq->bRequest == USB_BULK_UPLOAD_INIT) {
debug(DEBUG_USB,"USB_UPLOAD_INIT: ERROR state is not REQ_STATUS_IDLE\n");
return 0;
}
req_bank = 0; req_bank = 0;
rx_remaining = 0; rx_remaining = 0;
req_bank_size = 1 << rq->wValue.word; debug(DEBUG_USB, "USB_BULK_UPLOAD_INIT: %i %i\n", rq->wValue.word,
rq->wIndex.word);
req_bank_size = (uint32_t) (1L << rq->wValue.word);
req_bank_cnt = rq->wIndex.word;
req_addr_end = (uint32_t) req_bank_size *req_bank_cnt;
req_percent = 0;
req_percent_last = 0;
sync_errors = 0; sync_errors = 0;
crc = 0; debug(DEBUG_USB,
debug(DEBUG_USB,"USB_UPLOAD_INIT: bank_size=0x%x\n", req_bank_size); "USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n",
req_bank_size, req_bank_cnt, req_addr_end);
/* shared_memory_write(SHARED_MEM_TX_CMD_BANK_COUNT, req_bank_cnt);
* ------------------------------------------------------------------------- if (req_addr == 0x000000) {
*/ timer_start();
} else if (rq->bRequest == USB_UPLOAD_ADDR) {
req_state = REQ_STATUS_UPLOAD;
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
if (rx_remaining) {
sync_errors++;
debug
(DEBUG_USB,"USB_UPLOAD_ADDR: Out of sync addr=0x%lx remain=%i packet=%i sync_error=%i\n",
req_addr, rx_remaining, rq->wLength.word, sync_errors);
ret_len = 0;
} }
rx_remaining = rq->wLength.word;
ret_len = USB_MAX_TRANS;
if (req_addr && (req_addr % 0x1000) == 0) {
debug(DEBUG_USB,"USB_UPLOAD_ADDR: bank=0x%02x addr=0x%08lx\n",
req_bank, req_addr);
crc_check_bulk_memory(req_addr - 0x1000,req_addr);
}
if (req_addr && req_addr % req_bank_size == 0) {
debug(DEBUG_USB,"USB_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx\n",
req_bank, req_addr);
req_bank++;
}
ret_len = USB_MAX_TRANS;
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_DOWNLOAD_INIT) {
debug(DEBUG_USB,"USB_DOWNLOAD_INIT\n");
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_DOWNLOAD_ADDR) {
debug(DEBUG_USB,"USB_DOWNLOAD_ADDR\n");
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_BULK_UPLOAD_INIT) {
if (req_state != REQ_STATUS_IDLE){
debug(DEBUG_USB,"USB_BULK_UPLOAD_INIT: ERROR state is not REQ_STATUS_IDLE\n");
return 0;
}
req_bank = 0;
rx_remaining = 0;
req_bank_size = (1 << rq->wValue.word) & 0xffff;
sync_errors = 0;
debug(DEBUG_USB,"USB_BULK_UPLOAD_INIT: bank_size=0x%x\n", req_bank_size);
/* /*
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
} else if (rq->bRequest == USB_BULK_UPLOAD_ADDR) { } else if (rq->bRequest == USB_BULK_UPLOAD_ADDR) {
if (req_state != REQ_STATUS_IDLE){
debug(DEBUG_USB,"USB_BULK_UPLOAD_ADDR: ERROR state is not REQ_STATUS_IDLE\n");
return 0;
}
req_state = REQ_STATUS_BULK_UPLOAD; req_state = REQ_STATUS_BULK_UPLOAD;
req_addr = rq->wValue.word; req_addr = rq->wValue.word;
req_addr = req_addr << 16; req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word; req_addr = req_addr | rq->wIndex.word;
debug(DEBUG_USB,"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx \n",req_bank,req_addr); rx_remaining = rq->wLength.word;
ret_len = 0;
if (req_addr && req_addr % req_bank_size == 0) {
#ifdef FLT_DEBUG
debug(DEBUG_USB,
"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
req_bank, req_addr, timer_stop());
#else
debug(DEBUG_USB,
"USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%i\n",
req_bank, req_addr, timer_stop_int());
#endif
req_bank++;
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, req_bank);
sram_bulk_write_start(req_addr);
timer_start();
} else {
sram_bulk_write_start(req_addr);
}
ret_len = USB_MAX_TRANS;
/* /*
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
} else if (rq->bRequest == USB_BULK_UPLOAD_NEXT) { } else if (rq->bRequest == USB_BULK_UPLOAD_NEXT) {
if (req_state != REQ_STATUS_BULK_UPLOAD){ req_state = REQ_STATUS_BULK_UPLOAD;
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: ERROR state is not REQ_STATUS_BULK_UPLOAD\n"); req_addr = rq->wValue.word;
return 0; req_addr = req_addr << 16;
} req_addr = req_addr | rq->wIndex.word;
if (rx_remaining) {
sync_errors++;
debug(DEBUG_USB,
"USB_BULK_UPLOAD_NEXT: Out of sync addr=0x%lx remain=%i packet=%i sync_error=%i\n",
req_addr, rx_remaining, rq->wLength.word, sync_errors);
ret_len = 0;
}
rx_remaining = rq->wLength.word; rx_remaining = rq->wLength.word;
ret_len = USB_MAX_TRANS;
if (req_addr && req_addr % req_bank_size == 0) { req_percent = (uint32_t)( 100 * req_addr ) / req_addr_end;
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr= 0x%08lx \n", if (req_percent!=req_percent_last){
req_bank, req_addr); //debug(DEBUG_USB,
// "USB_BULK_UPLOAD_ADDR: precent=%i\n", req_percent);
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, req_percent);
sram_bulk_write_start(req_addr);
}
req_percent_last = req_percent;
#if 0
if (req_addr && (req_addr % 0x1000) == 0) {
debug(DEBUG_USB,
"USB_BULK_UPLOAD_NEXT: bank=0x%02x addr=0x%08lx crc=%04x\n",
req_bank, req_addr, crc_check_bulk_memory(req_addr - 0x1000,
req_addr,
req_bank_size));
}
sram_bulk_write_start(req_addr);
#endif
if (req_addr && (req_addr % req_bank_size) == 0) {
#ifdef FLT_DEBUG
debug(DEBUG_USB,
"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%.4f\n",
req_bank, req_addr, timer_stop());
#else
debug(DEBUG_USB,
"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%i\n",
req_bank, req_addr, timer_stop_int());
#endif
req_bank++; req_bank++;
timer_start();
shared_memory_write(SHARED_MEM_TX_CMD_BANK_CURRENT, req_bank);
sram_bulk_write_start(req_addr);
} }
ret_len = USB_MAX_TRANS; ret_len = USB_MAX_TRANS;
/* /*
@@ -157,13 +185,16 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
*/ */
} else if (rq->bRequest == USB_BULK_UPLOAD_END) { } else if (rq->bRequest == USB_BULK_UPLOAD_END) {
if (req_state != REQ_STATUS_BULK_UPLOAD) { if (req_state != REQ_STATUS_BULK_UPLOAD) {
debug(DEBUG_USB,"USB_BULK_UPLOAD_END: ERROR state is not REQ_STATUS_BULK_UPLOAD\n"); debug(DEBUG_USB,
"USB_BULK_UPLOAD_END: ERROR state is not REQ_STATUS_BULK_UPLOAD\n");
return 0; return 0;
} }
debug(DEBUG_USB, "USB_BULK_UPLOAD_END:\n"); debug(DEBUG_USB, "USB_BULK_UPLOAD_END:\n");
req_state = REQ_STATUS_IDLE; req_state = REQ_STATUS_IDLE;
sram_bulk_write_end(); sram_bulk_write_end();
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_END, 0);
ret_len = 0; ret_len = 0;
/* /*
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
@@ -172,14 +203,28 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_addr = req_addr << 16; req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word; req_addr = req_addr | rq->wIndex.word;
debug(DEBUG_USB, "USB_CRC: addr=0x%08lx \n", req_addr); debug(DEBUG_USB, "USB_CRC: addr=0x%08lx \n", req_addr);
crc_check_bulk_memory(0x000000,req_addr); crc_check_bulk_memory(0x000000, req_addr, req_bank_size);
ret_len = 0; ret_len = 0;
/* /*
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
} else if (rq->bRequest == USB_SNES_BOOT) { } else if (rq->bRequest == USB_MODE_SNES) {
req_state = REQ_STATUS_BOOT; req_state = REQ_STATUS_SNES;
debug(DEBUG_USB,"USB_SNES_BOOT: "); debug(DEBUG_USB, "USB_MODE_SNES:\n");
ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_MODE_AVR) {
req_state = REQ_STATUS_AVR;
debug(DEBUG_USB, "USB_MODE_AVR:\n");
ret_len = 0;
/*
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_AVR_RESET) {
debug(DEBUG_USB, "USB_AVR_RESET:\n");
soft_reset();
ret_len = 0; ret_len = 0;
/* /*
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
@@ -195,7 +240,8 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
req_size = rq->wLength.word; req_size = rq->wLength.word;
req_size = req_size << 2; req_size = req_size << 2;
tx_remaining = 2; tx_remaining = 2;
debug(DEBUG_USB,"USB_CRC_ADDR: addr=0x%lx size=%li\n", req_addr, req_size); debug(DEBUG_USB, "USB_CRC_ADDR: addr=0x%lx size=%li\n", req_addr,
req_size);
crc = crc_check_memory_range(req_addr, req_size, read_buffer); crc = crc_check_memory_range(req_addr, req_size, read_buffer);
tx_buffer[0] = crc & 0xff; tx_buffer[0] = crc & 0xff;
@@ -205,8 +251,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
} }
usbMsgPtr = data_buffer; usbMsgPtr = data_buffer;
return ret_len; /* default for not implemented requests: return return ret_len; /* default for not implemented requests: return no data back to host */
* no data back to host */
} }
@@ -214,121 +259,155 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
void test_read_write(){
uint8_t i; void usb_connect()
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 1;
while (addr++ <= 0x0000ff){
sram_write(addr,i++);
}
addr = 0x000000;
while (addr++ <= 0x0000ff){
printf("read addr=0x%08lx %x\n",addr,sram_read(addr));
}
}
void test_bulk_read_write(){
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 0;
sram_bulk_write_start(addr);
while (addr++ <= 0x3fffff){
sram_bulk_write(i++);
sram_bulk_write_next();
}
sram_bulk_write_end();
addr = 0x000000;
sram_bulk_read_start(addr);
while (addr <= 0x3fffff){
printf("addr=0x%08lx %x\n",addr,sram_bulk_read());
sram_bulk_read_next();
addr ++;
}
sram_bulk_read_end();
}
void test_non_zero_memory(uint32_t bottom_addr,uint32_t top_addr)
{ {
uint32_t addr = 0; uint8_t i = 0;
uint8_t c; info("USB init\n");
sram_bulk_read_start(bottom_addr); usbDeviceDisconnect(); /* enforce re-enumeration, do this while */
for (addr = bottom_addr; addr < top_addr; addr++) {
c = sram_bulk_read();
if (c!=0xff)
printf("addr=0x%08lx c=0x%x\n",addr,c);
sram_bulk_read_next();
}
sram_bulk_read_end();
}
void test_crc(){
printf("test_crc: clear\n");
avr_bus_active();
sram_bulk_set(0x000000,0x10000,0xff);
printf("test_crc: crc\n");
crc_check_bulk_memory(0x000000,0x10000);
printf("test_crc: check\n");
test_non_zero_memory(0x000000,0x10000);
}
int main(void)
{
uint8_t i;
uart_init();
stdout = &uart_stdout;
system_init();
printf("Sytem Init\n");
avr_bus_active();
usbInit();
printf("USB Init\n");
usbDeviceDisconnect(); /* enforce re-enumeration, do this while
* interrupts are disabled! */
cli(); cli();
printf("USB disconnect\n"); info("USB disconnect\n");
i = 10; i = 10;
while (--i) { /* fake USB disconnect for > 250 ms */ while (--i) { /* fake USB disconnect for > 250 ms */
led_on(); led_on();
_delay_ms(35); _delay_ms(35);
led_off(); led_off();
_delay_ms(65); _delay_ms(65);
} }
led_on(); led_on();
usbDeviceConnect(); usbDeviceConnect();
printf("USB connect\n"); info("USB connect\n");
}
void boot_startup_rom()
{
info("Activate AVR bus\n");
avr_bus_active();
info("IRQ off\n");
snes_irq_lo();
snes_irq_off();
snes_lorom();
info("Set Snes lowrom \n");
rle_decode(&_rom, ROM_BUFFER_SIZE, 0x000000);
dump_memory(0x10000 - 0x100, 0x10000);
snes_reset_hi();
snes_reset_off();
snes_irq_lo();
snes_irq_off();
info("IRQ off\n");
snes_hirom();
snes_wr_disable();
info("Disable snes WR\n");
snes_bus_active();
info("Activate Snes bus\n");
_delay_ms(20);
send_reset();
_delay_ms(200);
}
int main(void)
{
uart_init();
stdout = &uart_stdout;
info("Sytem start\n");
system_init();
#if 1
avr_bus_active();
info("Activate AVR bus\n");
info("IRQ off\n");
snes_irq_lo();
snes_irq_off();
info("Set Snes lowrom\n");
snes_lorom();
info("Disable snes WR\n");
snes_wr_disable();
test_sdcard();
#endif
info("Boot startup rom\n");
boot_startup_rom();
usbInit();
usb_connect();
while (1) {
avr_bus_active();
info("Activate AVR bus\n");
info("IRQ off\n");
snes_irq_lo();
snes_irq_off();
info("Set Snes lowrom\n");
snes_lorom();
info("Disable snes WR\n");
snes_wr_disable();
sei(); sei();
printf("USB poll\n"); info("USB poll\n");
while (req_state != REQ_STATUS_BOOT){ while (req_state != REQ_STATUS_SNES) {
usbPoll(); usbPoll();
} }
printf("USB poll done\n"); shared_memory_write(SHARED_MEM_TX_CMD_TERMINATE, 0);
usbDeviceDisconnect(); info("USB poll done\n");
printf("USB disconnect\n"); set_rom_mode();
crc_check_bulk_memory(0x000000,0x1000);
printf("Disable snes WR\n");
snes_wr_disable(); snes_wr_disable();
printf("Use Snes lowrom\n"); info("Disable snes WR\n");
snes_lorom();
printf("Activate Snes bus\n");
snes_bus_active(); snes_bus_active();
info("Activate Snes bus\n");
_delay_ms(100);
send_reset();
info("Poll\n");
while (req_state != REQ_STATUS_AVR) {
usbPoll();
while(1); #ifdef DO_IRQ
return 0; uint8_t i;
uint16_t irq_count = 0;
i = 10;
while (--i) {
_delay_ms(100);
}
info("Send IRQ %i\n", ++irq_count);
send_irq();
#endif
#ifdef DO_BUS_STEALING
avr_bus_active();
sram_bulk_read_start(0x003000);
c = sram_bulk_read();
i = 5;
while (--i) {
_delay_ms(500);
info("Wait to switch to snes mode %i\n", i);
} }
if (req_bank_size == 0x8000) {
snes_lorom();
info("Set Snes lowrom \n");
} else {
snes_hirom();
info("Set Snes hirom \n");
}
snes_wr_disable();
info("Disable snes WR\n");
snes_bus_active();
info("Activate Snes bus\n");
info("Read 0x3000=%c\n", c);
#endif
}
info("Boot startup rom\n");
boot_startup_rom();
}
return 0;
}

220
avr/usbload/mmc.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* ####################################################################################### Connect AVR to MMC/SD
*
* Copyright (C) 2004 Ulrich Radig
*
* Bei Fragen und Verbesserungen wendet euch per EMail an
*
* mail@ulrichradig.de
*
* oder im Forum meiner Web Page : www.ulrichradig.de
*
* Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software
* Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder (nach Ihrer Option) jeder
* späteren Version.
*
* Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
* sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU
* General Public License.
*
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem Programm erhalten haben. Falls nicht, schreiben Sie an die
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
* #######################################################################################
*/
#include <avr/io.h>
#include <util/delay.h>
#include "mmc.h"
uint8_t mmc_init()
{
uint16_t Timeout = 0, i;
MMC_REG |= ((1 << MMC_DO) | (1 << MMC_CS) | (1 << MMC_CLK));
MMC_REG &= ~(1 << MMC_DI);
MMC_WRITE |= ((1 << MMC_DO) | (1 << MMC_DI) | (1 << MMC_CS));
_delay_ms(20);
for (i = 0; i < 250; i++) {
MMC_WRITE ^= (1 << MMC_CLK);
_delay_us(4);
}
MMC_WRITE &= ~(1 << MMC_CLK);
_delay_us(10);
MMC_WRITE &= ~(1 << MMC_CS);
_delay_us(3);
uint8_t CMD[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x95 };
while (mmc_write_command(CMD) != 1) {
if (Timeout++ > 20) {
mmc_disable();
return (1);
}
}
Timeout = 0;
CMD[0] = 0x41;
CMD[5] = 0xFF;
while (mmc_write_command(CMD) != 0) {
if (Timeout++ > 800) {
mmc_disable();
return (9);
}
}
return (0);
}
uint8_t mmc_write_command(uint8_t * cmd)
{
uint8_t tmp = 0xff;
uint16_t Timeout = 0;
uint8_t a;
for (a = 0; a < 0x06; a++) {
mmc_write_byte(*cmd++);
}
while (tmp == 0xff) {
tmp = mmc_read_byte();
if (Timeout++ > 50) {
break;
}
}
return (tmp);
}
uint8_t mmc_read_byte(void)
{
uint8_t Byte = 0, j;
for (j = 0; j < 8; j++) {
Byte = (Byte << 1);
MMC_WRITE |= (1 << MMC_CLK);
_delay_us(4);
if (PINB & (1 << MMC_DI)) {
Byte |= 1;
}
else {
Byte &= ~1;
}
MMC_WRITE &= ~(1 << MMC_CLK);
_delay_us(4);
}
return (Byte);
}
void mmc_write_byte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (Byte & 0x80) {
MMC_WRITE |= (1 << MMC_DO);
}
else {
MMC_WRITE &= ~(1 << MMC_DO);
}
Byte = (Byte << 1);
MMC_WRITE |= (1 << MMC_CLK);
_delay_us(4);
MMC_WRITE &= ~(1 << MMC_CLK);
_delay_us(4);
}
MMC_WRITE |= (1 << MMC_DO);
}
uint8_t mmc_write_sector(uint32_t addr, uint8_t * Buffer)
{
uint8_t tmp;
uint8_t cmd[] = { 0x58, 0x00, 0x00, 0x00, 0x00, 0xFF };
uint8_t a;
uint16_t i;
addr = addr << 9;
cmd[1] = ((addr & 0xFF000000) >> 24);
cmd[2] = ((addr & 0x00FF0000) >> 16);
cmd[3] = ((addr & 0x0000FF00) >> 8);
tmp = mmc_write_command(cmd);
if (tmp != 0) {
return (tmp);
}
for (a = 0; a < 100; a++) {
mmc_read_byte();
}
mmc_write_byte(0xFE);
for (a = 0; i < 512; i++) {
mmc_write_byte(*Buffer++);
}
mmc_write_byte(0xFF);
mmc_write_byte(0xFF);
if ((mmc_read_byte() & 0x1F) != 0x05)
return (1);
while (mmc_read_byte() != 0xff) {
};
return (0);
}
void mmc_read_block(uint8_t * cmd, uint8_t * Buffer, uint16_t Bytes)
{
uint16_t a;
if (mmc_write_command(cmd) != 0) {
return;
}
while (mmc_read_byte() != 0xfe) {
};
for (a = 0; a < Bytes; a++) {
*Buffer++ = mmc_read_byte();
}
mmc_read_byte();
mmc_read_byte();
return;
}
uint8_t mmc_read_sector(uint32_t addr, uint8_t * Buffer)
{
uint8_t cmd[] = { 0x51, 0x00, 0x00, 0x00, 0x00, 0xFF };
addr = addr << 9;
cmd[1] = ((addr & 0xFF000000) >> 24);
cmd[2] = ((addr & 0x00FF0000) >> 16);
cmd[3] = ((addr & 0x0000FF00) >> 8);
mmc_read_block(cmd, Buffer, 512);
return (0);
}
uint8_t mmc_read_cid(uint8_t * Buffer)
{
uint8_t cmd[] = { 0x4A, 0x00, 0x00, 0x00, 0x00, 0xFF };
mmc_read_block(cmd, Buffer, 16);
return (0);
}
uint8_t mmc_read_csd(uint8_t * Buffer)
{
uint8_t cmd[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0xFF };
mmc_read_block(cmd, Buffer, 16);
return (0);
}

44
avr/usbload/mmc.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* ####################################################################################### Connect ARM to MMC/SD
*
* Copyright (C) 2004 Ulrich Radig #######################################################################################
*/
#ifndef _MMC_H
#define _MMC_H
#define SPI_Mode 0 // 1 = Hardware SPI | 0 = Software SPI
#define MMC_WRITE PORTB
#define MMC_READ PINB
#define MMC_REG DDRB
#define MMC_CS PB4
#define MMC_DO PB6
#define MMC_DI PB5
#define MMC_CLK PB7
#define MMC_WRITE PORTB // Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_READ PINB
#define MMC_REG DDRB
extern uint8_t mmc_read_byte(void);
extern void mmc_write_byte(uint8_t);
extern void mmc_read_block(uint8_t *, uint8_t *, unsigned in);
extern uint8_t mmc_init(void);
extern uint8_t mmc_read_sector(unsigned long, uint8_t *);
extern uint8_t mmc_write_sector(unsigned long, uint8_t *);
extern uint8_t mmc_write_command(uint8_t *);
#define mmc_disable() MMC_WRITE|= (1<<MMC_CS);
#define mmc_enable() MMC_WRITE&=~(1<<MMC_CS);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif

View File

@@ -1,17 +1,23 @@
/* Name: requests.h /*
* Project: custom-class, a basic USB example * =====================================================================================
* Author: Christian Starkjohann *
* Creation Date: 2008-04-09 * ________ .__ __ ________ ____ ________
* Tabsize: 4 * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* This Revision: $Id: requests.h 692 2008-11-07 15:07:40Z cs $ * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/ */
/* This header is shared between the firmware and the host software. It
* defines the USB request numbers (and optionally data types) used to
* communicate between the host and the device.
*/
#ifndef __REQUESTS_H__ #ifndef __REQUESTS_H__
#define __REQUESTS_H__ #define __REQUESTS_H__
@@ -29,6 +35,8 @@
#define USB_BULK_UPLOAD_ADDR 7 #define USB_BULK_UPLOAD_ADDR 7
#define USB_BULK_UPLOAD_NEXT 8 #define USB_BULK_UPLOAD_NEXT 8
#define USB_BULK_UPLOAD_END 9 #define USB_BULK_UPLOAD_END 9
#define USB_SNES_BOOT 10 #define USB_MODE_SNES 10
#define USB_MODE_AVR 11
#define USB_AVR_RESET 12
#endif /* __REQUESTS_H_INCLUDED__ */ #endif /* __REQUESTS_H_INCLUDED__ */

103
avr/usbload/rle.c Normal file
View File

@@ -0,0 +1,103 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <avr/pgmspace.h> /* required by usbdrv.h */
#include <util/delay.h> /* for _delay_ms() */
#include <avr/interrupt.h> /* for sei() */
#include "sram.h"
#include "debug.h"
#include "info.h"
#define RUNCHAR 0x90
uint8_t rle_decode(PGM_VOID_P in_addr, int32_t in_len, uint32_t out_addr)
{
uint8_t in_byte, in_repeat, last_byte;
uint32_t out_len, out_len_left;
info("RLE decode len=%li addr=0x%08lx\n", in_len, out_addr);
last_byte = 0;
out_len_left = out_len;
sram_bulk_write_start(out_addr);
#define INBYTE(b) \
do { \
if ( --in_len < 0 ) { \
return 1; \
} \
cli();\
b = pgm_read_byte((PGM_VOID_P)in_addr++); \
sei();\
} while(0)
#define OUTBYTE(b) \
do { \
sram_bulk_write(b);\
sram_bulk_write_next();\
out_addr++;\
} while(0)
INBYTE(in_byte);
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if (in_repeat != 0) {
info("Orphaned RLE code at start\n");
return 1;
}
OUTBYTE(RUNCHAR);
} else {
OUTBYTE(in_byte);
}
while (in_len > 0) {
INBYTE(in_byte);
if (in_len % 1024 == 0)
info(".");
if (in_byte == RUNCHAR) {
INBYTE(in_repeat);
if (in_repeat == 0) {
/*
* Just an escaped RUNCHAR value
*/
OUTBYTE(RUNCHAR);
} else {
/*
* Pick up value and output a sequence of it
*/
in_byte = last_byte; // ;out_data[-1];
while (--in_repeat > 0)
OUTBYTE(in_byte);
}
} else {
/*
* Normal byte
*/
OUTBYTE(in_byte);
}
last_byte = in_byte;
}
sram_bulk_write_end();
return 0;
}

28
avr/usbload/rle.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __RLE_H__
#define __RLE_H__
#include <avr/pgmspace.h>
uint8_t rle_decode(PGM_VOID_P in_addr, uint32_t in_len, uint32_t out_addr);
#endif

162
avr/usbload/shared_memory.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h>
#include <stdint.h>
#include <util/delay.h>
#include "shared_memory.h"
#include "config.h"
#include "sram.h"
#include "debug.h"
#include "info.h"
uint8_t irq_addr_lo;
uint8_t irq_addr_hi;
uint8_t scratchpad_state;
uint8_t scratchpad_cmd;
uint8_t scratchpad_payload;
void shared_memory_scratchpad_tx_save()
{
scratchpad_state = sram_read(SHARED_MEM_TX_LOC_STATE);
scratchpad_cmd = sram_read(SHARED_MEM_TX_LOC_CMD);
scratchpad_payload = sram_read(SHARED_MEM_TX_LOC_PAYLOAD);
}
void shared_memory_scratchpad_tx_restore()
{
sram_write(SHARED_MEM_TX_LOC_STATE, scratchpad_state);
sram_write(SHARED_MEM_TX_LOC_CMD, scratchpad_cmd);
sram_write(SHARED_MEM_TX_LOC_PAYLOAD, scratchpad_payload);
}
void shared_memory_irq_hook()
{
irq_addr_lo = sram_read(SHARED_IRQ_LOC_LO);
irq_addr_hi = sram_read(SHARED_IRQ_LOC_HI);
sram_write(SHARED_IRQ_HANDLER_LO, 0);
sram_write(SHARED_IRQ_HANDLER_HI, 0);
}
void shared_memory_irq_restore()
{
sram_write(SHARED_IRQ_LOC_LO, irq_addr_lo);
sram_write(SHARED_IRQ_LOC_HI, irq_addr_hi);
}
void shared_memory_write(uint8_t cmd, uint8_t value)
{
debug(DEBUG_SHM,"shared_memory_write: 0x%04x=0x%02x 0x%04x=0x%02x \n",
SHARED_MEM_TX_LOC_CMD, cmd, SHARED_MEM_TX_LOC_PAYLOAD, value);
sram_bulk_addr_save();
shared_memory_scratchpad_tx_save();
shared_memory_irq_hook();
sram_write(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_SNES_ACK);
sram_write(SHARED_MEM_TX_LOC_CMD, cmd);
sram_write(SHARED_MEM_TX_LOC_PAYLOAD, value);
snes_hirom();
snes_wr_disable();
snes_bus_active();
#if SHARED_MEM_SWITCH_IRQ
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
#else
_delay_ms(SHARED_MEM_SWITCH_DELAY);
#endif
avr_bus_active();
snes_irq_lo();
snes_irq_off();
snes_lorom();
snes_wr_disable();
shared_memory_scratchpad_tx_restore();
shared_memory_irq_restore();
sram_bulk_addr_restore();
}
void shared_memory_yield()
{
snes_hirom();
snes_wr_disable();
snes_bus_active();
_delay_ms(SHARED_MEM_SWITCH_DELAY);
avr_bus_active();
snes_lorom();
snes_wr_disable();
}
int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer)
{
uint8_t state;
state = sram_read(SHARED_MEM_RX_LOC_STATE);
if (state != SHARED_MEM_RX_AVR_ACK){
return 1;
}
sram_bulk_addr_save();
*cmd = sram_read(SHARED_MEM_RX_LOC_CMD);
*len = sram_read(SHARED_MEM_RX_LOC_LEN);
debug(DEBUG_SHM,"shared_memory_read: 0x%04x=0x%02x 0x%04x=0x%02x \n",
SHARED_MEM_RX_LOC_CMD, *cmd, SHARED_MEM_RX_LOC_LEN, *len);
sram_bulk_read_buffer(SHARED_MEM_RX_LOC_PAYLOAD,buffer, *len);
sram_write(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_AVR_RTS);
snes_hirom();
snes_wr_disable();
snes_bus_active();
#if SHARED_MEM_SWITCH_IRQ
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
#else
_delay_ms(SHARED_MEM_SWITCH_DELAY);
#endif
avr_bus_active();
snes_lorom();
snes_wr_disable();
sram_bulk_addr_restore();
return 0;
}

View File

@@ -0,0 +1,66 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __SHARED_MEMORY_H__
#define __SHARED_MEMORY_H__
#define SHARED_MEM_SWITCH_IRQ 0
#define SHARED_MEM_SWITCH_DELAY 20
#define SHARED_MEM_TX_SNES_ACK 0xa5
#define SHARED_MEM_TX_SNES_RTS 0x5a
#define SHARED_MEM_TX_CMD_BANK_COUNT 0x00
#define SHARED_MEM_TX_CMD_BANK_CURRENT 0x01
#define SHARED_MEM_TX_CMD_UPLOAD_START 0x03
#define SHARED_MEM_TX_CMD_UPLOAD_END 0x04
#define SHARED_MEM_TX_CMD_UPLOAD_PROGESS 0x05
#define SHARED_MEM_TX_CMD_TERMINATE 0x06
#define SHARED_MEM_TX_LOC_STATE 0x000000
#define SHARED_MEM_TX_LOC_CMD 0x000001
#define SHARED_MEM_TX_LOC_PAYLOAD 0x000002
#define SHARED_MEM_RX_AVR_ACK 0xa5
#define SHARED_MEM_RX_AVR_RTS 0x5a
#define SHARED_MEM_RX_CMD_PRINFT 0x00
#define SHARED_MEM_RX_CMD_FILESEL 0x01
#define SHARED_MEM_RX_LOC_STATE 0x001000
#define SHARED_MEM_RX_LOC_CMD 0x001001
#define SHARED_MEM_RX_LOC_LEN 0x001002
#define SHARED_MEM_RX_LOC_PAYLOAD 0x001003
#define SHARED_IRQ_LOC_LO 0x00fffe
#define SHARED_IRQ_LOC_HI 0x00ffff
/* Use COP IRQ LOC for hooked IRQ handler */
#define SHARED_IRQ_HANDLER_LO 0x0ffe4
#define SHARED_IRQ_HANDLER_HI 0x0ffe5
void shared_memory_write(uint8_t cmd, uint8_t value);
int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer);
#endif

View File

@@ -1,13 +1,38 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> /* for _delay_ms() */ #include <util/delay.h>
#include "config.h" #include "config.h"
#include "sram.h" #include "sram.h"
#include "uart.h" #include "uart.h"
#include "debug.h" #include "debug.h"
#include "info.h"
uint32_t addr_current = 0;
uint32_t addr_stash = 0;
void system_init(void) void system_init(void)
{ {
@@ -28,13 +53,15 @@ void system_init(void)
DDRC &= ~ (1 << SNES_WR_PIN); DDRC &= ~ (1 << SNES_WR_PIN);
PORTC &= ~((1 << AVR_ADDR_LATCH_PIN) PORTC &= ~((1 << AVR_ADDR_LATCH_PIN)
| (1 << AVR_ADDR_SCK_PIN)); | (1 << AVR_ADDR_SCK_PIN)
| (1 << SNES_WR_PIN));
PORTC |= ( (1 << AVR_ADDR_DOWN_PIN) PORTC |= ( (1 << AVR_ADDR_DOWN_PIN)
| (1 << AVR_ADDR_UP_PIN) | (1 << AVR_ADDR_UP_PIN)
| (1 << AVR_ADDR_LOAD_PIN) | (1 << AVR_ADDR_LOAD_PIN));
| (1 << SNES_WR_PIN));
//| (1 << SNES_WR_PIN));
/*-------------------------------------------------*/ /*-------------------------------------------------*/
DDRB |= ( (1 << AVR_RD_PIN) DDRB |= ( (1 << AVR_RD_PIN)
@@ -42,10 +69,12 @@ void system_init(void)
| (1 << AVR_CS_PIN) | (1 << AVR_CS_PIN)
| (1 << SNES_IRQ_PIN)); | (1 << SNES_IRQ_PIN));
PORTB |= ( (1 << AVR_RD_PIN) PORTB |= ( (1 << AVR_RD_PIN)
| (1 << AVR_WR_PIN) | (1 << AVR_WR_PIN)
| (1 << AVR_CS_PIN) | (1 << AVR_CS_PIN)
| (1 << SNES_IRQ_PIN)); | (1 << SNES_IRQ_PIN));
/*-------------------------------------------------*/ /*-------------------------------------------------*/
@@ -67,19 +96,19 @@ void system_init(void)
void sreg_set(uint32_t addr) void sreg_set(uint32_t addr)
{ {
uint8_t i = 24; uint8_t i = 24;
debug(DEBUG_SREG,"sreg_set: addr=0x%08lx",addr); debug(DEBUG_SRAM,"sreg_set: addr=0x%08lx\n",addr);
while(i--) { while(i--) {
if ((addr & ( 1L << i))){ if ((addr & ( 1L << i))){
debug(DEBUG_SREG,"1"); debug(DEBUG_SRAM,"1");
AVR_ADDR_SER_PORT |= ( 1 << AVR_ADDR_SER_PIN); AVR_ADDR_SER_PORT |= ( 1 << AVR_ADDR_SER_PIN);
} else { } else {
AVR_ADDR_SER_PORT &= ~( 1 << AVR_ADDR_SER_PIN); AVR_ADDR_SER_PORT &= ~( 1 << AVR_ADDR_SER_PIN);
debug(DEBUG_SREG,"0"); debug(DEBUG_SRAM,"0");
} }
AVR_ADDR_SCK_PORT |= (1 << AVR_ADDR_SCK_PIN); AVR_ADDR_SCK_PORT |= (1 << AVR_ADDR_SCK_PIN);
AVR_ADDR_SCK_PORT &= ~(1 << AVR_ADDR_SCK_PIN); AVR_ADDR_SCK_PORT &= ~(1 << AVR_ADDR_SCK_PIN);
} }
debug(DEBUG_SREG,"\n"); debug(DEBUG_SRAM,"\n");
AVR_ADDR_LATCH_PORT |= (1 << AVR_ADDR_LATCH_PIN); AVR_ADDR_LATCH_PORT |= (1 << AVR_ADDR_LATCH_PIN);
AVR_ADDR_LATCH_PORT &= ~(1 << AVR_ADDR_LATCH_PIN); AVR_ADDR_LATCH_PORT &= ~(1 << AVR_ADDR_LATCH_PIN);
@@ -87,11 +116,23 @@ void sreg_set(uint32_t addr)
} }
inline void sram_bulk_addr_save()
{
addr_stash = addr_current;
}
inline void sram_bulk_addr_restore()
{
sreg_set(addr_stash);
}
void sram_bulk_read_start(uint32_t addr) void sram_bulk_read_start(uint32_t addr)
{ {
debug(DEBUG_SRAM,"sram_bulk_read_start: addr=0x%08lx\n\r", addr); debug(DEBUG_SRAM,"sram_bulk_read_start: addr=0x%08lx\n\r", addr);
addr_current = addr;
avr_data_in(); avr_data_in();
AVR_CS_PORT &= ~(1 << AVR_CS_PIN); AVR_CS_PORT &= ~(1 << AVR_CS_PIN);
@@ -107,10 +148,12 @@ void sram_bulk_read_start(uint32_t addr)
asm volatile ("nop"); asm volatile ("nop");
asm volatile ("nop"); asm volatile ("nop");
asm volatile ("nop"); asm volatile ("nop");
} }
inline void sram_bulk_read_next(void) inline void sram_bulk_read_next(void)
{ {
addr_current++;
AVR_RD_PORT |= (1 << AVR_RD_PIN); AVR_RD_PORT |= (1 << AVR_RD_PIN);
counter_up(); counter_up();
AVR_RD_PORT &= ~(1 << AVR_RD_PIN); AVR_RD_PORT &= ~(1 << AVR_RD_PIN);
@@ -121,6 +164,7 @@ inline void sram_bulk_read_next(void)
asm volatile ("nop"); asm volatile ("nop");
asm volatile ("nop"); asm volatile ("nop");
asm volatile ("nop"); asm volatile ("nop");
} }
@@ -131,7 +175,7 @@ inline uint8_t sram_bulk_read(void)
void sram_bulk_read_end(void) void sram_bulk_read_end(void)
{ {
debug(DEBUG_SRAM,"sram_bulk_read_end:"); debug(DEBUG_SRAM,"sram_bulk_read_end:\n");
AVR_RD_PORT |= (1 << AVR_RD_PIN); AVR_RD_PORT |= (1 << AVR_RD_PIN);
AVR_CS_PORT |= (1 << AVR_CS_PIN); AVR_CS_PORT |= (1 << AVR_CS_PIN);
@@ -184,11 +228,12 @@ void sram_bulk_write_start(uint32_t addr)
sreg_set(addr); sreg_set(addr);
AVR_WR_PORT &= ~(1 << AVR_WR_PIN); AVR_WR_PORT &= ~(1 << AVR_WR_PIN);
} }
inline void sram_bulk_write_next(void) inline void sram_bulk_write_next(void)
{ {
AVR_RD_PORT |= (1 << AVR_RD_PIN); AVR_WR_PORT |= (1 << AVR_WR_PIN);
counter_up(); counter_up();
AVR_WR_PORT &= ~(1 << AVR_WR_PIN); AVR_WR_PORT &= ~(1 << AVR_WR_PIN);
} }
@@ -220,9 +265,18 @@ void sram_write(uint32_t addr, uint8_t data)
sreg_set(addr); sreg_set(addr);
AVR_WR_PORT &= ~(1 << AVR_WR_PIN); AVR_WR_PORT &= ~(1 << AVR_WR_PIN);
AVR_DATA_PORT = data; AVR_DATA_PORT = data;
AVR_WR_PORT |= (1 << AVR_WR_PIN); AVR_WR_PORT |= (1 << AVR_WR_PIN);
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
AVR_CS_PORT |= (1 << AVR_CS_PIN); AVR_CS_PORT |= (1 << AVR_CS_PIN);
avr_data_in(); avr_data_in();
@@ -271,48 +325,3 @@ void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value){
sram_bulk_write_end(); sram_bulk_write_end();
} }
void sram_setr(uint32_t addr, uint32_t len,uint8_t value)
{
uint32_t i;
debug(DEBUG_SRAM,"sram_clear: addr=0x%08lx len=%li\n\r", addr,len);
for (i = addr; i < (addr + len); i++) {
if (0 == i % 0xfff)
debug(DEBUG_SRAM,"sram_clear: addr=0x%08lx\n\r", i);
sram_write(i, value);
}
}
void sram_copy(uint32_t addr, uint8_t * src, uint32_t len)
{
uint32_t i;
uint8_t *ptr = src;
debug(DEBUG_SRAM,"sram_copy: addr=0x%08lx src=0x%p len=%li\n\r", addr,src,len);
for (i = addr; i < (addr + len); i++)
sram_write(i, *ptr++);
}
void sram_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len)
{
uint32_t i;
uint8_t *ptr = dst;
debug(DEBUG_SRAM,"sram_read_buffer: addr=0x%08lx dst=0x%p len=%li\n\r", addr,dst,len);
for (i = addr; i < (addr + len); i++) {
*ptr = sram_read(i);
ptr++;
}
}
uint8_t sram_check(uint8_t * buffer, uint32_t len)
{
uint16_t cnt;
debug(DEBUG_SRAM,"sram_check: len=%li\n\r",len);
for (cnt = 0; cnt < len; cnt++)
if (buffer[cnt])
return 1;
return 0;
}

View File

@@ -1,3 +1,25 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __SRAM_H__ #ifndef __SRAM_H__
#define __SRAM_H__ #define __SRAM_H__
@@ -56,9 +78,23 @@
#define SNES_IRQ_DIR DDRB #define SNES_IRQ_DIR DDRB
#define SNES_IRQ_PIN PB3 #define SNES_IRQ_PIN PB3
#define snes_irq_off() (SNES_IRQ_PORT |= (1 << SNES_IRQ_PIN))
#define snes_irq_on() (SNES_IRQ_PORT &= ~(1 << SNES_IRQ_PIN))
#define snes_irq_on() (SNES_IRQ_DIR |= (1 << SNES_IRQ_PIN))
#define snes_irq_hi() (SNES_IRQ_PORT |= (1 << SNES_IRQ_PIN))
#define snes_irq_off() (SNES_IRQ_DIR &= ~(1 << SNES_IRQ_PIN))
#define snes_irq_lo() (SNES_IRQ_PORT &= ~(1 << SNES_IRQ_PIN))
#define SNES_RESET_PORT PORTB
#define SNES_RESET_DIR DDRB
#define SNES_RESET_PIN PB4
#define snes_reset_on() (SNES_RESET_DIR |= (1 << SNES_RESET_PIN))
#define snes_reset_hi() (SNES_RESET_PORT |= (1 << SNES_RESET_PIN))
#define snes_reset_off() (SNES_RESET_DIR &= ~(1 << SNES_RESET_PIN))
#define snes_reset_lo() (SNES_RESET_PORT &= ~(1 << SNES_RESET_PIN))
/* ---------------------------- PORT C ---------------------------- */ /* ---------------------------- PORT C ---------------------------- */
@@ -120,9 +156,11 @@
#define AVR_SNES_SW_PIN PD5 #define AVR_SNES_SW_PIN PD5
#define avr_bus_active() ((AVR_SNES_SW_PORT &= ~(1 << AVR_SNES_SW_PIN)),\ #define avr_bus_active() ((AVR_SNES_SW_PORT &= ~(1 << AVR_SNES_SW_PIN)),\
(HI_LOROM_SW_PORT |= (1 << HI_LOROM_SW_PIN))) (HI_LOROM_SW_PORT |= (1 << HI_LOROM_SW_PIN)),\
(AVR_CS_DIR |= (1 << AVR_CS_PIN)))
#define snes_bus_active() (AVR_SNES_SW_PORT |= (1 << AVR_SNES_SW_PIN)) #define snes_bus_active() ((AVR_SNES_SW_PORT |= (1 << AVR_SNES_SW_PIN)),\
(AVR_CS_DIR &= ~(1 << AVR_CS_PIN)))
#define HI_LOROM_SW_PORT PORTD #define HI_LOROM_SW_PORT PORTD
#define HI_LOROM_SW_DIR DDRD #define HI_LOROM_SW_DIR DDRD
@@ -136,6 +174,7 @@
#define SNES_WR_EN_PIN PD7 #define SNES_WR_EN_PIN PD7
#define snes_wr_disable() (SNES_WR_EN_PORT &= ~(1 << SNES_WR_EN_PIN)) #define snes_wr_disable() (SNES_WR_EN_PORT &= ~(1 << SNES_WR_EN_PIN))
#define snes_wr_enable() (SNES_WR_EN_PORT |= (1 << SNES_WR_EN_PIN)) #define snes_wr_enable() (SNES_WR_EN_PORT |= (1 << SNES_WR_EN_PIN))
@@ -147,9 +186,6 @@ void sreg_set(uint32_t addr);
uint8_t sram_read(uint32_t addr); uint8_t sram_read(uint32_t addr);
void sram_write(uint32_t addr, uint8_t data); void sram_write(uint32_t addr, uint8_t data);
void sram_set(uint32_t addr, uint32_t len, uint8_t value);
void sram_copy(uint32_t addr,uint8_t *src, uint32_t len);
void sram_read_buffer(uint32_t addr,uint8_t *dst, uint32_t len);
void sram_bulk_read_start(uint32_t addr); void sram_bulk_read_start(uint32_t addr);
inline void sram_bulk_read_next(void); inline void sram_bulk_read_next(void);
@@ -165,4 +201,9 @@ void sram_bulk_copy(uint32_t addr, uint8_t * src, uint32_t len);
void sram_bulk_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len); void sram_bulk_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len);
void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value); void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value);
inline void sram_bulk_addr_save();
inline void sram_bulk_addr_restore();
#endif #endif

156
avr/usbload/testing.c Normal file
View File

@@ -0,0 +1,156 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <util/delay.h>
#include "shared_memory.h"
#include "config.h"
#include "sram.h"
#include "debug.h"
#include "crc.h"
#include "config.h"
#include "info.h"
#include "mmc.h"
#include "fat.h"
#include "file.h"
#include "dir.h"
void test_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 1;
while (addr++ <= 0x0000ff) {
sram_write(addr, i++);
}
addr = 0x000000;
while (addr++ <= 0x0000ff) {
info("read addr=0x%08lx %x\n", addr, sram_read(addr));
}
}
void test_bulk_read_write()
{
uint8_t i;
uint32_t addr;
avr_bus_active();
addr = 0x000000;
i = 0;
sram_bulk_write_start(addr);
while (addr++ <= 0x8000) {
sram_bulk_write(i++);
sram_bulk_write_next();
}
sram_bulk_write_end();
addr = 0x000000;
sram_bulk_read_start(addr);
while (addr <= 0x8000) {
info("addr=0x%08lx %x\n", addr, sram_bulk_read());
sram_bulk_read_next();
addr++;
}
sram_bulk_read_end();
}
void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr)
{
uint32_t addr = 0;
uint8_t c;
sram_bulk_read_start(bottom_addr);
for (addr = bottom_addr; addr < top_addr; addr++) {
c = sram_bulk_read();
if (c != 0xff)
info("addr=0x%08lx c=0x%x\n", addr, c);
sram_bulk_read_next();
}
sram_bulk_read_end();
}
void test_crc()
{
info("test_crc: clear\n");
avr_bus_active();
sram_bulk_set(0x000000, 0x10000, 0xff);
info("test_crc: crc\n");
crc_check_bulk_memory(0x000000, 0x10000, 0x8000);
info("test_crc: check\n");
test_non_zero_memory(0x000000, 0x10000);
}
void test_sdcard(void){
while (mmc_init() !=0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
printf("no sdcard\n");
}
if (fat_initfat()==0){
printf("fatinit ok\n");
} else {
printf("fatinit failed\n");
return;
}
printf("Root dirlist\n");
ffls_smc();
dump_memory(DIR_ENTRY_LOC , DIR_ENTRY_LOC + (64 * 2));
dir_entry_loop();
while(1);
#if (WRITE==1)
char datei[12]="test.txt"; // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !!
fat_str(datei);
ffrm( datei ); // löschen der datei/ordner falls vorhanden
printf("open %s\n",datei);
ffopen( datei );
printf("write %s\n",datei);
ffwrites((char*)"Hallo Datei :)");
ffwrite(0x0D);
ffwrite(0x0A);
printf("close %s\n",datei);
ffclose();
printf("open %s\n",datei);
ffopen( datei );
printf("open %s\n",datei);
unsigned long int seek=file.length; // eine variable setzen und runterzählen bis 0 geht am schnellsten !
do{
printf("%c",ffread()); // liest ein zeichen und gibt es über uart aus !
}while(--seek); // liest solange bytes da sind (von datei länge bis 0)
ffclose(); // schließt datei
#endif
}

32
avr/usbload/testing.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __TESTING_H__
#define __TESTING_H__
void test_read_write();
void test_bulk_read_write();
void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr);
void test_crc();
void test_sdcard();
#endif

89
avr/usbload/timer.c Normal file
View File

@@ -0,0 +1,89 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/io.h>
#include <avr/interrupt.h> /* for sei() */
#include "debug.h"
#include "info.h"
#ifndef OCR1A
#define OCR1A OCR1 // 2313 support
#endif
#ifndef WGM12
#define WGM12 CTC1 // 2313 support
#endif
//#define XTAL 11059201L // nominal value
#define XTAL 20000000UL
#define DEBOUNCE 500L // debounce clock (256Hz = 4msec)
#define uint8_t unsigned char
#define uint unsigned int
uint16_t prescaler;
uint16_t volatile second; // count seconds
ISR (SIG_OUTPUT_COMPARE1A)
{
#if XTAL % DEBOUNCE // bei rest
OCR1A = 20000000UL / DEBOUNCE - 1; // compare DEBOUNCE - 1 times
#endif
if( --prescaler == 0 ){
prescaler = (uint16_t)DEBOUNCE;
second++; // exact one second over
#if XTAL % DEBOUNCE // handle remainder
OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1; // compare once per second
#endif
}
}
void timer_start( void )
{
TCCR1B = (1<<WGM12) | (1<<CS10); // divide by 1
// clear on compare
OCR1A = XTAL / DEBOUNCE - 1UL; // Output Compare Register
TCNT1 = 0; // Timmer startet mit 0
second = 0;
prescaler = (uint16_t)DEBOUNCE; //software teiler
TIMSK1 = 1<<OCIE1A; // beim Vergleichswertes Compare Match
// Interrupt (SIG_OUTPUT_COMPARE1A)
sei();
}
uint16_t timer_stop_int(void)
{
uint16_t t = ((DEBOUNCE - prescaler) / DEBOUNCE ) + second;
return t;
}

29
avr/usbload/timer.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __TIMER_H__
#define __TIMER_H__
int16_t timer_start( void );
double timer_stop( void );
int16_t timer_stop_int( void );
#endif

View File

@@ -1,3 +1,23 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>

View File

@@ -1,3 +1,24 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __UART_H__ #ifndef __UART_H__
#define __UART_H__ #define __UART_H__
@@ -16,3 +37,4 @@ static int uart_stream(char c, FILE *stream);
#endif #endif

View File

@@ -1,3 +1,23 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/io.h> #include <avr/io.h>
#include <avr/pgmspace.h> /* required by usbdrv.h */ #include <avr/pgmspace.h> /* required by usbdrv.h */
@@ -14,6 +34,8 @@
#include "uart.h" #include "uart.h"
#include "sram.h" #include "sram.h"
#include "debug.h" #include "debug.h"
#include "info.h"
#include "crc.h" #include "crc.h"
#include "usb_bulk.h" #include "usb_bulk.h"
@@ -32,19 +54,13 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
{ {
uint8_t *ptr; uint8_t *ptr;
uint8_t i; uint8_t i;
if (len > rx_remaining) { if (len > rx_remaining) {
printf("ERROR:usbFunctionWrite more data than expected remain: %i len: %i\n", info("ERROR:usbFunctionWrite more data than expected remain: %i len: %i\n",
rx_remaining, len); rx_remaining, len);
len = rx_remaining; len = rx_remaining;
} }
if (req_state == REQ_STATUS_UPLOAD) { if (req_state == REQ_STATUS_BULK_UPLOAD) {
rx_remaining -= len;
debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n",
req_addr, len, rx_remaining);
sram_copy(req_addr, data, len);
req_addr += len;
} else if (req_state == REQ_STATUS_BULK_UPLOAD) {
rx_remaining -= len; rx_remaining -= len;
debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_BULK_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n", debug(DEBUG_USB_TRANS,"usbFunctionWrite REQ_STATUS_BULK_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n",
@@ -53,9 +69,11 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
i = len; i = len;
while(i--){ while(i--){
sram_bulk_write(*ptr++); sram_bulk_write(*ptr++);
counter_up(); sram_bulk_write_next();
} }
} }
/* test this */
//return rx_remaining == 0
return len; return len;
} }

View File

@@ -1,4 +1,29 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#ifndef __USB_BULK_H__
#define __USB_BULK_H__
uint8_t usbFunctionWrite(uint8_t * data, uint8_t len); uint8_t usbFunctionWrite(uint8_t * data, uint8_t len);
uint8_t usbFunctionRead(uint8_t * data, uint8_t len); uint8_t usbFunctionRead(uint8_t * data, uint8_t len);
#endif

View File

@@ -1,3 +1,25 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
/* Name: usbconfig.h /* Name: usbconfig.h
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann * Author: Christian Starkjohann
@@ -105,7 +127,7 @@ section at the end of this file).
* (e.g. HID), but never want to send any data. This option saves a couple * (e.g. HID), but never want to send any data. This option saves a couple
* of bytes in flash memory and the transmit buffers in RAM. * of bytes in flash memory and the transmit buffers in RAM.
*/ */
#define USB_CFG_INTR_POLL_INTERVAL 10 #define USB_CFG_INTR_POLL_INTERVAL 200
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll /* If you compile a version with endpoint 1 (interrupt-in), this is the poll
* interval. The value is in milliseconds and must not be less than 10 ms for * interval. The value is in milliseconds and must not be less than 10 ms for
* low speed devices. * low speed devices.
@@ -141,7 +163,7 @@ section at the end of this file).
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in * of the macros usbDisableAllRequests() and usbEnableAllRequests() in
* usbdrv.h. * usbdrv.h.
*/ */
#define USB_CFG_LONG_TRANSFERS 1 #define USB_CFG_LONG_TRANSFERS 0
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes /* Define this to 1 if you want to send/receive blocks of more than 254 bytes
* in a single control-in or control-out transfer. Note that the capability * in a single control-in or control-out transfer. Note that the capability
* for long transfers increases the driver size. * for long transfers increases the driver size.

31
avr/usbload/watchdog.c Normal file
View File

@@ -0,0 +1,31 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include "watchdog.h"
void wdt_init(void)
{
MCUSR = 0;
wdt_disable();
return;
}

42
avr/usbload/watchdog.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* =====================================================================================
*
* ________ .__ __ ________ ____ ________
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
* \__> \/ \/ \/ \/ \/
*
* www.optixx.org
*
*
* Version: 1.0
* Created: 07/21/2009 03:32:16 PM
* Author: david@optixx.org
*
* =====================================================================================
*/
#include <avr/wdt.h>
#ifndef __WATCHDOG_H__
#define __WATCHDOG_H__
void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
#define soft_reset() \
do \
{ \
wdt_enable(WDTO_500MS );\
for(;;) \
{ \
} \
} while(0)
#endif

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More