archive MK1 AVR source

This commit is contained in:
ikari 2010-09-06 23:51:48 +02:00
parent a6d66e7a8b
commit a9b84c3e0b
54 changed files with 1220 additions and 793 deletions

View File

@ -673,6 +673,8 @@ longwait0
; --------change region in eeprom and die--------
die
movlw 0x3a ;wait 50ms before writing
call longwait ;("error" might be due to power loss)
banksel EEADR
clrw
movwf EEADR

619
mk1-src/Makefile Normal file
View File

@ -0,0 +1,619 @@
# Hey Emacs, this is a -*- makefile -*-
# Define version number
MAJOR = 0
MINOR = 0
PATCHLEVEL = 1
FIX =
# Forces bootloader version to 0, comment out for release
#PRERELEASE =
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Joerg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
#
#
# Extensively modified for sd2iec by Ingo Korb
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# Read configuration file
ifdef CONFIG
CONFIGSUFFIX = $(CONFIG:config%=%)
else
CONFIG = config
CONFIGSUFFIX =
endif
# Enable verbose compilation with "make V=1"
ifdef V
Q :=
E := @:
else
Q := @
E := @echo
endif
# Include the configuration file
include $(CONFIG)
# Set MCU name and length of binary for bootloader
# WARNING: Fuse settings not tested!
MCU := $(CONFIG_MCU)
ifeq ($(MCU),atmega128)
BINARY_LENGTH = 0x1f000
# EFUSE = 0xff
# HFUSE = 0x91
# LFUSE = 0xaf
else ifeq ($(MCU),atmega1281)
BINARY_LENGTH = 0x1f000
BOOTLDRSIZE = 0x0800
EFUSE = 0xff
HFUSE = 0xd2
LFUSE = 0xfc
else ifeq ($(MCU),atmega2561)
BINARY_LENGTH = 0x3f000
EFUSE = 0xfd
HFUSE = 0x93
LFUSE = 0xef
else ifeq ($(MCU),atmega644)
BINARY_LENGTH = 0xf000
EFUSE = 0xfd
HFUSE = 0x91
# LFUSE = 0xef
LFUSE = 0xaf
else ifeq ($(MCU),atmega644p)
BINARY_LENGTH = 0xf000
EFUSE = 0xfd
HFUSE = 0x91
LFUSE = 0xef
else
.PHONY: nochip
nochip:
@echo '=============================================================='
@echo 'No known target chip specified.'
@echo
@echo 'Please edit the Makefile.'
@exit 1
endif
# Directory for all generated files
OBJDIR := obj-$(CONFIG_MCU:atmega%=m%)$(CONFIGSUFFIX)
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = $(OBJDIR)/sd2snes
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c ff.c utils.c led.c diskio.c sdcard.c spi.c crc7.c snes.c fpga.c memory.c crc16.c fileops.c fpga_spi.c smc.c filetypes.c
ifeq ($(CONFIG_UART_DEBUG),y)
SRC += uart.c
endif
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
# Use s -mcall-prologues when you really need size...
OPT = s
#OPT = 3 -finline-functions
# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS = -DF_CPU=$(CONFIG_MCU_FREQ)UL
# Calculate bootloader version
ifdef PRERELEASE
BOOT_VERSION := 0
else
BOOT_VERSION := 0x$(MAJOR)$(MINOR)$(PATCHLEVEL)$(FIX)
endif
# Create a version number define
ifdef PATCHLEVEL
ifdef FIX
PROGRAMVERSION := $(MAJOR).$(MINOR).$(PATCHLEVEL).$(FIX)
else
PROGRAMVERSION := $(MAJOR).$(MINOR).$(PATCHLEVEL)
BOOT_VERSION := $(BOOT_VERSION)0
endif
else
PROGRAMVERSION := $(MAJOR).$(MINOR)
BOOT_VERSION := $(BOOT_VERSION)00
endif
ifdef PRERELEASE
PROGRAMVERSION := $(PROGRAMVERSION)$(PRERELEASE)
endif
LONGVERSION := -$(CONFIG_MCU:atmega%=m%)$(CONFIGSUFFIX)
CDEFS += -DVERSION=\"$(PROGRAMVERSION)\" -DLONGVERSION=\"$(LONGVERSION)\"
# Place -I options here
CINCS =
# Define programs and commands.
# CC must be defined here to generate the correct CFLAGS
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
COPY = cp
WINSHELL = cmd
#---------------- Compiler Options ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes -Werror
CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst)
CFLAGS += -I$(OBJDIR)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS += -ffunction-sections -fdata-sections
#CFLAGS += -mcall-prologues
# these are needed for GCC 4.3.2, which is more aggressive at inlining
# gcc-4.2 knows one of those, but it tends to increase code size
ifeq ($(shell $(CC) --version|gawk -f gcctest.awk),YES)
CFLAGS += --param inline-call-cost=3
CFLAGS += -fno-inline-small-functions
CFLAGS += -fno-move-loop-invariants
CFLAGS += -fno-split-wide-types
# turn these on to keep the functions in the same order as in the source
# this is only useful if you're looking at disassembly
#CFLAGS += -fno-reorder-blocks
#CFLAGS += -fno-reorder-blocks-and-partition
#CFLAGS += -fno-reorder-functions
#CFLAGS += -fno-toplevel-reorder
endif
ifeq ($(CONFIG_STACK_TRACKING),y)
CFLAGS += -finstrument-functions
endif
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(OBJDIR)/$(<:.S=.lst),-gstabs -I$(OBJDIR)
#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
#---------------- External Memory Options ----------------
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
LDFLAGS += -Wl,--gc-sections
ifeq ($(CONFIG_LINKER_RELAX),y)
LDFLAGS += -Wl,-O9,--relax
endif
#---------------- Programming Options (avrdude) ----------------
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 stk500v2
#
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = dragon_isp
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = usb # programmer connected to serial device
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
# AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Allow fuse overrides from the config file
ifdef CONFIG_EFUSE
EFUSE := CONFIG_EFUSE
endif
ifdef CONFIG_HFUSE
HFUSE := CONFIG_HFUSE
endif
ifdef CONFIG_LFUSE
LFUSE := CONFIG_LFUSE
endif
# Calculate command line arguments for fuses
AVRDUDE_WRITE_FUSES :=
ifdef EFUSE
AVRDUDE_WRITE_FUSES += -U efuse:w:$(EFUSE):m
endif
ifdef HFUSE
AVRDUDE_WRITE_FUSES += -U hfuse:w:$(HFUSE):m
endif
ifdef LFUSE
AVRDUDE_WRITE_FUSES += -U lfuse:w:$(LFUSE):m
endif
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#---------------- Debugging Options ----------------
# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(CONFIG_MCU_FREQ)
# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight
# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr
# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit
# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1
# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242
# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost
#============================================================================
# De-dupe the list of C source files
CSRC := $(sort $(SRC))
# Define all object files.
OBJ := $(patsubst %,$(OBJDIR)/%,$(CSRC:.c=.o) $(ASRC:.S=.o))
# Define all listing files.
LST := $(patsubst %,$(OBJDIR)/%,$(CSRC:.c=.lst) $(ASRC:.S=.lst))
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
# Default target.
all: build
build: elf bin hex
$(E) " SIZE $(TARGET).elf"
$(Q)$(ELFSIZE)|grep -v debug
elf: $(TARGET).elf
bin: $(TARGET).bin
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# A little helper target for the maintainer =)
copy2card:
mount /mnt
cp $(TARGET).bin /mnt
umount /mnt
sync
# Doxygen output:
doxygen:
-rm -rf doxyinput
mkdir doxyinput
cp *.h *.c doxyinput
src2doxy.pl doxyinput/*.h doxyinput/*.c
doxygen doxygen.conf
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
AVRMEM = avr-mem.sh $(TARGET).elf $(MCU)
# Program the device.
program: bin hex eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Set fuses of the device
fuses: $(CONFIG)
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FUSES)
# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)
debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Generate autoconf.h from config
.PRECIOUS : $(OBJDIR)/autoconf.h
$(OBJDIR)/autoconf.h: $(CONFIG) | $(OBJDIR)
$(E) " CONF2H $(CONFIG)"
$(Q)gawk -f conf2h.awk $(CONFIG) > $(OBJDIR)/autoconf.h
# Create final output files (.hex, .eep) from ELF output file.
ifeq ($(CONFIG_BOOTLOADER),y)
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
$(E) " BIN $@"
$(Q)$(OBJCOPY) -O binary -R .eeprom $< $@
$(E) " CRCGEN $@"
-$(Q)crcgen-new $@ $(BINARY_LENGTH) $(CONFIG_BOOT_DEVID) $(BOOT_VERSION)
$(E) " COPY $(CONFIG_HARDWARE_NAME)-firmware-$(PROGRAMVERSION).bin"
$(Q)$(COPY) $@ $(OBJDIR)/$(CONFIG_HARDWARE_NAME)-firmware-$(PROGRAMVERSION).bin
else
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
$(E) " BIN $@"
$(Q)$(OBJCOPY) -O binary -R .eeprom $< $@
endif
$(OBJDIR)/%.hex: $(OBJDIR)/%.elf
$(E) " HEX $@"
$(Q)$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
$(OBJDIR)/%.eep: $(OBJDIR)/%.elf
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
$(OBJDIR)/%.lss: $(OBJDIR)/%.elf
$(E) " LSS $<"
$(Q)$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
$(OBJDIR)/%.sym: $(OBJDIR)/%.elf
$(E) " SYM $<"
$(E)$(NM) -n $< > $@
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
$(OBJDIR)/%.elf: $(OBJ)
$(E) " LINK $@"
$(Q)$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
$(E) " CC $<"
$(Q)$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
$(OBJDIR)/%.s : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S | $(OBJDIR) $(OBJDIR)/autoconf.h
$(E) " AS $<"
$(Q)$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Create preprocessed source for use in sending a bug report.
$(OBJDIR)/%.i : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
# Create the output directory
$(OBJDIR):
$(E) " MKDIR $(OBJDIR)"
$(Q)mkdir $(OBJDIR)
# Target: clean project.
clean: begin clean_list end
clean_list :
$(E) " CLEAN"
$(Q)$(REMOVE) $(TARGET).hex
$(Q)$(REMOVE) $(TARGET).bin
$(Q)$(REMOVE) $(TARGET).eep
$(Q)$(REMOVE) $(TARGET).cof
$(Q)$(REMOVE) $(TARGET).elf
$(Q)$(REMOVE) $(TARGET).map
$(Q)$(REMOVE) $(TARGET).sym
$(Q)$(REMOVE) $(TARGET).lss
$(Q)$(REMOVE) $(OBJ)
$(Q)$(REMOVE) $(OBJDIR)/autoconf.h
$(Q)$(REMOVE) $(OBJDIR)/*.bin
$(Q)$(REMOVE) $(LST)
$(Q)$(REMOVE) $(CSRC:.c=.s)
$(Q)$(REMOVE) $(CSRC:.c=.d)
$(Q)$(REMOVE) .dep/*
$(Q)$(REMOVE) -rf codedoc
$(Q)$(REMOVE) -rf doxyinput
-$(Q)rmdir $(OBJDIR)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Manual dependency for the assembler module
# $(OBJDIR)/fastloader-ll.o: config.h $(OBJDIR)/autoconf.h
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config doxygen

29
mk1-src/conf2h.awk Normal file
View File

@ -0,0 +1,29 @@
#! /usr/bin/gawk -f
# Trivial little script to convert from a makefile-style configuration
# file to a C header. No copyright claimed.
BEGIN {
print "// autoconf.h generated from " ARGV[1] " at " strftime() "\n" \
"#ifndef AUTOCONF_H\n" \
"#define AUTOCONF_H"
}
/^#/ { sub(/^#/,"//") }
/^CONFIG_.*=/ {
if (/=n$/) {
sub(/^/,"// ");
} else {
sub(/^/,"#define ")
if (/=y$/) {
sub(/=.*$/,"")
} else {
sub(/=/," ")
}
}
}
{ print }
END { print "#endif" }

47
mk1-src/config Normal file
View File

@ -0,0 +1,47 @@
# This may not look like it, but it's a -*- makefile -*-
# sd2snes - SD card based universal cartridge for the SNES
# Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
#
# This file was adapted from sd2iec, written by Ingo Korb.
# Original disclaimer follows:
#
# sd2iec - SD/MMC to Commodore serial bus interface/controller
# Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
#
# Inspiration and low-level SD/MMC access based on code from MMC2IEC
# by Lars Pontoppidan et al., see sdcard.c|h and config.h.
#
# FAT filesystem access based on code from ChaN, see tff.c|h.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# This file is included in the main sd2iec Makefile and also parsed
# into autoconf.h.
CONFIG_MCU=atmega644
CONFIG_LINKER_RELAX=n
CONFIG_MCU_FREQ=12288000
CONFIG_BOOTLOADER=y
CONFIG_BOOT_DEVID=0x4e534453
CONFIG_UART_DEBUG=y
CONFIG_UART_BAUDRATE=384000
CONFIG_UART_BUF_SHIFT=7
CONFIG_HARDWARE_NAME=sd2snes
CONFIG_SD_AUTO_RETRIES=10
#CONFIG_SD_DATACRC=y
CONFIG_EEPROM_SIZE=512
CONFIG_EEPROM_OFFSET=512
CONFIG_MAX_PARTITIONS=1
#CONFIG_DEADLOCK_ME_HARDER=y

400
mk1-src/main.c Normal file
View File

@ -0,0 +1,400 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
see ff.c|h.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License only.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
main.c: initialization and flow
*/
#include <stdio.h>
#include <string.h>
#include <avr/boot.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include "config.h"
#include "diskio.h"
#include "ff.h"
#include "led.h"
/* #include "timer.h" */
#include "fpga.h"
#include "uart.h"
#include "ustring.h"
#include "utils.h"
#include "snes.h"
#include "fileops.h"
#include "memory.h"
#include "fpga_spi.h"
#include "spi.h"
#include "avrcompat.h"
#include "filetypes.h"
#include "sdcard.h"
void writetest(void) {
// HERE BE LIONS, GET IN THE CAR
char teststring[58];
while(1) {
sram_writeblock((void*)"Testtext of DOOM!!1! 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", SRAM_SCRATCHPAD+0x20, 58);
sram_readblock((void*)teststring, SRAM_SCRATCHPAD+0x20, 58);
teststring[57]=0;
dprintf("%s\n", teststring);
}
// END OF LIONS
}
void memtest(void) {
/* HERE BE DRAGONS */
uint32_t dbg_i;
for(dbg_i=0; dbg_i < 65536; dbg_i++) {
sram_writeshort((uint16_t)dbg_i&0xffff, dbg_i*2);
}
save_sram((uint8_t*)"/sd2snes/memtest", 0x20000, 0);
set_pwr_led(0);
while(1);
/* END OF DRAGONS */
}
/* Make sure the watchdog is disabled as soon as possible */
/* Copy this code to your bootloader if you use one and your */
/* MCU doesn't disable the WDT after reset! */
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
MCUSR = 0;
wdt_disable();
}
#ifdef CONFIG_MEMPOISON
void poison_memory(void) \
__attribute__((naked)) \
__attribute__((section(".init1")));
void poison_memory(void) {
register uint16_t i;
register uint8_t *ptr;
asm("clr r1\n");
/* There is no RAMSTARt variable =( */
if (RAMEND > 2048 && RAMEND < 4096) {
/* 2K memory */
ptr = (void *)RAMEND-2047;
for (i=0;i<2048;i++)
ptr[i] = 0x55;
} else if (RAMEND > 4096 && RAMEND < 8192) {
/* 4K memory */
ptr = (void *)RAMEND-4095;
for (i=0;i<4096;i++)
ptr[i] = 0x55;
} else {
/* Assume 8K memory */
ptr = (void *)RAMEND-8191;
for (i=0;i<8192;i++)
ptr[i] = 0x55;
}
}
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)
int main(void) __attribute__((OS_main));
#endif
int main(void) {
#if defined __AVR_ATmega644__ || defined __AVR_ATmega644P__ || defined __AVR_ATmega2561__
asm volatile("in r24, %0\n"
"ori r24, 0x80\n"
"out %0, r24\n"
"out %0, r24\n"
:
: "I" (_SFR_IO_ADDR(MCUCR))
: "r24"
);
#elif defined __AVR_ATmega32__
asm volatile ("in r24, %0\n"
"ori r24, 0x80\n"
"out %0, r24\n"
"out %0, r24\n"
:
: "I" (_SFR_IO_ADDR(MCUCSR))
: "r24"
);
#elif defined __AVR_ATmega128__ || defined __AVR_ATmega1281__
/* Just assume that JTAG doesn't hurt us on the m128 */
#else
# error Unknown chip!
#endif
#ifdef CLOCK_PRESCALE
clock_prescale_set(CLOCK_PRESCALE);
#endif
set_pwr_led(0);
set_busy_led(1);
spi_none();
snes_reset(1);
uart_init();
sei();
_delay_ms(100);
disk_init();
snes_init();
/* timer_init(); */
uart_puts_P(PSTR("\nsd2snes " VERSION));
uart_putcrlf();
file_init();
FATFS fatfs;
f_mount(0,&fatfs);
uart_putc('W');
fpga_init();
fpga_pgm((uint8_t*)"/sd2snes/main.bit");
_delay_ms(100);
set_pwr_led(1);
fpga_spi_init();
uart_putc('!');
_delay_ms(100);
restart:
set_avr_ena(0);
snes_reset(1);
*fs_path=0;
uint16_t saved_dir_id;
get_db_id(&saved_dir_id);
uint16_t mem_dir_id = sram_readshort(SRAM_DIRID);
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
while(0) {
SD_SPI_OFFLOAD=0;
set_avr_addr(0L);
sd_read(0, file_buf, 0L, 1);
uart_trace((void*)file_buf, 0, 0x200);
// sram_writeblock((void*)file_buf, 0, 0x200);
// sram_hexdump(0,0x200);
uart_putc('+');
}
/* here be strange monsters */
while(0){
// uint16_t hurdur1 = 0, hurdur2 = 0;
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
PORTB |= _BV(PB2);
DDRB |= _BV(PB2);
PORTB &= ~_BV(PB2);
DDRB &= ~_BV(PB7); // tristate SCK
PORTB |= _BV(PB2);
DDRB &= ~_BV(PB2);
while(!(PINB & _BV(PB2))) {
}
DDRB |= _BV(PB7);
_delay_ms(1);
// dprintf("hurdur1=%d hurdur2=%d\n", hurdur1, hurdur2);
}
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
uint16_t curr_dir_id = scan_dir(fs_path, 0, 0); // generate files footprint
dprintf("curr dir id = %x\n", curr_dir_id);
if((get_db_id(&saved_dir_id) != FR_OK) // no database?
|| saved_dir_id != curr_dir_id) { // files changed? // XXX
dprintf("saved dir id = %x\n", saved_dir_id);
dprintf("rebuilding database...");
_delay_ms(50);
curr_dir_id = scan_dir(fs_path, 1, 0); // then rebuild database
sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 2);
uint32_t endaddr, direndaddr;
sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4);
sram_readblock(&direndaddr, SRAM_DB_ADDR+8, 4);
dprintf("%lx %lx\n", endaddr, direndaddr);
save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR);
save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
dprintf("done\n");
// sram_hexdump(SRAM_DB_ADDR, 0x400);
} else {
dprintf("saved dir id = %x\n", saved_dir_id);
dprintf("different card, consistent db, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
// save_sram((uint8_t*)"/debug.smc", 0x400000, 0);
// uart_putc('[');
// load_sram((uint8_t*)"/test.srm", SRAM_SAVE_ADDR);
// uart_putc(']');
sram_writeshort(curr_dir_id, SRAM_DIRID);
sram_writelong(0x12345678, SRAM_SCRATCHPAD);
} else {
dprintf("same card, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
led_pwm();
// sram_hexdump(0, 0x200);
uart_putc('(');
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
set_rom_mask(0x3fffff); // force mirroring off
set_avr_mapper(0x7); // menu mapper XXX
uart_putc(')');
uart_putcrlf();
// sram_hexdump(0x7ffff0, 0x10);
// sram_hexdump(0, 0x400);
// save_sram((uint8_t*)"/sd2snes/dump", 65536, 0);
sram_writebyte(0, SRAM_CMD_ADDR);
set_busy_led(0);
set_avr_ena(1);
_delay_ms(100);
uart_puts_P(PSTR("SNES GO!\r\n"));
snes_reset(0);
// writetest();
/* snes_reset(1);
set_avr_ena(0);
led_std();
set_busy_led(1);
save_sram((uint8_t*)"/sd2snes/dump", 65536, SRAM_MENU_ADDR);
set_busy_led(0);
set_avr_ena(1);
snes_reset(0); */
uint8_t cmd = 0;
while(!sram_reliable());
while(!cmd) {
cmd=menu_main_loop();
switch(cmd) {
case 0x01: // SNES_CMD_LOADROM:
get_selected_name(file_lfn);
_delay_ms(100);
// snes_reset(1);
set_avr_ena(0);
dprintf("Selected name: %s\n", file_lfn);
load_rom(file_lfn, SRAM_ROM_ADDR);
// save_sram((uint8_t*)"/sd2snes/test.smc", romprops.romsize_bytes, 0);
if(romprops.ramsize_bytes) {
strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
dprintf("SRM file: %s\n", file_lfn);
load_sram(file_lfn, SRAM_SAVE_ADDR);
} else {
dprintf("No SRAM\n");
}
set_avr_ena(1);
snes_reset(1);
_delay_ms(100);
snes_reset(0);
break;
default:
dprintf("unknown cmd: %d\n", cmd);
cmd=0; // unknown cmd: stay in loop
break;
}
}
dprintf("cmd was %x, going to snes main loop\n", cmd);
led_std();
cmd=0;
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
uint16_t reset_count=0;
while(fpga_test() == FPGA_TEST_TOKEN) {
snes_reset_now=get_snes_reset();
if(snes_reset_now) {
if(!snes_reset_prev) {
dprintf("RESET BUTTON DOWN\n");
snes_reset_state=1;
// reset reset counter
reset_count=0;
}
} else {
if(snes_reset_prev) {
dprintf("RESET BUTTON UP\n");
snes_reset_state=0;
}
}
if(snes_reset_state) {
_delay_ms(10);
reset_count++;
} else {
sram_reliable();
snes_main_loop();
}
if(reset_count>100) {
reset_count=0;
led_std();
set_avr_ena(0);
snes_reset(1);
_delay_ms(100);
if(romprops.ramsize_bytes && fpga_test() == 0xa5) {
set_busy_led(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
set_busy_led(0);
}
_delay_ms(1000);
set_busy_led(1);
goto restart;
}
snes_reset_prev = snes_reset_now;
}
// FPGA TEST FAIL. PANIC.
led_panic();
/* HERE BE LIONS */
while(1) {
set_avr_addr(0x600000);
spi_fpga();
spiTransferByte(0x81); // read w/ increment... hopefully
spiTransferByte(0x00); // 1 dummy read
uart_putcrlf();
uint8_t buff[21];
for(uint8_t cnt=0; cnt<21; cnt++) {
uint8_t data=spiTransferByte(0x00);
buff[cnt]=data;
}
for(uint8_t cnt=0; cnt<21; cnt++) {
uint8_t data = buff[cnt];
_delay_ms(2);
if(data>=0x20 && data <= 0x7a) {
uart_putc(data);
} else {
// uart_putc('.');
uart_putc("0123456789ABCDEF"[data>>4]);
uart_putc("0123456789ABCDEF"[data&15]);
uart_putc(' ');
}
// set_avr_bank(3);
}
spi_none();
}
while(1);
}

View File

@ -1,14 +1,5 @@
# Hey Emacs, this is a -*- makefile -*-
# Define version number
MAJOR = 0
MINOR = 0
PATCHLEVEL = 1
FIX =
# Forces bootloader version to 0, comment out for release
#PRERELEASE =
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Joerg Wunsch, et al.
#
@ -25,7 +16,7 @@ FIX =
# Carlos Lamas
#
#
# Extensively modified for sd2iec by Ingo Korb
# Extensively modified for sd2iec and later adapted for ARM by Ingo Korb
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
@ -50,62 +41,22 @@ endif
# Include the configuration file
include $(CONFIG)
# Set MCU name and length of binary for bootloader
# WARNING: Fuse settings not tested!
MCU := $(CONFIG_MCU)
ifeq ($(MCU),atmega128)
BINARY_LENGTH = 0x1f000
# EFUSE = 0xff
# HFUSE = 0x91
# LFUSE = 0xaf
else ifeq ($(MCU),atmega1281)
BINARY_LENGTH = 0x1f000
BOOTLDRSIZE = 0x0800
EFUSE = 0xff
HFUSE = 0xd2
LFUSE = 0xfc
else ifeq ($(MCU),atmega2561)
BINARY_LENGTH = 0x3f000
EFUSE = 0xfd
HFUSE = 0x93
LFUSE = 0xef
else ifeq ($(MCU),atmega644)
BINARY_LENGTH = 0xf000
EFUSE = 0xfd
HFUSE = 0x91
# LFUSE = 0xef
LFUSE = 0xaf
else ifeq ($(MCU),atmega644p)
BINARY_LENGTH = 0xf000
EFUSE = 0xfd
HFUSE = 0x91
LFUSE = 0xef
else
.PHONY: nochip
nochip:
@echo '=============================================================='
@echo 'No known target chip specified.'
@echo
@echo 'Please edit the Makefile.'
@exit 1
endif
# Directory for all generated files
OBJDIR := obj-$(CONFIG_MCU:atmega%=m%)$(CONFIGSUFFIX)
OBJDIR := obj$(CONFIGSUFFIX)
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
FORMAT = binary
# Linker script
LINKERSCRIPT = lpc1754.ld
# Target file name (without extension).
TARGET = $(OBJDIR)/sd2snes
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c ff.c utils.c led.c diskio.c sdcard.c spi.c crc7.c snes.c fpga.c memory.c crc16.c fileops.c fpga_spi.c smc.c filetypes.c
ifeq ($(CONFIG_UART_DEBUG),y)
SRC += uart.c
endif
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
@ -114,19 +65,17 @@ endif
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
ASRC = startup.S
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
# Use s -mcall-prologues when you really need size...
#OPT = 2
OPT = s
#OPT = 3 -finline-functions
# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2
@ -146,52 +95,33 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS = -DF_CPU=$(CONFIG_MCU_FREQ)UL
CDEFS = #-DF_CPU=$(CONFIG_MCU_FREQ)UL
# Calculate bootloader version
ifdef PRERELEASE
BOOT_VERSION := 0
else
BOOT_VERSION := 0x$(MAJOR)$(MINOR)$(PATCHLEVEL)$(FIX)
endif
# Create a version number define
ifdef PATCHLEVEL
ifdef FIX
PROGRAMVERSION := $(MAJOR).$(MINOR).$(PATCHLEVEL).$(FIX)
else
PROGRAMVERSION := $(MAJOR).$(MINOR).$(PATCHLEVEL)
BOOT_VERSION := $(BOOT_VERSION)0
endif
else
PROGRAMVERSION := $(MAJOR).$(MINOR)
BOOT_VERSION := $(BOOT_VERSION)00
endif
ifdef PRERELEASE
PROGRAMVERSION := $(PROGRAMVERSION)$(PRERELEASE)
endif
LONGVERSION := -$(CONFIG_MCU:atmega%=m%)$(CONFIGSUFFIX)
CDEFS += -DVERSION=\"$(PROGRAMVERSION)\" -DLONGVERSION=\"$(LONGVERSION)\"
# Place -I options here
CINCS =
# CPU-specific flags
ifndef CPUFLAGS
CPUFLAGS := -mthumb -mcpu=cortex-m3
endif
ifndef ARCH
ARCH := arm-none-eabi
endif
# Define programs and commands.
# CC must be defined here to generate the correct CFLAGS
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
CC = $(ARCH)-gcc
OBJCOPY = $(ARCH)-objcopy
OBJDUMP = $(ARCH)-objdump
SIZE = $(ARCH)-size
NM = $(ARCH)-nm
REMOVE = rm -f
COPY = cp
WINSHELL = cmd
AWK = awk
#---------------- Compiler Options ----------------
@ -204,34 +134,14 @@ WINSHELL = cmd
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += $(CPUFLAGS) -nostartfiles
#CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes -Werror
CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst)
#CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst)
CFLAGS += -I$(OBJDIR)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS += -ffunction-sections -fdata-sections
#CFLAGS += -mcall-prologues
# these are needed for GCC 4.3.2, which is more aggressive at inlining
# gcc-4.2 knows one of those, but it tends to increase code size
ifeq ($(shell $(CC) --version|gawk -f gcctest.awk),YES)
CFLAGS += --param inline-call-cost=3
CFLAGS += -fno-inline-small-functions
CFLAGS += -fno-move-loop-invariants
CFLAGS += -fno-split-wide-types
# turn these on to keep the functions in the same order as in the source
# this is only useful if you're looking at disassembly
#CFLAGS += -fno-reorder-blocks
#CFLAGS += -fno-reorder-blocks-and-partition
#CFLAGS += -fno-reorder-functions
#CFLAGS += -fno-toplevel-reorder
endif
ifeq ($(CONFIG_STACK_TRACKING),y)
CFLAGS += -finstrument-functions
endif
#---------------- Assembler Options ----------------
@ -241,50 +151,7 @@ endif
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(OBJDIR)/$(<:.S=.lst),-gstabs -I$(OBJDIR)
#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
#---------------- External Memory Options ----------------
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
ASFLAGS = $(CPUFLAGS) -Wa,-adhlns=$(OBJDIR)/$(<:.S=.lst),-gstabs -I$(OBJDIR)
#---------------- Linker Options ----------------
@ -292,105 +159,13 @@ EXTMEMOPTS =
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
LDFLAGS += -T$(LINKERSCRIPT)
LDFLAGS += -Wl,--gc-sections
ifeq ($(CONFIG_LINKER_RELAX),y)
LDFLAGS += -Wl,-O9,--relax
endif
#---------------- Programming Options (avrdude) ----------------
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 stk500v2
#
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = dragon_isp
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = usb # programmer connected to serial device
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
# AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Allow fuse overrides from the config file
ifdef CONFIG_EFUSE
EFUSE := CONFIG_EFUSE
endif
ifdef CONFIG_HFUSE
HFUSE := CONFIG_HFUSE
endif
ifdef CONFIG_LFUSE
LFUSE := CONFIG_LFUSE
endif
# Calculate command line arguments for fuses
AVRDUDE_WRITE_FUSES :=
ifdef EFUSE
AVRDUDE_WRITE_FUSES += -U efuse:w:$(EFUSE):m
endif
ifdef HFUSE
AVRDUDE_WRITE_FUSES += -U hfuse:w:$(HFUSE):m
endif
ifdef LFUSE
AVRDUDE_WRITE_FUSES += -U lfuse:w:$(LFUSE):m
endif
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#---------------- Debugging Options ----------------
# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(CONFIG_MCU_FREQ)
# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight
# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr
# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit
# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1
# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242
# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost
#============================================================================
@ -410,8 +185,8 @@ GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
ALL_CFLAGS = -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
@ -431,111 +206,38 @@ eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# A little helper target for the maintainer =)
copy2card:
mount /mnt
cp $(TARGET).bin /mnt
umount /mnt
sync
# # A little helper target for the maintainer =)
# copy2card:
# cp $(TARGET).bin /mbed/hw_LPC1768.bin
# Doxygen output:
doxygen:
-rm -rf doxyinput
mkdir doxyinput
cp *.h *.c doxyinput
src2doxy.pl doxyinput/*.h doxyinput/*.c
doxygen doxygen.conf
program: bin
utils/lpcchksum $(TARGET).bin
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg
debug: bin
openocd -f openocd-usb.cfg -f lpc1754.cfg
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
AVRMEM = avr-mem.sh $(TARGET).elf $(MCU)
# Program the device.
program: bin hex eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Set fuses of the device
fuses: $(CONFIG)
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FUSES)
# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)
debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Generate autoconf.h from config
.PRECIOUS : $(OBJDIR)/autoconf.h
$(OBJDIR)/autoconf.h: $(CONFIG) | $(OBJDIR)
$(E) " CONF2H $(CONFIG)"
$(Q)gawk -f conf2h.awk $(CONFIG) > $(OBJDIR)/autoconf.h
$(Q)$(AWK) -f conf2h.awk $(CONFIG) > $(OBJDIR)/autoconf.h
# Create final output files (.hex, .eep) from ELF output file.
ifeq ($(CONFIG_BOOTLOADER),y)
# Create final output files from ELF output file.
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
$(E) " BIN $@"
$(Q)$(OBJCOPY) -O binary -R .eeprom $< $@
$(E) " CRCGEN $@"
-$(Q)crcgen-new $@ $(BINARY_LENGTH) $(CONFIG_BOOT_DEVID) $(BOOT_VERSION)
$(E) " COPY $(CONFIG_HARDWARE_NAME)-firmware-$(PROGRAMVERSION).bin"
$(Q)$(COPY) $@ $(OBJDIR)/$(CONFIG_HARDWARE_NAME)-firmware-$(PROGRAMVERSION).bin
else
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
$(E) " BIN $@"
$(Q)$(OBJCOPY) -O binary -R .eeprom $< $@
endif
$(Q)$(OBJCOPY) -O binary $< $@
$(OBJDIR)/%.hex: $(OBJDIR)/%.elf
$(E) " HEX $@"
$(Q)$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
$(OBJDIR)/%.eep: $(OBJDIR)/%.elf
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
$(Q)$(OBJCOPY) -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
$(OBJDIR)/%.lss: $(OBJDIR)/%.elf
@ -548,7 +250,6 @@ $(OBJDIR)/%.sym: $(OBJDIR)/%.elf
$(E)$(NM) -n $< > $@
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
@ -589,8 +290,6 @@ clean_list :
$(E) " CLEAN"
$(Q)$(REMOVE) $(TARGET).hex
$(Q)$(REMOVE) $(TARGET).bin
$(Q)$(REMOVE) $(TARGET).eep
$(Q)$(REMOVE) $(TARGET).cof
$(Q)$(REMOVE) $(TARGET).elf
$(Q)$(REMOVE) $(TARGET).map
$(Q)$(REMOVE) $(TARGET).sym
@ -602,18 +301,11 @@ clean_list :
$(Q)$(REMOVE) $(CSRC:.c=.s)
$(Q)$(REMOVE) $(CSRC:.c=.d)
$(Q)$(REMOVE) .dep/*
$(Q)$(REMOVE) -rf codedoc
$(Q)$(REMOVE) -rf doxyinput
-$(Q)rmdir $(OBJDIR)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Manual dependency for the assembler module
# $(OBJDIR)/fastloader-ll.o: config.h $(OBJDIR)/autoconf.h
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config doxygen
.PHONY : all begin finish end sizebefore sizeafter \
build elf hex lss sym clean clean_list

View File

@ -1,47 +1 @@
# This may not look like it, but it's a -*- makefile -*-
# sd2snes - SD card based universal cartridge for the SNES
# Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
#
# This file was adapted from sd2iec, written by Ingo Korb.
# Original disclaimer follows:
#
# sd2iec - SD/MMC to Commodore serial bus interface/controller
# Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
#
# Inspiration and low-level SD/MMC access based on code from MMC2IEC
# by Lars Pontoppidan et al., see sdcard.c|h and config.h.
#
# FAT filesystem access based on code from ChaN, see tff.c|h.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# This file is included in the main sd2iec Makefile and also parsed
# into autoconf.h.
CONFIG_MCU=atmega644
CONFIG_LINKER_RELAX=n
CONFIG_MCU_FREQ=12288000
CONFIG_BOOTLOADER=y
CONFIG_BOOT_DEVID=0x4e534453
CONFIG_UART_DEBUG=y
CONFIG_UART_BAUDRATE=384000
CONFIG_UART_BUF_SHIFT=7
CONFIG_HARDWARE_NAME=sd2snes
CONFIG_SD_AUTO_RETRIES=10
#CONFIG_SD_DATACRC=y
CONFIG_EEPROM_SIZE=512
CONFIG_EEPROM_OFFSET=512
CONFIG_MAX_PARTITIONS=1
#CONFIG_DEADLOCK_ME_HARDER=y
# empty config file

View File

@ -1,400 +1,84 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
/* The classic embedded version of "Hello World": A blinking LED */
#include <arm/NXP/LPC17xx/LPC17xx.h>
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
#define BV(x) (1<<(x))
#define BITBAND(addr,bit) (*((volatile unsigned long *)(((unsigned long)&(addr)-0x20000000)*32 + bit*4 + 0x22000000)))
#define PLL_MULT(x) ((x)&0x7fff)
#define PLL_PREDIV(x) (((x)<<16)&0xff0000)
#define CLKSRC_MAINOSC (1)
#define PLLE0 (1<<0)
#define PLLC0 (1<<1)
#define PLOCK0 (1<<26)
#define OSCEN (1<<5)
#define OSCSTAT (1<<6)
#define EMC0TOGGLE (3<<4)
#define MR0R (1<<1)
#define FLASH5C (0x403A)
#define PCTIM3 (1<<23)
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
see ff.c|h.
#define PCLK_CCLK(x) (1<<(x))
#define PCLK_CCLK4(x) (0)
#define PCLK_CCLK8(x) (3<<(x))
#define PCLK_CCLK2(x) (2<<(x))
#define PCLK_TIMER3 (14)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License only.
int i;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
int main(void) {
LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2);
LPC_GPIO1->FIODIR = 0;
uint32_t p1;
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/* setup PLL0 */
LPC_SC->FLASHCFG=FLASH5C;
LPC_SC->PLL0CON &= ~PLLC0;
LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55;
LPC_SC->PLL0CON &= ~PLLE0;
LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55;
main.c: initialization and flow
/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed
reliably with PLL0 connected.
see:
http://ics.nxp.com/support/documents/microcontrollers/pdf/errata.lpc1754.pdf
*/
LPC_SC->PCLKSEL1=PCLK_CCLK(PCLK_TIMER3);
/* continue with PLL0 setup */
LPC_SC->SCS=OSCEN;
while(!(LPC_SC->SCS&OSCSTAT));
LPC_SC->CLKSRCSEL=CLKSRC_MAINOSC;
LPC_SC->PLL0CFG=PLL_MULT(428)|PLL_PREDIV(18);
LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55;
LPC_SC->PLL0CON |= PLLE0;
LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55;
LPC_SC->CCLKCFG=5;
while(!(LPC_SC->PLL0STAT&PLOCK0));
LPC_SC->PLL0CON |= PLLC0;
LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55;
#include <stdio.h>
#include <string.h>
#include <avr/boot.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include "config.h"
#include "diskio.h"
#include "ff.h"
#include "led.h"
/* #include "timer.h" */
#include "fpga.h"
#include "uart.h"
#include "ustring.h"
#include "utils.h"
#include "snes.h"
#include "fileops.h"
#include "memory.h"
#include "fpga_spi.h"
#include "spi.h"
#include "avrcompat.h"
#include "filetypes.h"
#include "sdcard.h"
/* setup timer (fpga clk) */
LPC_SC->PCONP |= PCTIM3; /* enable power */
LPC_TIM3->CTCR=0;
LPC_TIM3->EMR=EMC0TOGGLE;
LPC_PINCON->PINSEL0=(0x3<<20);
LPC_TIM3->MCR=MR0R;
LPC_TIM3->MR0=1;
LPC_TIM3->TCR=1;
void writetest(void) {
// HERE BE LIONS, GET IN THE CAR
char teststring[58];
while(1) {
sram_writeblock((void*)"Testtext of DOOM!!1! 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", SRAM_SCRATCHPAD+0x20, 58);
sram_readblock((void*)teststring, SRAM_SCRATCHPAD+0x20, 58);
teststring[57]=0;
dprintf("%s\n", teststring);
}
// END OF LIONS
}
void memtest(void) {
/* HERE BE DRAGONS */
uint32_t dbg_i;
for(dbg_i=0; dbg_i < 65536; dbg_i++) {
sram_writeshort((uint16_t)dbg_i&0xffff, dbg_i*2);
}
save_sram((uint8_t*)"/sd2snes/memtest", 0x20000, 0);
set_pwr_led(0);
while(1);
/* END OF DRAGONS */
}
/* Make sure the watchdog is disabled as soon as possible */
/* Copy this code to your bootloader if you use one and your */
/* MCU doesn't disable the WDT after reset! */
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
MCUSR = 0;
wdt_disable();
}
#ifdef CONFIG_MEMPOISON
void poison_memory(void) \
__attribute__((naked)) \
__attribute__((section(".init1")));
void poison_memory(void) {
register uint16_t i;
register uint8_t *ptr;
asm("clr r1\n");
/* There is no RAMSTARt variable =( */
if (RAMEND > 2048 && RAMEND < 4096) {
/* 2K memory */
ptr = (void *)RAMEND-2047;
for (i=0;i<2048;i++)
ptr[i] = 0x55;
} else if (RAMEND > 4096 && RAMEND < 8192) {
/* 4K memory */
ptr = (void *)RAMEND-4095;
for (i=0;i<4096;i++)
ptr[i] = 0x55;
} else {
/* Assume 8K memory */
ptr = (void *)RAMEND-8191;
for (i=0;i<8192;i++)
ptr[i] = 0x55;
while (1) {
p1 = LPC_GPIO1->FIOPIN;
BITBAND(LPC_GPIO2->FIOPIN, 0) = (p1 & BV(29))>>29;
BITBAND(LPC_GPIO2->FIOSET, 2) = 1;
for (i=0;i<100000;i++)
__NOP();
BITBAND(LPC_GPIO2->FIOCLR, 2) = 1;
for (i=0;i<100000;i++)
__NOP();
}
}
#endif
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)
int main(void) __attribute__((OS_main));
#endif
int main(void) {
#if defined __AVR_ATmega644__ || defined __AVR_ATmega644P__ || defined __AVR_ATmega2561__
asm volatile("in r24, %0\n"
"ori r24, 0x80\n"
"out %0, r24\n"
"out %0, r24\n"
:
: "I" (_SFR_IO_ADDR(MCUCR))
: "r24"
);
#elif defined __AVR_ATmega32__
asm volatile ("in r24, %0\n"
"ori r24, 0x80\n"
"out %0, r24\n"
"out %0, r24\n"
:
: "I" (_SFR_IO_ADDR(MCUCSR))
: "r24"
);
#elif defined __AVR_ATmega128__ || defined __AVR_ATmega1281__
/* Just assume that JTAG doesn't hurt us on the m128 */
#else
# error Unknown chip!
#endif
#ifdef CLOCK_PRESCALE
clock_prescale_set(CLOCK_PRESCALE);
#endif
set_pwr_led(0);
set_busy_led(1);
spi_none();
snes_reset(1);
uart_init();
sei();
_delay_ms(100);
disk_init();
snes_init();
/* timer_init(); */
uart_puts_P(PSTR("\nsd2snes " VERSION));
uart_putcrlf();
file_init();
FATFS fatfs;
f_mount(0,&fatfs);
uart_putc('W');
fpga_init();
fpga_pgm((uint8_t*)"/sd2snes/main.bit");
_delay_ms(100);
set_pwr_led(1);
fpga_spi_init();
uart_putc('!');
_delay_ms(100);
restart:
set_avr_ena(0);
snes_reset(1);
*fs_path=0;
uint16_t saved_dir_id;
get_db_id(&saved_dir_id);
uint16_t mem_dir_id = sram_readshort(SRAM_DIRID);
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
while(0) {
SD_SPI_OFFLOAD=0;
set_avr_addr(0L);
sd_read(0, file_buf, 0L, 1);
uart_trace((void*)file_buf, 0, 0x200);
// sram_writeblock((void*)file_buf, 0, 0x200);
// sram_hexdump(0,0x200);
uart_putc('+');
}
/* here be strange monsters */
while(0){
// uint16_t hurdur1 = 0, hurdur2 = 0;
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x00);
PORTB |= _BV(PB2);
DDRB |= _BV(PB2);
PORTB &= ~_BV(PB2);
DDRB &= ~_BV(PB7); // tristate SCK
PORTB |= _BV(PB2);
DDRB &= ~_BV(PB2);
while(!(PINB & _BV(PB2))) {
}
DDRB |= _BV(PB7);
_delay_ms(1);
// dprintf("hurdur1=%d hurdur2=%d\n", hurdur1, hurdur2);
}
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
uint16_t curr_dir_id = scan_dir(fs_path, 0, 0); // generate files footprint
dprintf("curr dir id = %x\n", curr_dir_id);
if((get_db_id(&saved_dir_id) != FR_OK) // no database?
|| saved_dir_id != curr_dir_id) { // files changed? // XXX
dprintf("saved dir id = %x\n", saved_dir_id);
dprintf("rebuilding database...");
_delay_ms(50);
curr_dir_id = scan_dir(fs_path, 1, 0); // then rebuild database
sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 2);
uint32_t endaddr, direndaddr;
sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4);
sram_readblock(&direndaddr, SRAM_DB_ADDR+8, 4);
dprintf("%lx %lx\n", endaddr, direndaddr);
save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR);
save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
dprintf("done\n");
// sram_hexdump(SRAM_DB_ADDR, 0x400);
} else {
dprintf("saved dir id = %x\n", saved_dir_id);
dprintf("different card, consistent db, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
// save_sram((uint8_t*)"/debug.smc", 0x400000, 0);
// uart_putc('[');
// load_sram((uint8_t*)"/test.srm", SRAM_SAVE_ADDR);
// uart_putc(']');
sram_writeshort(curr_dir_id, SRAM_DIRID);
sram_writelong(0x12345678, SRAM_SCRATCHPAD);
} else {
dprintf("same card, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
led_pwm();
// sram_hexdump(0, 0x200);
uart_putc('(');
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
set_rom_mask(0x3fffff); // force mirroring off
set_avr_mapper(0x7); // menu mapper XXX
uart_putc(')');
uart_putcrlf();
// sram_hexdump(0x7ffff0, 0x10);
// sram_hexdump(0, 0x400);
// save_sram((uint8_t*)"/sd2snes/dump", 65536, 0);
sram_writebyte(0, SRAM_CMD_ADDR);
set_busy_led(0);
set_avr_ena(1);
_delay_ms(100);
uart_puts_P(PSTR("SNES GO!\r\n"));
snes_reset(0);
// writetest();
/* snes_reset(1);
set_avr_ena(0);
led_std();
set_busy_led(1);
save_sram((uint8_t*)"/sd2snes/dump", 65536, SRAM_MENU_ADDR);
set_busy_led(0);
set_avr_ena(1);
snes_reset(0); */
uint8_t cmd = 0;
while(!sram_reliable());
while(!cmd) {
cmd=menu_main_loop();
switch(cmd) {
case 0x01: // SNES_CMD_LOADROM:
get_selected_name(file_lfn);
_delay_ms(100);
// snes_reset(1);
set_avr_ena(0);
dprintf("Selected name: %s\n", file_lfn);
load_rom(file_lfn, SRAM_ROM_ADDR);
// save_sram((uint8_t*)"/sd2snes/test.smc", romprops.romsize_bytes, 0);
if(romprops.ramsize_bytes) {
strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
dprintf("SRM file: %s\n", file_lfn);
load_sram(file_lfn, SRAM_SAVE_ADDR);
} else {
dprintf("No SRAM\n");
}
set_avr_ena(1);
snes_reset(1);
_delay_ms(100);
snes_reset(0);
break;
default:
dprintf("unknown cmd: %d\n", cmd);
cmd=0; // unknown cmd: stay in loop
break;
}
}
dprintf("cmd was %x, going to snes main loop\n", cmd);
led_std();
cmd=0;
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
uint16_t reset_count=0;
while(fpga_test() == FPGA_TEST_TOKEN) {
snes_reset_now=get_snes_reset();
if(snes_reset_now) {
if(!snes_reset_prev) {
dprintf("RESET BUTTON DOWN\n");
snes_reset_state=1;
// reset reset counter
reset_count=0;
}
} else {
if(snes_reset_prev) {
dprintf("RESET BUTTON UP\n");
snes_reset_state=0;
}
}
if(snes_reset_state) {
_delay_ms(10);
reset_count++;
} else {
sram_reliable();
snes_main_loop();
}
if(reset_count>100) {
reset_count=0;
led_std();
set_avr_ena(0);
snes_reset(1);
_delay_ms(100);
if(romprops.ramsize_bytes && fpga_test() == 0xa5) {
set_busy_led(1);
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
set_busy_led(0);
}
_delay_ms(1000);
set_busy_led(1);
goto restart;
}
snes_reset_prev = snes_reset_now;
}
// FPGA TEST FAIL. PANIC.
led_panic();
/* HERE BE LIONS */
while(1) {
set_avr_addr(0x600000);
spi_fpga();
spiTransferByte(0x81); // read w/ increment... hopefully
spiTransferByte(0x00); // 1 dummy read
uart_putcrlf();
uint8_t buff[21];
for(uint8_t cnt=0; cnt<21; cnt++) {
uint8_t data=spiTransferByte(0x00);
buff[cnt]=data;
}
for(uint8_t cnt=0; cnt<21; cnt++) {
uint8_t data = buff[cnt];
_delay_ms(2);
if(data>=0x20 && data <= 0x7a) {
uart_putc(data);
} else {
// uart_putc('.');
uart_putc("0123456789ABCDEF"[data>>4]);
uart_putc("0123456789ABCDEF"[data&15]);
uart_putc(' ');
}
// set_avr_bank(3);
}
spi_none();
}
while(1);
}