Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac85195bb8 | ||
|
|
92762d7f51 | ||
|
|
3e3fbe5bc4 | ||
|
|
570323f017 | ||
|
|
d1447db7b0 | ||
|
|
1b45c2f325 | ||
|
|
1539ff6111 | ||
|
|
c5e72c48eb | ||
|
|
82a6edad50 | ||
|
|
553ef0059a | ||
|
|
01e41d36dd | ||
|
|
3a85bb2ee5 | ||
|
|
29fb976051 | ||
|
|
3e988eafe2 | ||
|
|
7f84c8d97a | ||
|
|
1c8c3dc244 | ||
|
|
170ef9f5c6 | ||
|
|
6cab377087 | ||
|
|
8670300642 | ||
|
|
68d4ffc7f1 | ||
|
|
31989233b4 | ||
|
|
b2bf789b85 | ||
|
|
e45b08a5fb | ||
|
|
9e1a9fffc5 | ||
|
|
8bee3f786f | ||
|
|
31687b3094 | ||
|
|
cc2c7ab4dc | ||
|
|
a7270acdf1 | ||
|
|
56713860ac | ||
|
|
fbd05f2863 | ||
|
|
3a794947f0 | ||
|
|
ed16c23002 | ||
|
|
446c3932ae | ||
|
|
8e2889212a | ||
|
|
5a2bba0d33 | ||
|
|
8f0096eb5e | ||
|
|
18c4b45824 | ||
|
|
0f9ebb146e | ||
|
|
d7b82e2503 | ||
|
|
ef14c4dcd8 | ||
|
|
d609954c8b | ||
|
|
05db3108a2 | ||
|
|
a518ff1e1e | ||
|
|
e67e726743 | ||
|
|
ff6e13d8f0 | ||
|
|
935b2a3557 | ||
|
|
2e84cf22d1 | ||
|
|
bcd3d802f0 | ||
|
|
fd1e5d890a | ||
|
|
5cb972e7f6 | ||
|
|
21298fc63f | ||
|
|
f1b89eee83 | ||
|
|
10d435d2f9 | ||
|
|
690bfd6502 | ||
|
|
c55a66f90d | ||
|
|
fef90c7f6e | ||
|
|
8d571d0c55 | ||
|
|
c110d1132a | ||
|
|
30399e2d1c | ||
|
|
78b77a1352 | ||
|
|
b67de0308c | ||
|
|
9d707f612a | ||
|
|
0a62ac52be | ||
|
|
7ef03b498f | ||
|
|
656192fc14 | ||
|
|
77d9418cee | ||
|
|
2ebd2b75aa | ||
|
|
f9724a3209 | ||
|
|
6419623018 |
@@ -0,0 +1,3 @@
|
||||
[submodule "scripts/webpy"]
|
||||
path = scripts/webpy
|
||||
url = git://github.com/webpy/webpy.git
|
||||
@@ -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
|
||||
@@ -1,7 +1,7 @@
|
||||
# Programmer used for In System Programming
|
||||
ISP_PROG = dapa
|
||||
ISP_PROG = usbasp
|
||||
# device the ISP programmer is connected to
|
||||
ISP_DEV = /dev/parport0
|
||||
ISP_DEV =
|
||||
# Programmer used for serial programming (using the bootloader)
|
||||
SERIAL_PROG = avr109
|
||||
# device the serial programmer is connected to
|
||||
@@ -15,7 +15,6 @@ AS = avr-as
|
||||
CP = cp
|
||||
RM = rm -f
|
||||
AVRDUDE = avrdude
|
||||
AVRDUDE_BAUDRATE = 19200
|
||||
SIZE = avr-size
|
||||
|
||||
-include $(CURDIR)/config.mk
|
||||
@@ -33,8 +32,12 @@ endif
|
||||
ifeq ($(MCU),atmega168)
|
||||
AVRDUDE_MCU=m168
|
||||
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
|
||||
CFLAGS += -g -Os -finline-limit=800 -mmcu=$(MCU) -DF_CPU=$(F_CPU) -std=gnu99
|
||||
@@ -62,27 +65,14 @@ $(OBJECTS):
|
||||
clean:
|
||||
$(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
|
||||
|
||||
program-isp-%: %.hex
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) -c $(ISP_PROG) -P $(ISP_DEV) -U flash:w:$<
|
||||
flash:
|
||||
$(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:$<
|
||||
|
||||
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: %
|
||||
$(OBJCOPY) -O ihex -R .eeprom $< $@
|
||||
|
||||
@@ -94,6 +84,3 @@ program-serial-eeprom-%: %.eep.hex launch-bootloader
|
||||
|
||||
%-size: %.hex
|
||||
$(SIZE) $<
|
||||
|
||||
launch-bootloader:
|
||||
launch-bootloader $(SERIAL_DEV) $(AVRDUDE_BAUDRATE)
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,4 +15,8 @@
|
||||
//#define ENABLE_ECHO_FUNC
|
||||
|
||||
/* uncomment this for debug information via uart */
|
||||
//#define DEBUG_UART
|
||||
#define DEBUG_UART
|
||||
|
||||
|
||||
#define DEBUG 1
|
||||
#define DEBUG_USB 2
|
||||
@@ -5,5 +5,5 @@
|
||||
/* micro-jumptable, we are using just reset and int0 vectors */
|
||||
exit:
|
||||
__vector_default:
|
||||
rjmp __init
|
||||
rjmp __vector_1
|
||||
jmp __init
|
||||
jmp __vector_1
|
||||
@@ -231,40 +231,3 @@ Scroll down to the bottom to see the most recent changes.
|
||||
- Added 20 MHz module contributed by Jeroen Benschop.
|
||||
|
||||
* 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
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
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
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
USB Product ID(s) sent to you in e-mail after receiving your payment in
|
||||
@@ -1,8 +1,6 @@
|
||||
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
|
||||
your choice whether you apply the terms of version 2 or version 3. The full
|
||||
text of GPLv2 is included below. In addition to the requirements in the GPL,
|
||||
we STRONGLY ENCOURAGE you to do the following:
|
||||
terms and conditions of the GNU GPL version 2, see the text 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.
|
||||
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
|
||||
@@ -33,7 +33,7 @@ The driver consists of the following files:
|
||||
defined to a value greater than 0. Link this module
|
||||
to your code!
|
||||
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
|
||||
module instead of usbdrvasm.S when you assembler
|
||||
with IAR's tools.
|
||||
@@ -47,10 +47,9 @@ The driver consists of the following files:
|
||||
|
||||
CPU CORE CLOCK FREQUENCY
|
||||
========================
|
||||
We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz,
|
||||
16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The
|
||||
actual clock rate must be configured in usbdrv.h unless you use the default
|
||||
12 MHz.
|
||||
We supply assembler modules for clock frequencies of 12 MHz, 15 MHz, 16 MHz and
|
||||
16.5 MHz. Other clock rates are not supported. The actual clock rate must be
|
||||
configured in usbdrv.h unless you use the default 12 MHz.
|
||||
|
||||
12 MHz 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
|
||||
is somewhat tricky and has to insert a leap cycle every third byte.
|
||||
|
||||
12.8 MHz and 16.5 MHz Clock
|
||||
The assembler modules for these clock rates differ from the other modules
|
||||
because they have been built for an RC oscillator with only 1% precision. The
|
||||
receiver code inserts leap cycles to compensate for clock deviations. 1% is
|
||||
also the precision which can be achieved by calibrating the internal RC
|
||||
oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL
|
||||
oscillator can reach 16.5 MHz with the RC oscillator. This includes the very
|
||||
popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost
|
||||
all AVRs can reach 12.8 MHz, although this is outside the specified range.
|
||||
16.5 MHz Clock
|
||||
The assembler module for this clock rate differs from the other modules because
|
||||
it has been built for an RC oscillator with only 1% precision. The receiver
|
||||
code inserts leap cycles to compensate for clock deviations. 1% is also the
|
||||
precision which can be achieved by calibrating the internal RC oscillator of
|
||||
the AVR. Please note that only AVRs with internal 64 MHz PLL oscillator can be
|
||||
used since the 8 MHz RC oscillator cannot be trimmed up to 16.5 MHz. This
|
||||
includes the very popular ATTiny25, ATTiny45, ATTiny85 series as well as the
|
||||
ATTiny26.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
@@ -126,11 +115,10 @@ usbdrv.c because this module has been deliberately optimized for gcc.
|
||||
USING AVR-USB FOR FREE
|
||||
======================
|
||||
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
|
||||
your choice whether you apply the terms of version 2 or version 3.
|
||||
Version 2 (GPL2). See the file "License.txt" for details.
|
||||
|
||||
If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the
|
||||
following things IN ADDITION to the obligations from the GPL:
|
||||
If you decide for the free GPL2, we STRONGLY ENCOURAGE you to do the following
|
||||
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.
|
||||
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
|
||||
===============================
|
||||
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
|
||||
USB PIDs for free, licensed exclusively to you. See the file
|
||||
"CommercialLicense.txt" for details.
|
||||
@@ -4,7 +4,7 @@
|
||||
* Creation Date: 2007-11-05
|
||||
* Tabsize: 4
|
||||
* 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$
|
||||
*/
|
||||
|
||||
@@ -103,11 +103,8 @@ sofError:
|
||||
reti
|
||||
|
||||
handleData:
|
||||
#if USB_CFG_CHECK_CRC
|
||||
CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error
|
||||
#endif
|
||||
lds shift, usbCurrentTok;[18]
|
||||
tst shift ;[20]
|
||||
lds token, usbCurrentTok;[18]
|
||||
tst token ;[20]
|
||||
breq doReturn ;[21]
|
||||
lds x2, usbRxLen ;[22]
|
||||
tst x2 ;[24]
|
||||
@@ -116,11 +113,8 @@ handleData:
|
||||
; 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
|
||||
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 usbRxToken, shift ;[30]
|
||||
sts usbRxToken, token ;[30]
|
||||
lds x2, usbInputBufOffset;[32] swap buffers
|
||||
ldi cnt, USB_BUFSIZE ;[34]
|
||||
sub cnt, x2 ;[35]
|
||||
@@ -137,11 +131,7 @@ handleIn:
|
||||
ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
|
||||
#if USB_CFG_HAVE_INTRIN_ENDPOINT
|
||||
andi x3, 0xf ;[35] x3 contains endpoint
|
||||
#if USB_CFG_SUPPRESS_INTR_CODE
|
||||
brne sendNakAndReti ;[36]
|
||||
#else
|
||||
brne handleIn1 ;[36]
|
||||
#endif
|
||||
#endif
|
||||
lds cnt, usbTxLen ;[37]
|
||||
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
|
||||
; 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]
|
||||
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||
; 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 YH, hi8(usbTxBuf1) ;[47]
|
||||
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:
|
||||
lds cnt, usbTxLen3 ;[41]
|
||||
sbrc cnt, 4 ;[43]
|
||||
@@ -185,4 +176,3 @@ handleIn3:
|
||||
ldi YH, hi8(usbTxBuf3) ;[48]
|
||||
rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP
|
||||
#endif
|
||||
#endif
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2006-03-01
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: Proprietary, free under certain conditions. See Documentation.
|
||||
* This Revision: $Id$
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* 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
|
||||
|
||||
#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__
|
||||
# define __ASSEMBLER__
|
||||
@@ -58,6 +53,13 @@ Thanks to Oleg Semyonov for his help with the IAR tools port!
|
||||
#define sei() __enable_interrupt()
|
||||
#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 /* __iarcompat_h_INCLUDED__ */
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2005-01-16
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: oddebug.c 692 2008-11-07 15:07:40Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: oddebug.c 275 2007-03-20 09:58:28Z cs $
|
||||
*/
|
||||
|
||||
#include "oddebug.h"
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2005-01-16
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: oddebug.h 692 2008-11-07 15:07:40Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: oddebug.h 275 2007-03-20 09:58:28Z cs $
|
||||
*/
|
||||
|
||||
#ifndef __oddebug_h_included__
|
||||
@@ -29,7 +29,10 @@ the output and a memory block to dump in hex ('data' and 'len').
|
||||
#endif
|
||||
|
||||
/* make sure we have the UART defines: */
|
||||
#include "usbportability.h"
|
||||
#include "iarcompat.h"
|
||||
#ifndef __IAR_SYSTEMS_ICC__
|
||||
# include <avr/io.h>
|
||||
#endif
|
||||
|
||||
#ifndef uchar
|
||||
# define uchar unsigned char
|
||||
+7
-56
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2005-04-01
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbconfig-prototype.h 734 2009-03-23 11:10:07Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbconfig-prototype.h 600 2008-05-13 10:34:56Z cs $
|
||||
*/
|
||||
|
||||
#ifndef __usbconfig_h_included__
|
||||
@@ -44,18 +44,12 @@ section at the end of this file).
|
||||
* markers every millisecond.]
|
||||
*/
|
||||
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
||||
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
|
||||
* 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no
|
||||
* crystal, they tolerate +/- 1% deviation from the nominal frequency. All
|
||||
* other rates require a precision of 2000 ppm and thus a crystal!
|
||||
/* Clock rate of the AVR in MHz. Legal values are 12000, 15000, 16000, 16500
|
||||
* and 20000. The 16.5 MHz version of the code requires no crystal, it
|
||||
* tolerates +/- 1% deviation from the nominal frequency. All other rates
|
||||
* require a precision of 2000 ppm and thus a crystal!
|
||||
* 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 ------------------------ */
|
||||
|
||||
@@ -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
|
||||
* 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
|
||||
/* 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
|
||||
@@ -170,33 +156,6 @@ section at the end of this file).
|
||||
* counts SOF packets. This feature requires that the hardware interrupt is
|
||||
* 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 this macro to 1 if you want the function usbMeasureFrameLength()
|
||||
* 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.
|
||||
* Possible properties are:
|
||||
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
|
||||
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
|
||||
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
|
||||
* you want RAM pointers.
|
||||
* at runtime via usbFunctionDescriptor().
|
||||
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
|
||||
* in static memory is in RAM, not in flash memory.
|
||||
* + 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_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
|
||||
@@ -4,11 +4,15 @@
|
||||
* Creation Date: 2004-12-29
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrv.c 721 2009-03-16 19:03:19Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* 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 "oddebug.h"
|
||||
|
||||
@@ -34,15 +38,12 @@ uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbT
|
||||
#if USB_COUNT_SOF
|
||||
volatile uchar usbSofCount; /* incremented by assembler module every SOF */
|
||||
#endif
|
||||
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
|
||||
#if USB_CFG_HAVE_INTRIN_ENDPOINT
|
||||
usbTxStatus_t usbTxStatus1;
|
||||
# if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||
usbTxStatus_t usbTxStatus3;
|
||||
# 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 */
|
||||
uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
|
||||
@@ -55,7 +56,7 @@ static uchar usbMsgFlags; /* flag values see below */
|
||||
/*
|
||||
optimizing hints:
|
||||
- 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
|
||||
- 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)
|
||||
{
|
||||
#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 */
|
||||
# if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||
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
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
#endif /* USB_CFG_SUPPRESS_INTR_CODE */
|
||||
|
||||
/* ------------------ utilities for code following below ------------------- */
|
||||
|
||||
@@ -400,7 +408,7 @@ uchar index = rq->wIndex.bytes[0];
|
||||
usbResetStall();
|
||||
SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */
|
||||
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 */
|
||||
usbResetDataToggling();
|
||||
usbResetStall();
|
||||
@@ -428,7 +436,7 @@ usbRequest_t *rq = (void *)data;
|
||||
* 0xe1 11100001 (USBPID_OUT: data phase of setup transfer)
|
||||
* 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)
|
||||
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
|
||||
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(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(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
|
||||
replyLen = rq->wLength.bytes[0];
|
||||
}else{
|
||||
replyLen = rq->wLength.word;
|
||||
}
|
||||
replyLen = rq->wLength.bytes[0]; /* IN transfers only */
|
||||
}
|
||||
usbMsgFlags = USB_FLG_USE_USER_RW;
|
||||
}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;
|
||||
if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
|
||||
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;
|
||||
r++;
|
||||
}while(--i);
|
||||
@@ -588,17 +592,17 @@ uchar i;
|
||||
usbBuildTxBlock();
|
||||
}
|
||||
}
|
||||
for(i = 20; i > 0; i--){
|
||||
for(i = 10; i > 0; i--){
|
||||
uchar usbLineStatus = USBIN & USBMASK;
|
||||
if(usbLineStatus != 0) /* SE0 has ended */
|
||||
goto isNotReset;
|
||||
break;
|
||||
}
|
||||
if(i == 0){ /* RESET condition, called multiple times during reset */
|
||||
usbNewDeviceAddr = 0;
|
||||
usbDeviceAddr = 0;
|
||||
usbResetStall();
|
||||
DBG1(0xff, 0, 0);
|
||||
}
|
||||
/* RESET condition, called multiple times during reset */
|
||||
usbNewDeviceAddr = 0;
|
||||
usbDeviceAddr = 0;
|
||||
usbResetStall();
|
||||
DBG1(0xff, 0, 0);
|
||||
isNotReset:
|
||||
usbHandleResetHook(i);
|
||||
}
|
||||
|
||||
@@ -614,7 +618,7 @@ USB_PUBLIC void usbInit(void)
|
||||
#endif
|
||||
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
|
||||
usbResetDataToggling();
|
||||
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
|
||||
#if USB_CFG_HAVE_INTRIN_ENDPOINT
|
||||
usbTxLen1 = USBPID_NAK;
|
||||
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
||||
usbTxLen3 = USBPID_NAK;
|
||||
@@ -4,14 +4,14 @@
|
||||
* Creation Date: 2004-12-29
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrv.h 738 2009-03-23 11:13:24Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrv.h 607 2008-05-13 15:57:28Z cs $
|
||||
*/
|
||||
|
||||
#ifndef __usbdrv_h_included__
|
||||
#define __usbdrv_h_included__
|
||||
#include "usbconfig.h"
|
||||
#include "usbportability.h"
|
||||
#include "iarcompat.h"
|
||||
|
||||
/*
|
||||
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!
|
||||
|
||||
The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz
|
||||
or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details.
|
||||
The device MUST be clocked at exactly 12 MHz, 15 MHz or 16 MHz
|
||||
or at 16.5 MHz +/- 1%. See usbconfig-prototype.h for details.
|
||||
|
||||
|
||||
Limitations:
|
||||
@@ -122,7 +122,7 @@ USB messages, even if they address another (low-speed) device on the same bus.
|
||||
/* --------------------------- Module Interface ---------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define USBDRV_VERSION 20090323
|
||||
#define USBDRV_VERSION 20080513
|
||||
/* 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
|
||||
* 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()..
|
||||
*/
|
||||
#endif /* USB_CFG_IMPLEMENT_FN_READ */
|
||||
|
||||
extern uchar usbRxToken; /* may be used in usbFunctionWriteOut() below */
|
||||
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
|
||||
USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len);
|
||||
/* 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.
|
||||
*/
|
||||
#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))
|
||||
/* 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)
|
||||
/* If this property is set for a descriptor, usbFunctionDescriptor() will be
|
||||
* used to obtain the particular descriptor. Data directly returned via
|
||||
* usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to
|
||||
* return RAM data.
|
||||
* used to obtain the particular descriptor.
|
||||
*/
|
||||
#define USB_PROP_IS_RAM (1 << 15)
|
||||
/* 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
|
||||
#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 */
|
||||
|
||||
/* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */
|
||||
@@ -572,14 +558,7 @@ int usbDescriptorStringSerialNumber[];
|
||||
# endif
|
||||
#endif
|
||||
#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 */
|
||||
# endif
|
||||
# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */
|
||||
#endif
|
||||
#ifndef USB_INTR_CFG_CLR /* allow user to override our default */
|
||||
# define USB_INTR_CFG_CLR 0 /* no bits to clear */
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2007-06-13
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm.S 722 2009-03-16 19:03:57Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -15,9 +15,16 @@ general code (preprocessor acrobatics and CRC computation) and then includes
|
||||
the file appropriate for the given clock rate.
|
||||
*/
|
||||
|
||||
#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
|
||||
#include "usbportability.h"
|
||||
#include "usbdrv.h" /* for common defs */
|
||||
#include "iarcompat.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 */
|
||||
|
||||
/* register names */
|
||||
#define x1 r16
|
||||
@@ -26,14 +33,24 @@ the file appropriate for the given clock rate.
|
||||
#define cnt r19
|
||||
#define x3 r20
|
||||
#define x4 r21
|
||||
#define x5 r22
|
||||
#define bitcnt x5
|
||||
#define bitcnt r22
|
||||
#define phase x4
|
||||
#define leap x4
|
||||
|
||||
/* Some assembler dependent definitions and declarations: */
|
||||
|
||||
#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 usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
|
||||
extern usbTxBuf, usbTxStatus1, usbTxStatus3
|
||||
@@ -56,6 +73,8 @@ the file appropriate for the given clock rate.
|
||||
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
|
||||
# define nop2 rjmp .+0 /* jump to next instruction */
|
||||
|
||||
# ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
|
||||
# define USB_INTR_VECTOR SIG_INTERRUPT0
|
||||
# endif
|
||||
@@ -280,26 +299,16 @@ usbMFTimeout:
|
||||
# define USB_CFG_CLOCK_KHZ 12000
|
||||
#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
|
||||
# include "usbdrvasm12.inc"
|
||||
# elif USB_CFG_CLOCK_KHZ == 12800
|
||||
# include "usbdrvasm128.inc"
|
||||
# elif USB_CFG_CLOCK_KHZ == 15000
|
||||
# include "usbdrvasm15.inc"
|
||||
# elif USB_CFG_CLOCK_KHZ == 16000
|
||||
# include "usbdrvasm16.inc"
|
||||
# elif USB_CFG_CLOCK_KHZ == 16500
|
||||
# include "usbdrvasm165.inc"
|
||||
# elif USB_CFG_CLOCK_KHZ == 20000
|
||||
# include "usbdrvasm20.inc"
|
||||
# else
|
||||
# error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
|
||||
# endif
|
||||
#endif /* USB_CFG_CHECK_CRC */
|
||||
#if USB_CFG_CLOCK_KHZ == 12000
|
||||
# include "usbdrvasm12.inc"
|
||||
#elif USB_CFG_CLOCK_KHZ == 15000
|
||||
# include "usbdrvasm15.inc"
|
||||
#elif USB_CFG_CLOCK_KHZ == 16000
|
||||
# include "usbdrvasm16.inc"
|
||||
#elif USB_CFG_CLOCK_KHZ == 16500
|
||||
# include "usbdrvasm165.inc"
|
||||
#elif USB_CFG_CLOCK_KHZ == 20000
|
||||
# include "usbdrvasm20.inc"
|
||||
#else
|
||||
# error "USB_CFG_CLOCK_KHZ is not one of the supported rates!"
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
* Creation Date: 2006-03-01
|
||||
* Tabsize: 4
|
||||
* 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$
|
||||
*/
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2004-12-29
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrvasm12.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* 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
|
||||
@@ -48,13 +48,10 @@ USB_INTR_VECTOR:
|
||||
;----------------------------------------------------------------------------
|
||||
;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
|
||||
;The first part waits at most 1 bit long since we must be in sync pattern.
|
||||
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
|
||||
;waitForJ, ensure that this prerequisite is met.
|
||||
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
|
||||
waitForJ:
|
||||
inc YL
|
||||
sbis USBIN, USBMINUS
|
||||
brne waitForJ ; just make sure we have ANY timeout
|
||||
sbis USBIN, USBMINUS ;1 [40] wait for D- == 1
|
||||
rjmp waitForJ ;2
|
||||
waitForK:
|
||||
;The following code results in a sampling window of 1/4 bit which meets the spec.
|
||||
sbis USBIN, USBMINUS
|
||||
@@ -72,9 +69,6 @@ waitForK:
|
||||
inc YL
|
||||
sts usbSofCount, YL
|
||||
#endif /* USB_COUNT_SOF */
|
||||
#ifdef USB_SOF_HOOK
|
||||
USB_SOF_HOOK
|
||||
#endif
|
||||
rjmp sofError
|
||||
foundK:
|
||||
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
|
||||
@@ -256,12 +250,12 @@ macro POP_STANDARD ; 12 cycles
|
||||
pop x1
|
||||
pop shift
|
||||
pop YH
|
||||
endm
|
||||
endm
|
||||
macro POP_RETI ; 5 cycles
|
||||
pop YL
|
||||
out SREG, YL
|
||||
pop YL
|
||||
endm
|
||||
endm
|
||||
|
||||
#include "asmcommon.inc"
|
||||
|
||||
@@ -269,16 +263,25 @@ macro POP_RETI ; 5 cycles
|
||||
; Transmitting data
|
||||
;----------------------------------------------------------------------------
|
||||
|
||||
txByteLoop:
|
||||
txBitloop:
|
||||
stuffN1Delay: ; [03]
|
||||
ror shift ;[-5] [11] [59]
|
||||
brcc doExorN1 ;[-4] [60]
|
||||
subi x4, 1 ;[-3]
|
||||
brne commonN1 ;[-2]
|
||||
lsl shift ;[-1] compensate ror after rjmp stuffDelay
|
||||
nop ;[00] stuffing consists of just waiting 8 cycles
|
||||
rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
|
||||
bitstuff0: ;1 (for branch taken)
|
||||
eor x1, x4 ;1
|
||||
ldi x2, 0 ;1
|
||||
out USBOUT, x1 ;1 <-- out
|
||||
rjmp didStuff0 ;2 branch back 2 cycles earlier
|
||||
bitstuff1: ;1 (for branch taken)
|
||||
eor x1, x4 ;1
|
||||
rjmp didStuff1 ;2 we know that C is clear, jump back to do OUT and ror 0 into x2
|
||||
bitstuff2: ;1 (for branch taken)
|
||||
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
|
||||
ldi x3, USBPID_NAK ;1 [-18]
|
||||
@@ -303,91 +306,122 @@ usbSendX3: ;0 [-16]
|
||||
;usbSend:
|
||||
;pointer to data in 'Y'
|
||||
;number of bytes in 'cnt' -- including sync byte
|
||||
;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt]
|
||||
;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
|
||||
usbSendAndReti:
|
||||
in x2, USBDDR ;[-12] 12 cycles until SOP
|
||||
ori x2, USBMASK ;[-11]
|
||||
sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
|
||||
out USBDDR, x2 ;[-8] <--- acquire bus
|
||||
in x1, USBOUT ;[-7] port mirror for tx loop
|
||||
ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror)
|
||||
ldi x2, USBMASK ;[-5]
|
||||
push x4 ;[-4]
|
||||
doExorN1:
|
||||
eor x1, x2 ;[-2] [06] [62]
|
||||
ldi x4, 6 ;[-1] [07] [63]
|
||||
commonN1:
|
||||
stuffN2Delay:
|
||||
out USBOUT, x1 ;[00] [08] [64] <--- set bit
|
||||
ror shift ;[01]
|
||||
brcc doExorN2 ;[02]
|
||||
subi x4, 1 ;[03]
|
||||
brne commonN2 ;[04]
|
||||
lsl shift ;[05] compensate ror after rjmp stuffDelay
|
||||
rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
|
||||
doExorN2:
|
||||
eor x1, x2 ;[04] [12]
|
||||
ldi x4, 6 ;[05] [13]
|
||||
commonN2:
|
||||
nop ;[06] [14]
|
||||
subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1
|
||||
out USBOUT, x1 ;[08] [16] <--- set bit
|
||||
brcs txBitloop ;[09] [25] [41]
|
||||
|
||||
stuff6Delay:
|
||||
ror shift ;[42] [50]
|
||||
brcc doExor6 ;[43]
|
||||
subi x4, 1 ;[44]
|
||||
brne common6 ;[45]
|
||||
lsl shift ;[46] compensate ror after rjmp stuffDelay
|
||||
nop ;[47] stuffing consists of just waiting 8 cycles
|
||||
rjmp stuff6Delay ;[48] after ror, C bit is reliably clear
|
||||
doExor6:
|
||||
eor x1, x2 ;[45] [53]
|
||||
ldi x4, 6 ;[46]
|
||||
common6:
|
||||
stuff7Delay:
|
||||
ror shift ;[47] [55]
|
||||
out USBOUT, x1 ;[48] <--- set bit
|
||||
brcc doExor7 ;[49]
|
||||
subi x4, 1 ;[50]
|
||||
brne common7 ;[51]
|
||||
lsl shift ;[52] compensate ror after rjmp stuffDelay
|
||||
rjmp stuff7Delay ;[53] after ror, C bit is reliably clear
|
||||
doExor7:
|
||||
eor x1, x2 ;[51] [59]
|
||||
ldi x4, 6 ;[52]
|
||||
common7:
|
||||
ld shift, y+ ;[53]
|
||||
tst cnt ;[55]
|
||||
out USBOUT, x1 ;[56] <--- set bit
|
||||
brne txByteLoop ;[57]
|
||||
|
||||
;uses: x1...x4, shift, cnt, Y
|
||||
;Numbers in brackets are time since first bit of sync pattern is sent
|
||||
usbSendAndReti: ;0 [-13] timing: 13 cycles until SOP
|
||||
in x2, USBDDR ;1 [-12]
|
||||
ori x2, USBMASK ;1 [-11]
|
||||
sbi USBOUT, USBMINUS;2 [-9] prepare idle state; D+ and D- must have been 0 (no pullups)
|
||||
in x1, USBOUT ;1 [-8] port mirror for tx loop
|
||||
out USBDDR, x2 ;1 [-7] <- acquire bus
|
||||
; need not init x2 (bitstuff history) because sync starts with 0
|
||||
push x4 ;2 [-5]
|
||||
ldi x4, USBMASK ;1 [-4] exor mask
|
||||
ldi shift, 0x80 ;1 [-3] sync byte is first byte sent
|
||||
txLoop: ; [62]
|
||||
sbrs shift, 0 ;1 [-2] [62]
|
||||
eor x1, x4 ;1 [-1] [63]
|
||||
out USBOUT, x1 ;1 [0] <-- out bit 0
|
||||
ror shift ;1 [1]
|
||||
ror x2 ;1 [2]
|
||||
didStuff0:
|
||||
cpi x2, 0xfc ;1 [3]
|
||||
brsh bitstuff0 ;1 [4]
|
||||
sbrs shift, 0 ;1 [5]
|
||||
eor x1, x4 ;1 [6]
|
||||
ror shift ;1 [7]
|
||||
didStuff1:
|
||||
out USBOUT, x1 ;1 [8] <-- out bit 1
|
||||
ror x2 ;1 [9]
|
||||
cpi x2, 0xfc ;1 [10]
|
||||
brsh bitstuff1 ;1 [11]
|
||||
sbrs shift, 0 ;1 [12]
|
||||
eor x1, x4 ;1 [13]
|
||||
ror shift ;1 [14]
|
||||
didStuff2:
|
||||
ror x2 ;1 [15]
|
||||
out USBOUT, x1 ;1 [16] <-- out bit 2
|
||||
cpi x2, 0xfc ;1 [17]
|
||||
brsh bitstuff2 ;1 [18]
|
||||
sbrs shift, 0 ;1 [19]
|
||||
eor x1, x4 ;1 [20]
|
||||
ror shift ;1 [21]
|
||||
didStuff3:
|
||||
ror x2 ;1 [22]
|
||||
cpi x2, 0xfc ;1 [23]
|
||||
out USBOUT, x1 ;1 [24] <-- out bit 3
|
||||
brsh bitstuff3 ;1 [25]
|
||||
nop2 ;2 [27]
|
||||
ld x3, y+ ;2 [29]
|
||||
sbrs shift, 0 ;1 [30]
|
||||
eor x1, x4 ;1 [31]
|
||||
out USBOUT, x1 ;1 [32] <-- out bit 4
|
||||
ror shift ;1 [33]
|
||||
ror x2 ;1 [34]
|
||||
didStuff4:
|
||||
cpi x2, 0xfc ;1 [35]
|
||||
brsh bitstuff4 ;1 [36]
|
||||
sbrs shift, 0 ;1 [37]
|
||||
eor x1, x4 ;1 [38]
|
||||
ror shift ;1 [39]
|
||||
didStuff5:
|
||||
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:
|
||||
cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles]
|
||||
lds x2, usbNewDeviceAddr;[59]
|
||||
lsl x2 ;[61] we compare with left shifted address
|
||||
subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3
|
||||
sbci YH, 0 ;[63]
|
||||
out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
|
||||
cbr x1, USBMASK ;1 [61] prepare SE0 [spec says EOP may be 15 to 18 cycles]
|
||||
pop x4 ;2 [63]
|
||||
;brackets are cycles from start of SE0 now
|
||||
out USBOUT, x1 ;1 [0] <-- 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:
|
||||
;set address only after data packet was sent, not after handshake
|
||||
breq skipAddrAssign ;[01]
|
||||
sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
|
||||
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
|
||||
skipAddrAssign:
|
||||
;end of usbDeviceAddress transfer
|
||||
ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
|
||||
USB_STORE_PENDING(x2) ;[04]
|
||||
ori x1, USBIDLE ;[05]
|
||||
in x2, USBDDR ;[06]
|
||||
cbr x2, USBMASK ;[07] set both pins to input
|
||||
mov x3, x1 ;[08]
|
||||
cbr x3, USBMASK ;[09] configure no pullup on both pins
|
||||
pop x4 ;[10]
|
||||
nop2 ;[12]
|
||||
nop2 ;[14]
|
||||
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
|
||||
ldi x2, 1<<USB_INTR_PENDING_BIT;1 [8] int0 occurred during TX -- clear pending flag
|
||||
USB_STORE_PENDING(x2) ;1 [9]
|
||||
ori x1, USBIDLE ;1 [10]
|
||||
in x2, USBDDR ;1 [11]
|
||||
cbr x2, USBMASK ;1 [12] set both pins to input
|
||||
mov x3, x1 ;1 [13]
|
||||
cbr x3, USBMASK ;1 [14] configure no pullup on both pins
|
||||
out USBOUT, x1 ;1 [15] <-- out J (idle) -- end of SE0 (EOP signal)
|
||||
out USBDDR, x2 ;1 [16] <-- release bus now
|
||||
out USBOUT, x3 ;1 [17] <-- ensure no pull-up resistors are active
|
||||
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...
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm128.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-10-11
|
||||
* 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: 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
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2007-08-06
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm15.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm15.inc 607 2008-05-13 15:57:28Z cs $
|
||||
*/
|
||||
|
||||
/* 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 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.
|
||||
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
|
||||
;waitForJ, ensure that this prerequisite is met.
|
||||
waitForJ:
|
||||
inc YL
|
||||
sbis USBIN, USBMINUS
|
||||
brne waitForJ ; just make sure we have ANY timeout
|
||||
; first part has no timeout because it waits for IDLE or SE1 (== disconnected)
|
||||
;-------------------------------------------------------------------------------
|
||||
waitForJ: ;-
|
||||
sbis USBIN, USBMINUS ;1 <-- sample: wait for D- == 1
|
||||
rjmp waitForJ ;2
|
||||
;-------------------------------------------------------------------------------
|
||||
; The following code results in a sampling window of < 1/4 bit
|
||||
; which meets the spec.
|
||||
@@ -72,9 +70,6 @@ waitForK: ;-
|
||||
inc YL
|
||||
sts usbSofCount, YL
|
||||
#endif /* USB_COUNT_SOF */
|
||||
#ifdef USB_SOF_HOOK
|
||||
USB_SOF_HOOK
|
||||
#endif
|
||||
rjmp sofError
|
||||
;------------------------------------------------------------------------------
|
||||
; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for
|
||||
@@ -294,12 +289,12 @@ macro POP_STANDARD ; 16 cycles
|
||||
pop x1
|
||||
pop shift
|
||||
pop YH
|
||||
endm
|
||||
endm
|
||||
macro POP_RETI ; 5 cycles
|
||||
pop YL
|
||||
out SREG, YL
|
||||
pop YL
|
||||
endm
|
||||
endm
|
||||
|
||||
#include "asmcommon.inc"
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2007-06-15
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm16.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm16.inc 607 2008-05-13 15:57:28Z cs $
|
||||
*/
|
||||
|
||||
/* 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 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.
|
||||
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
|
||||
;waitForJ, ensure that this prerequisite is met.
|
||||
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
|
||||
waitForJ:
|
||||
inc YL
|
||||
sbis USBIN, USBMINUS
|
||||
brne waitForJ ; just make sure we have ANY timeout
|
||||
sbis USBIN, USBMINUS ;[-18] wait for D- == 1
|
||||
rjmp waitForJ
|
||||
waitForK:
|
||||
;The following code results in a sampling window of < 1/4 bit which meets the spec.
|
||||
sbis USBIN, USBMINUS ;[-15]
|
||||
@@ -67,9 +64,6 @@ waitForK:
|
||||
inc YL
|
||||
sts usbSofCount, YL
|
||||
#endif /* USB_COUNT_SOF */
|
||||
#ifdef USB_SOF_HOOK
|
||||
USB_SOF_HOOK
|
||||
#endif
|
||||
rjmp sofError
|
||||
foundK: ;[-12]
|
||||
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
|
||||
@@ -214,13 +208,13 @@ macro POP_STANDARD ; 14 cycles
|
||||
pop x1
|
||||
pop shift
|
||||
pop bitcnt
|
||||
endm
|
||||
endm
|
||||
macro POP_RETI ; 7 cycles
|
||||
pop YH
|
||||
pop YL
|
||||
out SREG, YL
|
||||
pop YL
|
||||
endm
|
||||
endm
|
||||
|
||||
#include "asmcommon.inc"
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* Creation Date: 2007-04-22
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm165.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm165.inc 607 2008-05-13 15:57:28Z cs $
|
||||
*/
|
||||
|
||||
/* 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 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.
|
||||
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
|
||||
;waitForJ, ensure that this prerequisite is met.
|
||||
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
|
||||
waitForJ:
|
||||
inc YL
|
||||
sbis USBIN, USBMINUS
|
||||
brne waitForJ ; just make sure we have ANY timeout
|
||||
sbis USBIN, USBMINUS ;[-18] wait for D- == 1
|
||||
rjmp waitForJ
|
||||
waitForK:
|
||||
;The following code results in a sampling window of < 1/4 bit which meets the spec.
|
||||
sbis USBIN, USBMINUS ;[-15]
|
||||
@@ -72,9 +69,6 @@ waitForK:
|
||||
inc YL
|
||||
sts usbSofCount, YL
|
||||
#endif /* USB_COUNT_SOF */
|
||||
#ifdef USB_SOF_HOOK
|
||||
USB_SOF_HOOK
|
||||
#endif
|
||||
rjmp sofError
|
||||
foundK: ;[-12]
|
||||
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
|
||||
@@ -340,12 +334,12 @@ macro POP_STANDARD ; 16 cycles
|
||||
pop shift
|
||||
pop YH
|
||||
pop r0
|
||||
endm
|
||||
endm
|
||||
macro POP_RETI ; 5 cycles
|
||||
pop YL
|
||||
out SREG, YL
|
||||
pop YL
|
||||
endm
|
||||
endm
|
||||
|
||||
#include "asmcommon.inc"
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
/* 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)
|
||||
* Creation Date: 2009-01-20
|
||||
* Tabsize: 4
|
||||
* 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)
|
||||
* 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
|
||||
@@ -5,8 +5,8 @@
|
||||
* Creation Date: 2008-03-05
|
||||
* Tabsize: 4
|
||||
* 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)
|
||||
* Revision: $Id: usbdrvasm20.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm20.inc 607 2008-05-13 15:57:28Z cs $
|
||||
*/
|
||||
|
||||
/* 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 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.
|
||||
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
|
||||
;waitForJ, ensure that this prerequisite is met.
|
||||
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
|
||||
waitForJ:
|
||||
inc YL
|
||||
sbis USBIN, USBMINUS
|
||||
brne waitForJ ; just make sure we have ANY timeout
|
||||
sbis USBIN, USBMINUS ;[-21] wait for D- == 1
|
||||
rjmp waitForJ
|
||||
waitForK:
|
||||
;The following code results in a sampling window of < 1/4 bit which meets the spec.
|
||||
sbis USBIN, USBMINUS ;[-19]
|
||||
@@ -89,9 +86,6 @@ waitForK:
|
||||
inc YL
|
||||
sts usbSofCount, YL
|
||||
#endif /* USB_COUNT_SOF */
|
||||
#ifdef USB_SOF_HOOK
|
||||
USB_SOF_HOOK
|
||||
#endif
|
||||
rjmp sofError
|
||||
foundK: ;[-16]
|
||||
;{3, 5} after falling D- edge, average delay: 4 cycles
|
||||
@@ -238,13 +232,13 @@ macro POP_STANDARD ; 14 cycles
|
||||
pop x1
|
||||
pop shift
|
||||
pop bitcnt
|
||||
endm
|
||||
endm
|
||||
macro POP_RETI ; 7 cycles
|
||||
pop YH
|
||||
pop YL
|
||||
out SREG, YL
|
||||
pop YL
|
||||
endm
|
||||
endm
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbportability.h
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-06-17
|
||||
* 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: usbportability.h 692 2008-11-07 15:07:40Z cs $
|
||||
* This Revision: $Id: usbportability.h 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
+46
-47
@@ -1,45 +1,53 @@
|
||||
# =====================================================================================
|
||||
#
|
||||
# ________ .__ __ ________ ____ ________
|
||||
# \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
# / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
# / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
# \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
# \__> \/ \/ \/ \/ \/
|
||||
# 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
|
||||
DEVICE = atmega644
|
||||
F_CPU = 20000000 # in Hz
|
||||
FUSE_L = 0xf7
|
||||
FUSE_H = 0xd9
|
||||
TARGET = main
|
||||
AVRDUDE = avrdude -c usbasp -p $(DEVICE)
|
||||
SIZE = avr-size
|
||||
|
||||
|
||||
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
LDFLAGS = -Wl,-u,vfprintf -lprintf_flt
|
||||
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0
|
||||
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 huffman-decode.o rle.c loader.o info.o shared_memory.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
|
||||
endif
|
||||
|
||||
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0
|
||||
#-std=gnu99
|
||||
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
|
||||
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Fuse values for particular devices
|
||||
##############################################################################
|
||||
# If your device is not listed here, go to
|
||||
# http://palmavr.sourceforge.net/cgi-bin/fc.cgi
|
||||
# and choose options for external crystal clock and no clock divider
|
||||
#
|
||||
################################## 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)
|
||||
# http://www.engbedded.com/fusecalc/
|
||||
FUSE_L = 0xf7
|
||||
FUSE_H = 0xda
|
||||
|
||||
# ATMega644 FUSE_H (Fuse high byte):
|
||||
# 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)
|
||||
all: hex
|
||||
|
||||
|
||||
|
||||
# symbolic targets:
|
||||
help:
|
||||
@echo "This Makefile has no default rule. Use one of the following:"
|
||||
@echo "make hex ....... to build main.hex"
|
||||
@@ -48,9 +56,12 @@ help:
|
||||
@echo "make flash ..... to flash the firmware (use this on metaboard)"
|
||||
@echo "make clean ..... to delete objects and hex file"
|
||||
|
||||
all: 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
|
||||
|
||||
@@ -60,48 +71,36 @@ fuse:
|
||||
{ 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
|
||||
|
||||
# rule for uploading firmware:
|
||||
flash: main.hex
|
||||
$(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:
|
||||
$(COMPILE) -c $< -o $@
|
||||
|
||||
# Generic rule for assembling Assembler source files:
|
||||
.S.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:
|
||||
$(COMPILE) -S $< -o $@
|
||||
|
||||
# file targets:
|
||||
|
||||
# Since we don't want to ship the driver multipe times, we copy it into this project:
|
||||
usbdrv:
|
||||
cp -r ../../../usbdrv .
|
||||
|
||||
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
|
||||
rm -f main.hex main.eep.hex
|
||||
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
|
||||
avr-size main.hex
|
||||
|
||||
# debugging targets:
|
||||
|
||||
disasm: main.elf
|
||||
avr-objdump -d main.elf
|
||||
|
||||
cpp:
|
||||
$(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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
/* 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 $
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#ifndef __OPENDEVICE_H_INCLUDED__
|
||||
#define __OPENDEVICE_H_INCLUDED__
|
||||
|
||||
Binary file not shown.
@@ -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 (1<<BANK_SIZE_SHIFT)
|
||||
#define READ_BUFFER_SIZE (1<<BANK_SIZE_SHIFT)
|
||||
#define SEND_BUFFER_SIZE 128
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <usb.h> /* this is libusb */
|
||||
|
||||
#include "opendevice.h" /* common code moved to separate module */
|
||||
|
||||
#include "../requests.h" /* custom request numbers */
|
||||
@@ -119,20 +123,22 @@ int main(int argc, char **argv)
|
||||
USB_CFG_DEVICE_ID};
|
||||
char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = {
|
||||
USB_CFG_DEVICE_NAME, 0};
|
||||
int cnt,
|
||||
vid,
|
||||
pid;
|
||||
int cnt_crc = 0;
|
||||
int cnt, vid, pid;
|
||||
uint8_t *read_buffer;
|
||||
uint8_t *crc_buffer;
|
||||
uint8_t *ptr;
|
||||
|
||||
uint32_t addr = 0;
|
||||
uint16_t addr_lo = 0;
|
||||
uint16_t addr_hi = 0;
|
||||
uint16_t step = 0;
|
||||
uint32_t step = 0;
|
||||
uint16_t crc = 0;
|
||||
uint8_t bank = 0;
|
||||
uint8_t bank_cnt = 0;
|
||||
uint32_t file_size = 0;
|
||||
uint32_t file_offset = 0;
|
||||
|
||||
FILE *fp;
|
||||
|
||||
usb_init();
|
||||
if (argc < 2) { /* we need at least one argument */
|
||||
usage(argv[0]);
|
||||
@@ -166,59 +172,107 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "Cannot open file %s ", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
read_buffer = (unsigned char *) malloc(READ_BUFFER_SIZE);
|
||||
crc_buffer = (unsigned char *) malloc(BUFFER_CRC);
|
||||
memset(crc_buffer, 0, BUFFER_CRC);
|
||||
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,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_UPLOAD_ADDR, addr_hi,
|
||||
addr_lo, (char *) read_buffer + step,
|
||||
SEND_BUFFER_SIZE, 5000);
|
||||
if (addr%0x1000==0){
|
||||
printf ("bank=0x%02x addr=0x%08x\n", bank, addr);
|
||||
}
|
||||
|
||||
if (cnt < 0) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
exit(-1);
|
||||
}
|
||||
addr += SEND_BUFFER_SIZE;
|
||||
}
|
||||
dump_packet(0x00000,READ_BUFFER_SIZE, read_buffer);
|
||||
memcpy(crc_buffer + cnt_crc, read_buffer, READ_BUFFER_SIZE);
|
||||
cnt_crc += READ_BUFFER_SIZE;
|
||||
if (cnt_crc >= READ_BUFFER_SIZE) {
|
||||
crc = do_crc(crc_buffer, BANK_SIZE);
|
||||
printf ("bank=0x%02x crc=0x%04x\n", bank, crc);
|
||||
memset(crc_buffer, 0, BUFFER_CRC);
|
||||
bank++;
|
||||
cnt_crc = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_CRC, addr_hi, addr_lo, NULL,
|
||||
0, 5000);
|
||||
*/
|
||||
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);
|
||||
crc_buffer = (unsigned char *) malloc(0x1000);
|
||||
memset(crc_buffer, 0, 0x1000);
|
||||
addr = 0x000000;
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_SNES_BOOT, 0, 0, NULL,
|
||||
USB_ENDPOINT_OUT, USB_MODE_AVR, 0, 0, NULL,
|
||||
0, 5000);
|
||||
|
||||
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
usb_close(handle);
|
||||
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;
|
||||
ptr += SEND_BUFFER_SIZE;
|
||||
if ( addr % BANK_SIZE == 0){
|
||||
crc = do_crc(crc_buffer, 0x1000);
|
||||
printf ("bank=0x%02x addr=0x%08x addr=0x%08x crc=0x%04x\n", bank, addr - 0x1000, addr, crc);
|
||||
ptr = crc_buffer;
|
||||
if ( addr % BANK_SIZE == 0) {
|
||||
bank++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bank = 0;
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
|
||||
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,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
|
||||
0, 5000);
|
||||
|
||||
|
||||
|
||||
+23
-1
@@ -1,20 +1,42 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* www.optixx.org
|
||||
*
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 07/21/2009 03:32:16 PM
|
||||
* Author: david@optixx.org
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#ifndef __CONFIH_H__
|
||||
#define __CONFIH_H__
|
||||
|
||||
|
||||
#define DEBUG 1
|
||||
#define DEBUG_USB 2
|
||||
#define DEBUG_USB_TRANS 4
|
||||
#define DEBUG_SRAM 8
|
||||
#define DEBUG_SRAM_RAW 16
|
||||
#define DEBUG_SREG 32
|
||||
#define DEBUG_CRC 64
|
||||
|
||||
#define REQ_STATUS_IDLE 0x01
|
||||
#define REQ_STATUS_UPLOAD 0x02
|
||||
#define REQ_STATUS_BULK_UPLOAD 0x03
|
||||
#define REQ_STATUS_BULK_NEXT 0x04
|
||||
#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_CRC_CHECK 0x01
|
||||
|
||||
+34
-9
@@ -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 <stdint.h>
|
||||
|
||||
@@ -5,6 +26,8 @@
|
||||
#include "uart.h"
|
||||
#include "config.h"
|
||||
#include "sram.h"
|
||||
#include "debug.h"
|
||||
#include "info.h"
|
||||
|
||||
extern FILE uart_stdout;
|
||||
|
||||
@@ -27,6 +50,7 @@ uint16_t do_crc(uint8_t * data, uint16_t size)
|
||||
uint16_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc_xmodem_update(crc, data[i]);
|
||||
|
||||
}
|
||||
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;
|
||||
uint32_t addr = 0;
|
||||
uint8_t req_bank = 0;
|
||||
sram_bulk_read_start(bottom_addr);
|
||||
|
||||
for (addr = bottom_addr; addr < top_addr; addr++) {
|
||||
if (addr && addr % 0x8000 == 0) {
|
||||
printf("crc_check_bulk: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
|
||||
if (addr && addr % bank_size == 0) {
|
||||
debug(DEBUG_CRC,"crc_check_bulk_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
|
||||
req_bank,addr,crc);
|
||||
req_bank++;
|
||||
crc = 0;
|
||||
@@ -57,23 +82,23 @@ void crc_check_bulk_memory(uint32_t bottom_addr,uint32_t top_addr)
|
||||
crc = crc_xmodem_update(crc, sram_bulk_read());
|
||||
sram_bulk_read_next();
|
||||
}
|
||||
sram_bulk_read_end();
|
||||
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);
|
||||
|
||||
sram_bulk_read_end();
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint8_t *buffer)
|
||||
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint32_t bank_size,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",
|
||||
if (addr && addr % bank_size == 0) {
|
||||
debug(DEBUG_CRC,"crc_check_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n",
|
||||
req_bank,addr,crc);
|
||||
req_bank++;
|
||||
crc = 0;
|
||||
|
||||
+22
-2
@@ -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__
|
||||
#define __CRC_H__
|
||||
@@ -9,8 +29,8 @@
|
||||
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_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);
|
||||
void crc_check_memory(uint32_t bottom_addr,uint32_t top_addr,uint32_t bank_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
|
||||
|
||||
+26
-6
@@ -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 <stdint.h>
|
||||
|
||||
@@ -5,25 +25,25 @@
|
||||
#include "uart.h"
|
||||
|
||||
|
||||
|
||||
extern FILE uart_stdout;
|
||||
|
||||
extern int debug_level; /* the higher, the more messages... */
|
||||
|
||||
#if defined(NO_DEBUG) && defined(__GNUC__)
|
||||
/* Nothing. debug has been "defined away" in debug.h already. */
|
||||
#else
|
||||
void debug(int level, char* format, ...) {
|
||||
#ifdef NO_DEBUG
|
||||
/* Empty body, so a good compiler will optimise calls
|
||||
to pmesg away */
|
||||
|
||||
#else
|
||||
va_list args;
|
||||
if (!(debug_level & level))
|
||||
return;
|
||||
va_start(args, format);
|
||||
printf(format, args);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
#endif /* NDEBUG */
|
||||
#endif /* NDEBUG && __GNUC__ */
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+23
-1
@@ -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__
|
||||
#define __DEBUG_H__
|
||||
|
||||
@@ -18,4 +40,4 @@ void debug(int level, char *format, ...);
|
||||
|
||||
|
||||
#endif /* DEBUG_H */
|
||||
|
||||
|
||||
|
||||
+34
-12
@@ -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 <stdint.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "info.h"
|
||||
#include "uart.h"
|
||||
#include "sram.h"
|
||||
|
||||
@@ -25,36 +47,36 @@ void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet)
|
||||
continue;
|
||||
}
|
||||
if (clear) {
|
||||
printf("*\n");
|
||||
info("*\n");
|
||||
clear = 0;
|
||||
}
|
||||
printf("%08lx:", addr + i);
|
||||
info("%08lx:", addr + i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
printf(" %02x", packet[i + j]);
|
||||
info(" %02x", packet[i + j]);
|
||||
}
|
||||
printf(" |");
|
||||
info(" |");
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (packet[i + j] >= 33 && packet[i + j] <= 126)
|
||||
printf("%c", packet[i + j]);
|
||||
info("%c", packet[i + j]);
|
||||
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;
|
||||
uint8_t byte;
|
||||
sram_bulk_read_start(bottom_addr);
|
||||
printf("%08lx:", bottom_addr);
|
||||
for ( addr = bottom_addr; addr < top_addr; addr++) {
|
||||
if (addr%0x16 == 0)
|
||||
printf("\n%08lx:", bottom_addr);
|
||||
if (addr%0x10 == 0)
|
||||
info("\n%08lx:", addr);
|
||||
byte = sram_bulk_read();
|
||||
sram_bulk_read_next();
|
||||
printf(" %02x", byte);
|
||||
info(" %02x", byte);
|
||||
}
|
||||
info("\n");
|
||||
sram_bulk_read_end();
|
||||
}
|
||||
|
||||
+23
-1
@@ -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__
|
||||
#define __DUMP_H__
|
||||
|
||||
@@ -5,8 +26,9 @@
|
||||
#include <stdint.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_memoryt(uint32_t bottom_addr, uint32_t top_addr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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"
|
||||
|
||||
void fifo_init(fifo_t * f, uint8_t * buffer, const uint8_t size)
|
||||
|
||||
@@ -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__
|
||||
#define __FIFO_H__
|
||||
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* www.optixx.org
|
||||
*
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 07/21/2009 03:32:16 PM
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
|
||||
#include "huffman-decode.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "info.h"
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#if DEBUG
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
#define V_NODE (-2)
|
||||
#define V_EOF (-1)
|
||||
|
||||
#define PREFIX_SIZE_B 32
|
||||
|
||||
#define ALLOC_ERROR {}
|
||||
|
||||
#undef BLOCK_ALLOC
|
||||
|
||||
typedef struct {
|
||||
int16_t value;
|
||||
void* left;
|
||||
void* right;
|
||||
} node_t;
|
||||
|
||||
#if HUFFMAN_USE_ADDR_16
|
||||
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint16_t)){
|
||||
#else
|
||||
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint32_t)){
|
||||
#endif
|
||||
ctx->tree = NULL;
|
||||
ctx->addr = 0;
|
||||
ctx->read_byte = rb_func;
|
||||
ctx->rbuffer_index = 8;
|
||||
}
|
||||
|
||||
#if HUFFMAN_USE_ADDR_16
|
||||
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx, uint16_t addr){
|
||||
#else
|
||||
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx, uint32_t addr){
|
||||
#endif
|
||||
ctx->addr = addr;
|
||||
}
|
||||
|
||||
static inline void prefix_increment(uint8_t* prefix){
|
||||
uint8_t i;
|
||||
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||
prefix[i] += 1;
|
||||
if(prefix[i]!=0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void prefix_shiftleft(uint8_t* prefix){
|
||||
uint8_t i;
|
||||
uint8_t c[2]={0,0};
|
||||
uint8_t ci=0;
|
||||
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||
c[ci] = (prefix[i])>>7;
|
||||
prefix[i]<<=1;
|
||||
ci ^= 1;
|
||||
prefix[i]|=c[ci];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_last_to_eof(node_t* start){
|
||||
node_t* current = start;
|
||||
while(current->value==V_NODE){
|
||||
current=current->right;
|
||||
}
|
||||
current->value=V_EOF;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
void print_tree(node_t* node){
|
||||
if(node->value==V_NODE){
|
||||
info("\n%p --> node->left=%p node->right=%p",node,node->left, node->right);
|
||||
print_tree(node->left);
|
||||
print_tree(node->right);
|
||||
}else{
|
||||
info("\n%p => %i",node,node->value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t build_tree(huffman_dec_ctx_t* ctx){
|
||||
uint16_t treesize;
|
||||
uint16_t treeindex=1;
|
||||
int8_t i,t;
|
||||
if(ctx->read_byte(ctx->addr++)!=0xC0)
|
||||
return 1;
|
||||
if(((treesize=ctx->read_byte(ctx->addr++))&0xFE)!=0xDE)
|
||||
return 1;
|
||||
treesize = (treesize&1)<<8;
|
||||
treesize += ctx->read_byte(ctx->addr++);
|
||||
if(treesize>0x1ff)
|
||||
return 2;
|
||||
#if BLOCK_ALLOC
|
||||
ctx->tree = malloc((2*treesize-1) * sizeof(node_t));
|
||||
#else
|
||||
ctx->tree = malloc(sizeof(node_t));
|
||||
#endif
|
||||
((node_t*)(ctx->tree))->value = V_NODE;
|
||||
uint16_t depth=0;
|
||||
uint16_t count=0;
|
||||
uint16_t v;
|
||||
uint8_t prefix[PREFIX_SIZE_B];
|
||||
uint8_t cdepth=0;
|
||||
node_t* current=ctx->tree;
|
||||
current->value = V_NODE;
|
||||
memset(prefix, 0, PREFIX_SIZE_B);
|
||||
do{
|
||||
while(count==0){
|
||||
depth++;
|
||||
count= ctx->read_byte(ctx->addr++);
|
||||
if(count==255)
|
||||
count += ctx->read_byte(ctx->addr++);
|
||||
}
|
||||
v = ctx->read_byte(ctx->addr++);
|
||||
if(v>0xff)
|
||||
return 3;
|
||||
--count;
|
||||
for(;cdepth<depth;++cdepth){
|
||||
prefix_shiftleft(prefix);
|
||||
}
|
||||
#if DEBUG
|
||||
printf("\n value %x => ",v);
|
||||
#endif
|
||||
current=ctx->tree;
|
||||
for(i=depth-1; i>=0; --i){
|
||||
t=(prefix[i/8])&(1<<(i%8));
|
||||
if(t==0){
|
||||
#if DEBUG
|
||||
printf("0");
|
||||
#endif
|
||||
if(current->left==NULL){
|
||||
#if BLOCK_ALLOC
|
||||
current->left=&(((node_t*)(ctx->tree))[treeindex++]);
|
||||
#else
|
||||
current->left=malloc(sizeof(node_t));
|
||||
#endif
|
||||
((node_t*)(current->left))->value = V_NODE;
|
||||
}
|
||||
current = current->left;
|
||||
} else {
|
||||
#if DEBUG
|
||||
printf("1");
|
||||
#endif
|
||||
if(current->right==NULL){
|
||||
#if BLOCK_ALLOC
|
||||
current->right=&(((node_t*)(ctx->tree))[treeindex++]);
|
||||
#else
|
||||
current->right=malloc( sizeof(node_t));
|
||||
#endif
|
||||
((node_t*)(current->right))->value=V_NODE;
|
||||
}
|
||||
current = current->right;
|
||||
}
|
||||
}
|
||||
#if !BLOCK_ALLOC
|
||||
if(current==NULL)
|
||||
ALLOC_ERROR
|
||||
#endif
|
||||
current->value=v;
|
||||
prefix_increment(prefix);
|
||||
}while(!(prefix[depth/8]&(1<<(depth%8))));
|
||||
#if DEBUG
|
||||
print_tree(ctx->tree);
|
||||
#endif
|
||||
set_last_to_eof(ctx->tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_tree(node_t* node){
|
||||
#if !BLOCK_ALLOC
|
||||
if(node->value==V_NODE){
|
||||
free_tree(node->left);
|
||||
free_tree(node->right);
|
||||
}
|
||||
#endif
|
||||
free(node);
|
||||
|
||||
}
|
||||
|
||||
static uint8_t read_bit(huffman_dec_ctx_t* ctx){
|
||||
uint16_t x;
|
||||
uint8_t t;
|
||||
if(ctx->rbuffer_index==8){
|
||||
x=ctx->read_byte(ctx->addr);
|
||||
ctx->addr++;
|
||||
if(t>0xff)
|
||||
return 0xFF;
|
||||
ctx->rbuffer = (uint8_t)x;
|
||||
ctx->rbuffer_index=0;
|
||||
}
|
||||
t=(ctx->rbuffer)>>7;
|
||||
ctx->rbuffer<<=1;
|
||||
ctx->rbuffer_index++;
|
||||
return t;
|
||||
}
|
||||
|
||||
uint16_t huffman_dec_byte(huffman_dec_ctx_t* ctx){
|
||||
node_t* current=ctx->tree;
|
||||
uint8_t t;
|
||||
if(current==NULL){
|
||||
#if DEBUG
|
||||
printf("\nbuild tree");
|
||||
#endif
|
||||
t=build_tree(ctx);
|
||||
if(t!=0){
|
||||
#if DEBUG
|
||||
printf("\n!!! building tree failed !!!\r\n");
|
||||
#endif
|
||||
return 0xFFFF;
|
||||
}
|
||||
#if DEBUG
|
||||
printf("\ntree build successful");
|
||||
#endif
|
||||
current=ctx->tree;
|
||||
}
|
||||
while(current->value==V_NODE){
|
||||
t=read_bit(ctx);
|
||||
if(t==0xFF)
|
||||
goto eof_detected;
|
||||
if(t==0){
|
||||
current=current->left;
|
||||
} else {
|
||||
current=current->right;
|
||||
}
|
||||
}
|
||||
if(current->value!=V_EOF){
|
||||
return current->value;
|
||||
}
|
||||
eof_detected:
|
||||
free_tree(ctx->tree);
|
||||
ctx->tree = NULL;
|
||||
return 0xFFFF;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* www.optixx.org
|
||||
*
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 07/21/2009 03:32:16 PM
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#ifndef AVR_HUFFMAN_DECODE_H_
|
||||
#define AVR_HUFFMAN_DECODE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define HUFFMAN_USE_ADDR_16 1
|
||||
|
||||
typedef struct {
|
||||
void* tree;
|
||||
uint8_t rbuffer;
|
||||
uint8_t rbuffer_index;
|
||||
#if HUFFMAN_USE_ADDR_16
|
||||
uint16_t(*read_byte)(uint16_t addr);
|
||||
uint16_t addr;
|
||||
#else
|
||||
uint16_t(*read_byte)(uint32_t addr);
|
||||
uint32_t addr;
|
||||
#endif
|
||||
} huffman_dec_ctx_t;
|
||||
|
||||
#if HUFFMAN_USE_ADDR_16
|
||||
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint16_t));
|
||||
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx,uint16_t addr);
|
||||
#else
|
||||
void huffman_dec_init(huffman_dec_ctx_t* ctx, uint16_t(*rb_func)(uint32_t));
|
||||
void huffman_dec_set_addr(huffman_dec_ctx_t* ctx,uint32_t addr);
|
||||
#endif
|
||||
|
||||
|
||||
uint16_t huffman_dec_byte(huffman_dec_ctx_t* ctx);
|
||||
|
||||
#endif /* AVR_HUFFMAN_DECODE_H_ */
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef __FIFO_H__
|
||||
#define __FIFO_H__
|
||||
|
||||
#define ROM_BUFFER_SIZE 27288
|
||||
#define ROM_HUFFMAN_SIZE 27288
|
||||
#define ROM_RLE_SIZE 30344
|
||||
|
||||
#endif
|
||||
+336
-81
@@ -1,8 +1,31 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* www.optixx.org
|
||||
*
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 07/21/2009 03:32:16 PM
|
||||
* Author: david@optixx.org
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h> /* for sei() */
|
||||
#include <util/delay.h> /* for _delay_ms() */
|
||||
#include <stdlib.h>
|
||||
#include <avr/pgmspace.h> /* required by usbdrv.h */
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
#include "usbdrv.h"
|
||||
#include "oddebug.h" /* This is also an example for using debug
|
||||
@@ -12,18 +35,30 @@
|
||||
#include "uart.h"
|
||||
#include "sram.h"
|
||||
#include "debug.h"
|
||||
#include "info.h"
|
||||
#include "dump.h"
|
||||
#include "crc.h"
|
||||
#include "usb_bulk.h"
|
||||
#include "timer.h"
|
||||
#include "watchdog.h"
|
||||
#include "huffman-decode.h"
|
||||
#include "rle.h"
|
||||
#include "loader.h"
|
||||
#include "shared_memory.h"
|
||||
|
||||
|
||||
extern const char _rom[] PROGMEM;
|
||||
extern FILE uart_stdout;
|
||||
|
||||
uint8_t debug_level = ( DEBUG | DEBUG_USB );
|
||||
uint8_t debug_level = ( DEBUG | DEBUG_USB | DEBUG_CRC );
|
||||
|
||||
uint8_t read_buffer[TRANSFER_BUFFER_SIZE];
|
||||
uint32_t req_addr = 0;
|
||||
uint32_t req_addr_end = 0;
|
||||
uint32_t req_size;
|
||||
uint8_t req_bank;
|
||||
uint16_t req_bank_size;
|
||||
uint32_t req_bank_size;
|
||||
uint16_t req_bank_cnt;
|
||||
uint8_t req_state = REQ_STATUS_IDLE;
|
||||
uint8_t rx_remaining = 0;
|
||||
uint8_t tx_remaining = 0;
|
||||
@@ -33,6 +68,9 @@ uint8_t data_buffer[4];
|
||||
uint32_t addr;
|
||||
uint16_t crc = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
{
|
||||
|
||||
@@ -50,10 +88,10 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
|
||||
req_bank = 0;
|
||||
rx_remaining = 0;
|
||||
req_bank_size = 1 << rq->wValue.word;
|
||||
req_bank_size = (uint32_t)1 << rq->wValue.word;
|
||||
sync_errors = 0;
|
||||
crc = 0;
|
||||
debug(DEBUG_USB,"USB_UPLOAD_INIT: bank_size=0x%x\n", req_bank_size);
|
||||
debug(DEBUG_USB,"USB_UPLOAD_INIT: bank_size=0x%08lx\n", req_bank_size);
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
@@ -74,10 +112,10 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
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);
|
||||
debug(DEBUG_USB,"USB_UPLOAD_ADDR: 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));
|
||||
|
||||
}
|
||||
if (req_addr && req_addr % req_bank_size == 0) {
|
||||
@@ -85,6 +123,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
req_bank, req_addr);
|
||||
|
||||
req_bank++;
|
||||
//shared_memory_put(SHARED_MEM_CMD_UPLOAD_PROGESS,req_bank);
|
||||
}
|
||||
ret_len = USB_MAX_TRANS;
|
||||
/*
|
||||
@@ -102,54 +141,82 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
} 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;
|
||||
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;
|
||||
|
||||
sync_errors = 0;
|
||||
debug(DEBUG_USB,"USB_BULK_UPLOAD_INIT: bank_size=0x%x\n", req_bank_size);
|
||||
debug(DEBUG_USB,"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_put(SHARED_MEM_CMD_BANK_COUNT,req_bank_cnt);
|
||||
if (req_addr == 0x000000){
|
||||
timer_start();
|
||||
}
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
} 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_addr = rq->wValue.word;
|
||||
req_addr = req_addr << 16;
|
||||
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);
|
||||
ret_len = 0;
|
||||
rx_remaining = rq->wLength.word;
|
||||
|
||||
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_put(SHARED_MEM_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) {
|
||||
|
||||
if (req_state != REQ_STATUS_BULK_UPLOAD){
|
||||
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: ERROR state is not REQ_STATUS_BULK_UPLOAD\n");
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
req_state = REQ_STATUS_BULK_UPLOAD;
|
||||
req_addr = rq->wValue.word;
|
||||
req_addr = req_addr << 16;
|
||||
req_addr = req_addr | rq->wIndex.word;
|
||||
rx_remaining = rq->wLength.word;
|
||||
ret_len = USB_MAX_TRANS;
|
||||
if (req_addr && req_addr % req_bank_size == 0) {
|
||||
debug(DEBUG_USB,"USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr= 0x%08lx \n",
|
||||
req_bank, req_addr);
|
||||
#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++;
|
||||
timer_start();
|
||||
shared_memory_put(SHARED_MEM_CMD_BANK_CURRENT,req_bank);
|
||||
sram_bulk_write_start(req_addr);
|
||||
|
||||
}
|
||||
ret_len = USB_MAX_TRANS;
|
||||
/*
|
||||
@@ -163,7 +230,9 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
debug(DEBUG_USB,"USB_BULK_UPLOAD_END:\n");
|
||||
req_state = REQ_STATUS_IDLE;
|
||||
sram_bulk_write_end();
|
||||
shared_memory_put(SHARED_MEM_CMD_UPLOAD_END,0);
|
||||
ret_len = 0;
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -172,14 +241,28 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
req_addr = req_addr << 16;
|
||||
req_addr = req_addr | rq->wIndex.word;
|
||||
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;
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
} else if (rq->bRequest == USB_SNES_BOOT) {
|
||||
req_state = REQ_STATUS_BOOT;
|
||||
debug(DEBUG_USB,"USB_SNES_BOOT: ");
|
||||
} else if (rq->bRequest == USB_MODE_SNES) {
|
||||
req_state = REQ_STATUS_SNES;
|
||||
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;
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
@@ -197,7 +280,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
tx_remaining = 2;
|
||||
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[1] = (crc >> 8) & 0xff;
|
||||
ret_len = 2;
|
||||
@@ -226,11 +309,12 @@ void test_read_write(){
|
||||
}
|
||||
addr = 0x000000;
|
||||
while (addr++ <= 0x0000ff){
|
||||
printf("read addr=0x%08lx %x\n",addr,sram_read(addr));
|
||||
info("read addr=0x%08lx %x\n",addr,sram_read(addr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void test_bulk_read_write(){
|
||||
|
||||
uint8_t i;
|
||||
@@ -239,7 +323,7 @@ void test_bulk_read_write(){
|
||||
addr = 0x000000;
|
||||
i = 0;
|
||||
sram_bulk_write_start(addr);
|
||||
while (addr++ <= 0x3fffff){
|
||||
while (addr++ <= 0x8000){
|
||||
sram_bulk_write(i++);
|
||||
sram_bulk_write_next();
|
||||
}
|
||||
@@ -247,10 +331,10 @@ void test_bulk_read_write(){
|
||||
|
||||
addr = 0x000000;
|
||||
sram_bulk_read_start(addr);
|
||||
while (addr <= 0x3fffff){
|
||||
printf("addr=0x%08lx %x\n",addr,sram_bulk_read());
|
||||
while (addr <= 0x8000){
|
||||
info("addr=0x%08lx %x\n",addr,sram_bulk_read());
|
||||
sram_bulk_read_next();
|
||||
addr ++;
|
||||
addr++;
|
||||
}
|
||||
sram_bulk_read_end();
|
||||
}
|
||||
@@ -264,7 +348,7 @@ void test_non_zero_memory(uint32_t bottom_addr,uint32_t top_addr)
|
||||
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);
|
||||
info("addr=0x%08lx c=0x%x\n",addr,c);
|
||||
sram_bulk_read_next();
|
||||
}
|
||||
sram_bulk_read_end();
|
||||
@@ -273,62 +357,233 @@ void test_non_zero_memory(uint32_t bottom_addr,uint32_t top_addr)
|
||||
|
||||
|
||||
void test_crc(){
|
||||
printf("test_crc: clear\n");
|
||||
info("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");
|
||||
info("test_crc: crc\n");
|
||||
crc_check_bulk_memory(0x000000,0x10000,0x8000);
|
||||
info("test_crc: check\n");
|
||||
test_non_zero_memory(0x000000,0x10000);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t read_byte_pgm(uint16_t addr){
|
||||
return pgm_read_byte((PGM_VOID_P)addr);
|
||||
}
|
||||
|
||||
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! */
|
||||
void decompress_huffman(PGM_VOID_P addr, uint16_t(*fp)(uint16_t)){
|
||||
uint16_t c;
|
||||
uint32_t i = 0;
|
||||
huffman_dec_ctx_t ctx;
|
||||
info("ok1\n");
|
||||
huffman_dec_init(&ctx, fp);
|
||||
info("ok2\n");
|
||||
huffman_dec_set_addr(&ctx, (uint16_t)addr);
|
||||
info("ok3\n");
|
||||
while(1){
|
||||
info("ok4\n");
|
||||
i++;
|
||||
c=huffman_dec_byte(&ctx);
|
||||
if (i%1024==0)
|
||||
info(".");
|
||||
if(c>0xff){
|
||||
return;
|
||||
}
|
||||
c&=0xff;
|
||||
sram_bulk_write(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void usb_connect(){
|
||||
uint8_t i = 0;
|
||||
info("USB init\n");
|
||||
usbDeviceDisconnect(); /* enforce re-enumeration, do this while */
|
||||
cli();
|
||||
printf("USB disconnect\n");
|
||||
info("USB disconnect\n");
|
||||
i = 10;
|
||||
while (--i) { /* fake USB disconnect for > 250 ms */
|
||||
led_on();
|
||||
_delay_ms(35);
|
||||
led_off();
|
||||
_delay_ms(65);
|
||||
|
||||
}
|
||||
led_on();
|
||||
usbDeviceConnect();
|
||||
printf("USB connect\n");
|
||||
sei();
|
||||
printf("USB poll\n");
|
||||
while (req_state != REQ_STATUS_BOOT){
|
||||
usbPoll();
|
||||
}
|
||||
printf("USB poll done\n");
|
||||
usbDeviceDisconnect();
|
||||
printf("USB disconnect\n");
|
||||
crc_check_bulk_memory(0x000000,0x1000);
|
||||
info("USB connect\n");
|
||||
}
|
||||
|
||||
|
||||
void boot_startup_rom(){
|
||||
|
||||
printf("Disable snes WR\n");
|
||||
snes_wr_disable();
|
||||
printf("Use Snes lowrom\n");
|
||||
|
||||
info("Activate AVR bus\n");
|
||||
avr_bus_active();
|
||||
|
||||
info("IRQ off\n");
|
||||
snes_irq_lo();
|
||||
snes_irq_off();
|
||||
|
||||
snes_lorom();
|
||||
printf("Activate Snes bus\n");
|
||||
info("Set Snes lowrom \n");
|
||||
|
||||
|
||||
info("Huffman decompress to 0x010000\n",(void*)_rom);
|
||||
sram_bulk_write_start(0x010000);
|
||||
decompress_huffman(&_rom,read_byte_pgm);
|
||||
sram_bulk_write_end();
|
||||
info("RLE decompress to 0x000000\n",(void*)_rom);
|
||||
rle_decode_sram(0x010000, ROM_RLE_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(100);
|
||||
info("Reset Snes\n");
|
||||
send_reset();
|
||||
_delay_ms(100);
|
||||
#if 0
|
||||
uint8_t i = 0;
|
||||
i = 20;
|
||||
info("Wait");
|
||||
while (--i){
|
||||
_delay_ms(500);
|
||||
info(".");
|
||||
}
|
||||
info("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
uart_init();
|
||||
stdout = &uart_stdout;
|
||||
|
||||
info("Sytem start\n");
|
||||
system_init();
|
||||
|
||||
#if 0
|
||||
test_read_write();
|
||||
test_bulk_read_write();
|
||||
test_crc();
|
||||
while(1);
|
||||
#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();
|
||||
info("USB poll\n");
|
||||
while (req_state != REQ_STATUS_SNES){
|
||||
usbPoll();
|
||||
}
|
||||
shared_memory_put(SHARED_MEM_CMD_TERMINATE,0);
|
||||
info("USB poll done\n");
|
||||
snes_reset_hi();
|
||||
snes_reset_off();
|
||||
snes_irq_lo();
|
||||
snes_irq_off();
|
||||
info("IRQ off\n");
|
||||
set_rom_mode();
|
||||
snes_wr_disable();
|
||||
info("Disable snes WR\n");
|
||||
snes_bus_active();
|
||||
info("Activate Snes bus\n");
|
||||
_delay_ms(100);
|
||||
info("Reset Snes\n");
|
||||
send_reset();
|
||||
|
||||
info("Poll\n");
|
||||
while (req_state != REQ_STATUS_AVR){
|
||||
|
||||
usbPoll();
|
||||
|
||||
#ifdef DO_IRQ
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+21
-13
@@ -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__
|
||||
#define __REQUESTS_H__
|
||||
@@ -29,6 +35,8 @@
|
||||
#define USB_BULK_UPLOAD_ADDR 7
|
||||
#define USB_BULK_UPLOAD_NEXT 8
|
||||
#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__ */
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
uint8_t rle_decode_sram(uint32_t 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;
|
||||
#define INBYTE(b) \
|
||||
do { \
|
||||
if ( --in_len < 0 ) { \
|
||||
return 1; \
|
||||
} \
|
||||
b = sram_read(in_addr);\
|
||||
in_addr++;\
|
||||
} while(0)
|
||||
|
||||
#define OUTBYTE(b) \
|
||||
do { \
|
||||
sram_write(out_addr,b);\
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* 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);
|
||||
uint8_t rle_decode_sram(uint32_t in_addr, int32_t in_len, uint32_t out_addr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* 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_save(){
|
||||
scratchpad_state = sram_read(SHARED_MEM_LOC_STATE);
|
||||
scratchpad_cmd = sram_read(SHARED_MEM_LOC_CMD);
|
||||
scratchpad_payload = sram_read(SHARED_MEM_LOC_PAYLOAD);
|
||||
}
|
||||
|
||||
void shared_memory_scratchpad_restore(){
|
||||
sram_write(SHARED_MEM_LOC_STATE, scratchpad_state);
|
||||
sram_write(SHARED_MEM_LOC_CMD, scratchpad_cmd);
|
||||
sram_write(SHARED_MEM_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_put(uint8_t cmd, uint8_t value){
|
||||
|
||||
info("Write shared memory 0x%04x=0x%02x 0x%04x=0x%02x \n",SHARED_MEM_LOC_CMD,cmd,SHARED_MEM_LOC_PAYLOAD,value);
|
||||
|
||||
shared_memory_scratchpad_save();
|
||||
shared_memory_irq_hook();
|
||||
|
||||
sram_write(SHARED_MEM_LOC_STATE,SHARED_MEM_SNES_ACK);
|
||||
sram_write(SHARED_MEM_LOC_CMD,cmd);
|
||||
sram_write(SHARED_MEM_LOC_PAYLOAD,value);
|
||||
|
||||
snes_hirom();
|
||||
snes_wr_disable();
|
||||
snes_bus_active();
|
||||
_delay_ms(50);
|
||||
|
||||
|
||||
avr_bus_active();
|
||||
snes_irq_lo();
|
||||
snes_irq_off();
|
||||
snes_lorom();
|
||||
snes_wr_disable();
|
||||
|
||||
shared_memory_scratchpad_restore();
|
||||
shared_memory_irq_restore();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* ________ .__ __ ________ ____ ________
|
||||
* \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
|
||||
* / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
|
||||
* / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
|
||||
* \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
|
||||
* \__> \/ \/ \/ \/ \/
|
||||
*
|
||||
* 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_SNES_ACK 0xa5
|
||||
#define SHARED_MEM_SNES_RTS 0x5a
|
||||
|
||||
|
||||
#define SHARED_MEM_CMD_BANK_COUNT 0
|
||||
#define SHARED_MEM_CMD_BANK_CURRENT 1
|
||||
|
||||
#define SHARED_MEM_CMD_UPLOAD_START 3
|
||||
#define SHARED_MEM_CMD_UPLOAD_END 4
|
||||
#define SHARED_MEM_CMD_UPLOAD_PROGESS 5
|
||||
#define SHARED_MEM_CMD_TERMINATE 6
|
||||
|
||||
|
||||
#define SHARED_MEM_LOC_STATE 0x000000
|
||||
#define SHARED_MEM_LOC_CMD 0x000001
|
||||
#define SHARED_MEM_LOC_PAYLOAD 0x000002
|
||||
|
||||
#define SHARED_IRQ_LOC_LO 0x00fffe
|
||||
#define SHARED_IRQ_LOC_HI 0x00ffff
|
||||
|
||||
|
||||
#define SHARED_IRQ_HANDLER_LO 0x00
|
||||
#define SHARED_IRQ_HANDLER_HI 0x10
|
||||
|
||||
void shared_memory_put(uint8_t cmd, uint8_t value);
|
||||
|
||||
#endif
|
||||
+44
-6
@@ -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 <stdint.h>
|
||||
#include <avr/io.h>
|
||||
@@ -8,6 +29,7 @@
|
||||
#include "sram.h"
|
||||
#include "uart.h"
|
||||
#include "debug.h"
|
||||
#include "info.h"
|
||||
|
||||
void system_init(void)
|
||||
{
|
||||
@@ -28,24 +50,28 @@ void system_init(void)
|
||||
DDRC &= ~ (1 << SNES_WR_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)
|
||||
| (1 << AVR_ADDR_UP_PIN)
|
||||
| (1 << AVR_ADDR_LOAD_PIN)
|
||||
| (1 << SNES_WR_PIN));
|
||||
| (1 << AVR_ADDR_LOAD_PIN));
|
||||
|
||||
//| (1 << SNES_WR_PIN));
|
||||
/*-------------------------------------------------*/
|
||||
|
||||
DDRB |= ( (1 << AVR_RD_PIN)
|
||||
| (1 << AVR_WR_PIN)
|
||||
| (1 << AVR_CS_PIN)
|
||||
| (1 << SNES_IRQ_PIN));
|
||||
|
||||
|
||||
PORTB |= ( (1 << AVR_RD_PIN)
|
||||
| (1 << AVR_WR_PIN)
|
||||
| (1 << AVR_CS_PIN)
|
||||
| (1 << SNES_IRQ_PIN));
|
||||
|
||||
/*-------------------------------------------------*/
|
||||
|
||||
|
||||
@@ -107,6 +133,7 @@ void sram_bulk_read_start(uint32_t addr)
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
|
||||
}
|
||||
|
||||
inline void sram_bulk_read_next(void)
|
||||
@@ -121,6 +148,7 @@ inline void sram_bulk_read_next(void)
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +159,7 @@ inline uint8_t sram_bulk_read(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_CS_PORT |= (1 << AVR_CS_PIN);
|
||||
@@ -184,11 +212,12 @@ void sram_bulk_write_start(uint32_t addr)
|
||||
sreg_set(addr);
|
||||
|
||||
AVR_WR_PORT &= ~(1 << AVR_WR_PIN);
|
||||
|
||||
}
|
||||
|
||||
inline void sram_bulk_write_next(void)
|
||||
{
|
||||
AVR_RD_PORT |= (1 << AVR_RD_PIN);
|
||||
AVR_WR_PORT |= (1 << AVR_WR_PIN);
|
||||
counter_up();
|
||||
AVR_WR_PORT &= ~(1 << AVR_WR_PIN);
|
||||
}
|
||||
@@ -196,7 +225,7 @@ inline void sram_bulk_write_next(void)
|
||||
inline void sram_bulk_write( uint8_t data)
|
||||
{
|
||||
AVR_DATA_PORT = data;
|
||||
}
|
||||
}
|
||||
|
||||
void sram_bulk_write_end(void)
|
||||
{
|
||||
@@ -220,9 +249,18 @@ void sram_write(uint32_t addr, uint8_t data)
|
||||
sreg_set(addr);
|
||||
|
||||
AVR_WR_PORT &= ~(1 << AVR_WR_PIN);
|
||||
|
||||
|
||||
AVR_DATA_PORT = data;
|
||||
|
||||
|
||||
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_data_in();
|
||||
|
||||
+43
-4
@@ -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__
|
||||
#define __SRAM_H__
|
||||
|
||||
@@ -56,9 +78,23 @@
|
||||
#define SNES_IRQ_DIR DDRB
|
||||
#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 ---------------------------- */
|
||||
@@ -120,9 +156,11 @@
|
||||
#define AVR_SNES_SW_PIN PD5
|
||||
|
||||
#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_DIR DDRD
|
||||
@@ -136,6 +174,7 @@
|
||||
#define SNES_WR_EN_PIN PD7
|
||||
|
||||
#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))
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
@@ -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__
|
||||
#define __UART_H__
|
||||
|
||||
|
||||
+30
-3
@@ -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/pgmspace.h> /* required by usbdrv.h */
|
||||
@@ -14,6 +34,8 @@
|
||||
#include "uart.h"
|
||||
#include "sram.h"
|
||||
#include "debug.h"
|
||||
#include "info.h"
|
||||
|
||||
#include "crc.h"
|
||||
#include "usb_bulk.h"
|
||||
|
||||
@@ -32,8 +54,9 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
uint8_t i;
|
||||
|
||||
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);
|
||||
len = rx_remaining;
|
||||
}
|
||||
@@ -42,6 +65,8 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
|
||||
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);
|
||||
debug(DEBUG_USB_TRANS,"usbFunctionWrite %02x %02x %02x %02x %02x %02x %02x %x\n",
|
||||
data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
|
||||
sram_copy(req_addr, data, len);
|
||||
req_addr += len;
|
||||
} else if (req_state == REQ_STATUS_BULK_UPLOAD) {
|
||||
@@ -53,9 +78,11 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
|
||||
i = len;
|
||||
while(i--){
|
||||
sram_bulk_write(*ptr++);
|
||||
counter_up();
|
||||
sram_bulk_write_next();
|
||||
}
|
||||
}
|
||||
/* test this */
|
||||
//return rx_remaining == 0
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -72,4 +99,4 @@ uint8_t usbFunctionRead(uint8_t * data, uint8_t len)
|
||||
data++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 usbFunctionRead(uint8_t * data, uint8_t len);
|
||||
|
||||
#endif
|
||||
|
||||
+24
-2
@@ -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
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* 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
|
||||
* 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
|
||||
* interval. The value is in milliseconds and must not be less than 10 ms for
|
||||
* low speed devices.
|
||||
@@ -141,7 +163,7 @@ section at the end of this file).
|
||||
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
|
||||
* 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
|
||||
* in a single control-in or control-out transfer. Note that the capability
|
||||
* for long transfers increases the driver size.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+476
-286
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.
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.
@@ -0,0 +1,71 @@
|
||||
import binascii
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
LEN = 2**16
|
||||
|
||||
TARGET="/Users/david/Devel/arch/avr/code/quickdev16/avr/usbload"
|
||||
HUFFMAN_ENCODER="/Users/david/Devel/arch/avr/code/quickdev16/tools/huffman/huffman-encode"
|
||||
data = open(sys.argv[1],"r").read()
|
||||
print "Load %s, %i bytes" % (sys.argv[1],len(data))
|
||||
data = data[:LEN]
|
||||
print "Use %i bytes" % (len(data))
|
||||
data = binascii.rlecode_hqx(data)
|
||||
print "RLE crunch (%i) bytes" % (len(data))
|
||||
|
||||
binfile = open("/tmp/loader.rle","w")
|
||||
binfile.write(data)
|
||||
binfile.close()
|
||||
rle_size = len(data)
|
||||
|
||||
cmd = "%s /tmp/loader.rle" % HUFFMAN_ENCODER
|
||||
os.system(cmd)
|
||||
data = open("/tmp/loader.rle.hfm","r").read()
|
||||
print "HUFFMAN crunch (%i) bytes" % (len(data))
|
||||
huffman_size = len(data)
|
||||
|
||||
os.unlink("/tmp/loader.rle")
|
||||
os.unlink("/tmp/loader.rle.hfm")
|
||||
|
||||
cfile = open("/tmp/loader.c","w")
|
||||
hfile = open("/tmp/loader.h","w")
|
||||
|
||||
hfile.write('''
|
||||
#ifndef __FIFO_H__
|
||||
#define __FIFO_H__
|
||||
|
||||
#define ROM_BUFFER_SIZE %i
|
||||
#define ROM_HUFFMAN_SIZE %i
|
||||
#define ROM_RLE_SIZE %i
|
||||
|
||||
#endif
|
||||
''' % (len(data), huffman_size, rle_size))
|
||||
|
||||
cfile.write('''/*
|
||||
File: %s
|
||||
Time: %s
|
||||
*/
|
||||
#include <avr/pgmspace.h>
|
||||
#include <loader.h>
|
||||
|
||||
const char _rom[ROM_BUFFER_SIZE] PROGMEM = {
|
||||
''' % (sys.argv[1],time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())))
|
||||
|
||||
for idx,c in enumerate(data):
|
||||
c = ord(c)
|
||||
if idx<len(data)-1:
|
||||
cfile.write("0x%02x," % c)
|
||||
else:
|
||||
cfile.write("0x%02x" % c)
|
||||
if idx and idx%16==0:
|
||||
cfile.write("\n")
|
||||
cfile.write('''
|
||||
};
|
||||
''')
|
||||
cfile.close()
|
||||
|
||||
os.rename("/tmp/loader.c", os.path.join(TARGET,"loader.c"))
|
||||
os.rename("/tmp/loader.h", os.path.join(TARGET,"loader.h"))
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import web
|
||||
from subprocess import *
|
||||
urls = ('/upload', 'Upload')
|
||||
|
||||
class Upload:
|
||||
def GET(self):
|
||||
return """<html><head></head><body>
|
||||
<form method="POST" enctype="multipart/form-data" action="">
|
||||
<input type="file" name="myfile" />
|
||||
<br/>
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</body></html>"""
|
||||
|
||||
def POST(self):
|
||||
obj = web.input(myfile={})
|
||||
filedir = '/Users/david/Devel/arch/avr/code/quickdev16/roms' # change this to the directory you want to store the file in.
|
||||
if 'myfile' in obj:
|
||||
web.debug("Upload file %s" % obj['myfile'].filename)
|
||||
filepath = obj.myfile.filename.replace('\\','/')
|
||||
filename = filepath.split('/')[-1]
|
||||
foutname = filedir +'/'+ filename
|
||||
web.debug("Write to %s" % foutname)
|
||||
fout = open(foutname,'w')
|
||||
fout.write( obj.myfile.file.read())
|
||||
fout.close()
|
||||
|
||||
cmd = "ucon64 --port=usb --xsnesram %s " % foutname
|
||||
web.debug("Execute: %s" % cmd)
|
||||
p = Popen(cmd, shell=True, bufsize=128,
|
||||
stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
|
||||
stdout,stderr = p.communicate()
|
||||
return '''<html><head></head><body>Out: %s <br/>Err: %s</body></html>''' % (
|
||||
stdout.replace("\n","<br/>").replace("\r","<br/>"),
|
||||
stderr.replace("\n","<br/>"))
|
||||
raise web.seeother('/upload')
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = web.application(urls, globals())
|
||||
app.run()
|
||||
@@ -0,0 +1,2 @@
|
||||
ln -s `pwd`/webpy/web .
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user