firmware: bootloader with firmware upgrade
This commit is contained in:
parent
2d15e24f4d
commit
cb202569d1
@ -200,6 +200,8 @@ all: build
|
||||
build: elf bin hex
|
||||
$(E) " SIZE $(TARGET).elf"
|
||||
$(Q)$(ELFSIZE)|grep -v debug
|
||||
cp $(TARGET).bin $(OBJDIR)/firmware.img
|
||||
utils/genhdr $(OBJDIR)/firmware.img SNSD $(CONFIG_FWVER)
|
||||
|
||||
elf: $(TARGET).elf
|
||||
bin: $(TARGET).bin
|
||||
@ -216,6 +218,7 @@ sym: $(TARGET).sym
|
||||
program: bin
|
||||
utils/lpcchksum $(TARGET).bin
|
||||
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg
|
||||
make -C bootldr program
|
||||
|
||||
debug: bin
|
||||
openocd -f openocd-usb.cfg -f lpc1754.cfg
|
||||
|
||||
319
src/bootldr/Makefile
Normal file
319
src/bootldr/Makefile
Normal file
@ -0,0 +1,319 @@
|
||||
# Hey Emacs, this is a -*- makefile -*-
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# 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 and later adapted for ARM 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)
|
||||
|
||||
# Directory for all generated files
|
||||
OBJDIR := obj$(CONFIGSUFFIX)
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = binary
|
||||
|
||||
# Linker script
|
||||
LINKERSCRIPT = lpc1754boot.ld
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = $(OBJDIR)/sd2snes_bootldr
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = timer.c main.c ff.c clock.c uart.c power.c led.c printf.c faulthandler.c crc32.c sdnative.c fileops.c iap.c
|
||||
|
||||
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
|
||||
|
||||
|
||||
# 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 = startup.S crc.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
|
||||
|
||||
# Debugging format.
|
||||
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_OSC=$(CONFIG_MCU_FOSC)UL
|
||||
|
||||
|
||||
# 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 = $(ARCH)-gcc
|
||||
OBJCOPY = $(ARCH)-objcopy
|
||||
OBJDUMP = $(ARCH)-objdump
|
||||
SIZE = $(ARCH)-size
|
||||
NM = $(ARCH)-nm
|
||||
REMOVE = rm -f
|
||||
COPY = cp
|
||||
AWK = awk
|
||||
|
||||
|
||||
#---------------- 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 += $(CPUFLAGS) -nostartfiles
|
||||
#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
|
||||
|
||||
|
||||
#---------------- 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 = $(CPUFLAGS) -Wa,-adhlns=$(OBJDIR)/$(<:.S=.lst),-gstabs -I$(OBJDIR)
|
||||
|
||||
|
||||
#---------------- 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 += -T$(LINKERSCRIPT)
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
ifeq ($(CONFIG_LINKER_RELAX),y)
|
||||
LDFLAGS += -Wl,-O9,--relax
|
||||
endif
|
||||
|
||||
|
||||
#============================================================================
|
||||
|
||||
|
||||
# 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 = -I. $(CFLAGS) $(GENDEPFLAGS)
|
||||
ALL_ASFLAGS = -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:
|
||||
# cp $(TARGET).bin /mbed/hw_LPC1768.bin
|
||||
|
||||
|
||||
# utils/lpcchksum $(TARGET).bin
|
||||
program: bin
|
||||
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg
|
||||
|
||||
debug: bin
|
||||
openocd -f openocd-usb.cfg -f lpc1754.cfg
|
||||
|
||||
reset:
|
||||
openocd -f openocd-usb.cfg -f lpc1754.cfg -f reset.cfg
|
||||
|
||||
erase:
|
||||
openocd -f openocd-usb.cfg -f lpc1754.cfg -f erase.cfg
|
||||
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) -A $(TARGET).elf
|
||||
|
||||
|
||||
|
||||
# Generate autoconf.h from config
|
||||
.PRECIOUS : $(OBJDIR)/autoconf.h
|
||||
$(OBJDIR)/autoconf.h: $(CONFIG) | $(OBJDIR)
|
||||
$(E) " CONF2H $(CONFIG)"
|
||||
$(Q)$(AWK) -f conf2h.awk $(CONFIG) > $(OBJDIR)/autoconf.h
|
||||
|
||||
# Create final output files from ELF output file.
|
||||
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
|
||||
$(E) " BIN $@"
|
||||
$(Q)$(OBJCOPY) -O binary $< $@
|
||||
|
||||
$(OBJDIR)/%.hex: $(OBJDIR)/%.elf
|
||||
$(E) " HEX $@"
|
||||
$(Q)$(OBJCOPY) -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)
|
||||
$(TARGET).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).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)rmdir $(OBJDIR)
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter \
|
||||
build elf hex lss sym clean clean_list
|
||||
21
src/bootldr/bits.h
Normal file
21
src/bootldr/bits.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _ARM_BITS_H
|
||||
#define _ARM_BITS_H
|
||||
|
||||
/* The classic macro */
|
||||
#define BV(x) (1<<(x))
|
||||
|
||||
/* CM3 bit-band access macro - no error checks! */
|
||||
#define BITBAND(addr,bit) \
|
||||
(*((volatile unsigned long *)( \
|
||||
((unsigned long)&(addr) & 0x01ffffff)*32 + \
|
||||
(bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \
|
||||
)))
|
||||
|
||||
#define BITBAND_OFF(addr,offset,bit) \
|
||||
(*((volatile unsigned long *)( \
|
||||
(((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \
|
||||
(bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \
|
||||
)))
|
||||
|
||||
|
||||
#endif
|
||||
540
src/bootldr/ccsbcs.c
Normal file
540
src/bootldr/ccsbcs.c
Normal file
@ -0,0 +1,540 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Unicode - Local code bidirectional converter (C)ChaN, 2009 */
|
||||
/* (SBCS code pages) */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* 437 U.S. (OEM)
|
||||
/ 720 Arabic (OEM)
|
||||
/ 1256 Arabic (Windows)
|
||||
/ 737 Greek (OEM)
|
||||
/ 1253 Greek (Windows)
|
||||
/ 1250 Central Europe (Windows)
|
||||
/ 775 Baltic (OEM)
|
||||
/ 1257 Baltic (Windows)
|
||||
/ 850 Multilingual Latin 1 (OEM)
|
||||
/ 852 Latin 2 (OEM)
|
||||
/ 1252 Latin 1 (Windows)
|
||||
/ 855 Cyrillic (OEM)
|
||||
/ 1251 Cyrillic (Windows)
|
||||
/ 866 Russian (OEM)
|
||||
/ 857 Turkish (OEM)
|
||||
/ 1254 Turkish (Windows)
|
||||
/ 858 Multilingual Latin 1 + Euro (OEM)
|
||||
/ 862 Hebrew (OEM)
|
||||
/ 1255 Hebrew (Windows)
|
||||
/ 874 Thai (OEM, Windows)
|
||||
/ 1258 Vietnam (OEM, Windows)
|
||||
*/
|
||||
|
||||
#include "../ff.h"
|
||||
|
||||
|
||||
#if _CODE_PAGE == 437
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
|
||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
|
||||
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
|
||||
0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
|
||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
|
||||
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
|
||||
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
|
||||
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
|
||||
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 720
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
|
||||
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
|
||||
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
|
||||
0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
|
||||
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
|
||||
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642,
|
||||
0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
|
||||
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0xO650, 0x2248,
|
||||
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 737
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
|
||||
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
|
||||
0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
|
||||
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
|
||||
0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
|
||||
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0,
|
||||
0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD,
|
||||
0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
|
||||
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248,
|
||||
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 775
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
|
||||
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
|
||||
0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
|
||||
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
|
||||
0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
|
||||
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6,
|
||||
0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118,
|
||||
0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
|
||||
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B,
|
||||
0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144,
|
||||
0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
|
||||
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E,
|
||||
0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 850
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
|
||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
|
||||
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
|
||||
0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
|
||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
|
||||
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
|
||||
0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
|
||||
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
|
||||
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
|
||||
0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
|
||||
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
|
||||
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 852
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
|
||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
|
||||
0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
|
||||
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
|
||||
0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
|
||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E,
|
||||
0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A,
|
||||
0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE,
|
||||
0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
|
||||
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161,
|
||||
0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
|
||||
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8,
|
||||
0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 855
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
|
||||
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
|
||||
0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
|
||||
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
|
||||
0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
|
||||
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414,
|
||||
0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438,
|
||||
0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E,
|
||||
0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
|
||||
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443,
|
||||
0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
|
||||
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D,
|
||||
0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 857
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
|
||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
|
||||
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
|
||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
|
||||
0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
|
||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F,
|
||||
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
|
||||
0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE,
|
||||
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
|
||||
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000,
|
||||
0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
|
||||
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
|
||||
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 858
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
|
||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
|
||||
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
|
||||
0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
|
||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
|
||||
0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
|
||||
0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE,
|
||||
0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580,
|
||||
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
|
||||
0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
|
||||
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
|
||||
0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 862
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
|
||||
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
|
||||
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
|
||||
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
|
||||
0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
|
||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
|
||||
0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4,
|
||||
0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
|
||||
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,
|
||||
0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 866
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
|
||||
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
|
||||
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
|
||||
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
|
||||
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
|
||||
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E,
|
||||
0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 874
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07,
|
||||
0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F,
|
||||
0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17,
|
||||
0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F,
|
||||
0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
|
||||
0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F,
|
||||
0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37,
|
||||
0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F,
|
||||
0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47,
|
||||
0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F,
|
||||
0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57,
|
||||
0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1250
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
|
||||
0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
|
||||
0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
|
||||
0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
|
||||
0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
|
||||
0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
|
||||
0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
|
||||
0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
|
||||
0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
|
||||
0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
|
||||
0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1251
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
|
||||
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
|
||||
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
|
||||
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
|
||||
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
|
||||
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
|
||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
|
||||
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
|
||||
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
|
||||
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
|
||||
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1252
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178,
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
|
||||
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
|
||||
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
|
||||
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
|
||||
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1253
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F,
|
||||
0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
|
||||
0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
|
||||
0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
|
||||
0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
|
||||
0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
|
||||
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
|
||||
0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
|
||||
0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1254
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
|
||||
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
|
||||
0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
|
||||
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
|
||||
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1255
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
|
||||
0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
|
||||
0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
|
||||
0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
|
||||
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
|
||||
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
|
||||
0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1256
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
|
||||
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA,
|
||||
0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F,
|
||||
0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
|
||||
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F,
|
||||
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7,
|
||||
0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643,
|
||||
0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7,
|
||||
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF,
|
||||
0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7,
|
||||
0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2
|
||||
}
|
||||
|
||||
#elif _CODE_PAGE == 1257
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000,
|
||||
0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7,
|
||||
0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6,
|
||||
0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
|
||||
0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B,
|
||||
0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7,
|
||||
0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF,
|
||||
0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113,
|
||||
0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C,
|
||||
0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7,
|
||||
0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9
|
||||
};
|
||||
|
||||
#elif _CODE_PAGE == 1258
|
||||
#define _TBLDEF 1
|
||||
static
|
||||
const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */
|
||||
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178,
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
|
||||
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
|
||||
0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
|
||||
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF,
|
||||
0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7,
|
||||
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF,
|
||||
0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
|
||||
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF,
|
||||
0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7,
|
||||
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !_TBLDEF || !_USE_LFN
|
||||
#error This file is not needed in current configuration. Remove from the project.
|
||||
#endif
|
||||
|
||||
|
||||
WCHAR ff_convert ( /* Converted character, Returns zero on error */
|
||||
WCHAR src, /* Character code to be converted */
|
||||
UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
|
||||
)
|
||||
{
|
||||
WCHAR c;
|
||||
|
||||
|
||||
if (src < 0x80) { /* ASCII */
|
||||
c = src;
|
||||
|
||||
} else {
|
||||
if (dir) { /* OEMCP to Unicode */
|
||||
c = (src >= 0x100) ? 0 : Tbl[src - 0x80];
|
||||
|
||||
} else { /* Unicode to OEMCP */
|
||||
for (c = 0; c < 0x80; c++) {
|
||||
if (src == Tbl[c]) break;
|
||||
}
|
||||
c = (c + 0x80) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
WCHAR ff_wtoupper ( /* Upper converted character */
|
||||
WCHAR chr /* Input character */
|
||||
)
|
||||
{
|
||||
static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 };
|
||||
static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 };
|
||||
int i;
|
||||
|
||||
|
||||
for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ;
|
||||
|
||||
return tbl_lower[i] ? tbl_upper[i] : chr;
|
||||
}
|
||||
108
src/bootldr/clock.c
Normal file
108
src/bootldr/clock.c
Normal file
@ -0,0 +1,108 @@
|
||||
/* ___DISCLAIMER___ */
|
||||
|
||||
/* clock.c: PLL, CCLK, PCLK controls */
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "clock.h"
|
||||
#include "bits.h"
|
||||
#include "uart.h"
|
||||
|
||||
void clock_disconnect() {
|
||||
disconnectPLL0();
|
||||
disablePLL0();
|
||||
}
|
||||
|
||||
void clock_init() {
|
||||
|
||||
/* set flash access time to 5 clks (80<f<=100MHz) */
|
||||
setFlashAccessTime(5);
|
||||
|
||||
/* setup PLL0 for ~44100*256*8 Hz
|
||||
Base clock: 12MHz
|
||||
Multiplier: 429
|
||||
Pre-Divisor: 19
|
||||
Divisor: 6
|
||||
(want: 90316800, get: 90315789.47)
|
||||
-> DAC freq = 44099.5 Hz
|
||||
-> FPGA freq = 11289473.7Hz
|
||||
First, disable and disconnect PLL0.
|
||||
*/
|
||||
// clock_disconnect();
|
||||
|
||||
/* 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
|
||||
*/
|
||||
|
||||
|
||||
/* continue with PLL0 setup:
|
||||
enable the xtal oscillator and wait for it to become stable
|
||||
set the oscillator as clk source for PLL0
|
||||
set PLL0 multiplier+predivider
|
||||
enable PLL0
|
||||
set CCLK divider
|
||||
wait for PLL0 to lock
|
||||
connect PLL0
|
||||
done
|
||||
*/
|
||||
enableMainOsc();
|
||||
setClkSrc(CLKSRC_MAINOSC);
|
||||
// XXX setPLL0MultPrediv(429, 19);
|
||||
setPLL0MultPrediv(23, 2);
|
||||
enablePLL0();
|
||||
setCCLKDiv(3);
|
||||
connectPLL0();
|
||||
}
|
||||
|
||||
void setFlashAccessTime(uint8_t clocks) {
|
||||
LPC_SC->FLASHCFG=FLASHTIM(clocks);
|
||||
}
|
||||
|
||||
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) {
|
||||
LPC_SC->PLL0CFG=PLL_MULT(mult) | PLL_PREDIV(prediv);
|
||||
PLL0feed();
|
||||
}
|
||||
|
||||
void enablePLL0() {
|
||||
LPC_SC->PLL0CON |= PLLE0;
|
||||
PLL0feed();
|
||||
}
|
||||
|
||||
void disablePLL0() {
|
||||
LPC_SC->PLL0CON &= ~PLLE0;
|
||||
PLL0feed();
|
||||
}
|
||||
|
||||
void connectPLL0() {
|
||||
while(!(LPC_SC->PLL0STAT&PLOCK0));
|
||||
LPC_SC->PLL0CON |= PLLC0;
|
||||
PLL0feed();
|
||||
}
|
||||
|
||||
void disconnectPLL0() {
|
||||
LPC_SC->PLL0CON &= ~PLLC0;
|
||||
PLL0feed();
|
||||
}
|
||||
|
||||
void setCCLKDiv(uint8_t div) {
|
||||
LPC_SC->CCLKCFG=CCLK_DIV(div);
|
||||
}
|
||||
|
||||
void enableMainOsc() {
|
||||
LPC_SC->SCS=OSCEN;
|
||||
while(!(LPC_SC->SCS&OSCSTAT));
|
||||
}
|
||||
|
||||
void disableMainOsc() {
|
||||
LPC_SC->SCS=0;
|
||||
}
|
||||
|
||||
void PLL0feed() {
|
||||
LPC_SC->PLL0FEED=0xaa;
|
||||
LPC_SC->PLL0FEED=0x55;
|
||||
}
|
||||
|
||||
void setClkSrc(uint8_t src) {
|
||||
LPC_SC->CLKSRCSEL=src;
|
||||
}
|
||||
79
src/bootldr/clock.h
Normal file
79
src/bootldr/clock.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef _CLOCK_H
|
||||
#define _CLOCK_H
|
||||
|
||||
#define PLL_MULT(x) ((x-1)&0x7fff)
|
||||
#define PLL_PREDIV(x) (((x-1)<<16)&0xff0000)
|
||||
#define CCLK_DIV(x) ((x-1)&0xff)
|
||||
#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 FLASHTIM(x) (((x-1)<<12)|0x3A)
|
||||
|
||||
#define PCLK_CCLK(x) (1<<(x))
|
||||
#define PCLK_CCLK4(x) (0)
|
||||
#define PCLK_CCLK8(x) (3<<(x))
|
||||
#define PCLK_CCLK2(x) (2<<(x))
|
||||
|
||||
/* shift values for use with PCLKSEL0 */
|
||||
#define PCLK_WDT (0)
|
||||
#define PCLK_TIMER0 (2)
|
||||
#define PCLK_TIMER1 (4)
|
||||
#define PCLK_UART0 (6)
|
||||
#define PCLK_UART1 (8)
|
||||
#define PCLK_PWM1 (12)
|
||||
#define PCLK_I2C0 (14)
|
||||
#define PCLK_SPI (16)
|
||||
#define PCLK_SSP1 (20)
|
||||
#define PCLK_DAC (22)
|
||||
#define PCLK_ADC (24)
|
||||
#define PCLK_CAN1 (26)
|
||||
#define PCLK_CAN2 (28)
|
||||
#define PCLK_ACF (30)
|
||||
|
||||
/* shift values for use with PCLKSEL1 */
|
||||
#define PCLK_QEI (0)
|
||||
#define PCLK_GPIOINT (2)
|
||||
#define PCLK_PCB (4)
|
||||
#define PCLK_I2C1 (6)
|
||||
#define PCLK_SSP0 (10)
|
||||
#define PCLK_TIMER2 (12)
|
||||
#define PCLK_TIMER3 (14)
|
||||
#define PCLK_UART2 (16)
|
||||
#define PCLK_UART3 (18)
|
||||
#define PCLK_I2C2 (20)
|
||||
#define PCLK_I2S (22)
|
||||
#define PCLK_RIT (26)
|
||||
#define PCLK_SYSCON (28)
|
||||
#define PCLK_MC (30)
|
||||
|
||||
void clock_disconnect(void);
|
||||
|
||||
void clock_init(void);
|
||||
|
||||
void setFlashAccessTime(uint8_t clocks);
|
||||
|
||||
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv);
|
||||
|
||||
void enablePLL0(void);
|
||||
|
||||
void disablePLL0(void);
|
||||
|
||||
void connectPLL0(void);
|
||||
|
||||
void disconnectPLL0(void);
|
||||
|
||||
void setCCLKDiv(uint8_t div);
|
||||
|
||||
void enableMainOsc(void);
|
||||
|
||||
void disableMainOsc(void);
|
||||
|
||||
void PLL0feed(void);
|
||||
|
||||
void setClkSrc(uint8_t src);
|
||||
|
||||
|
||||
#endif
|
||||
29
src/bootldr/conf2h.awk
Normal file
29
src/bootldr/conf2h.awk
Normal 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" }
|
||||
2
src/bootldr/config
Normal file
2
src/bootldr/config
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_VERSION=0.0.1
|
||||
CONFIG_MCU_FOSC=12000000
|
||||
99
src/bootldr/config.h
Normal file
99
src/bootldr/config.h
Normal file
@ -0,0 +1,99 @@
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
// #define DEBUG_SD
|
||||
// #define DEBUG_IRQ
|
||||
// #define DEBUG_MSU1
|
||||
|
||||
#define FW_START (0x00004000L)
|
||||
#define FLASH_SECTORS (17)
|
||||
|
||||
#define VER "0.0.1(NSFW)"
|
||||
#define IN_AHBRAM __attribute__ ((section(".ahbram")))
|
||||
|
||||
#define SD_DT_INT_SETUP() do {\
|
||||
BITBAND(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\
|
||||
BITBAND(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\
|
||||
} while(0)
|
||||
|
||||
#define SD_CHANGE_DETECT (BITBAND(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\
|
||||
|BITBAND(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT))
|
||||
|
||||
#define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
|
||||
|
||||
#define SD_DT_REG LPC_GPIO2
|
||||
#define SD_DT_BIT 3
|
||||
#define SD_WP_REG LPC_GPIO2
|
||||
#define SD_WP_BIT 4
|
||||
|
||||
#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
|
||||
#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
|
||||
#define SD_SUPPLY_VOLTAGE (1L<<21) /* 3.3V - 3.4V */
|
||||
#define CONFIG_SD_BLOCKTRANSFER 1
|
||||
#define CONFIG_SD_AUTO_RETRIES 10
|
||||
// #define SD_CHANGE_VECT
|
||||
// #define CONFIG_SD_DATACRC 1
|
||||
|
||||
#define CONFIG_UART_NUM 3
|
||||
// #define CONFIG_CPU_FREQUENCY 90315789
|
||||
#define CONFIG_CPU_FREQUENCY (92000000L)
|
||||
//#define CONFIG_CPU_FREQUENCY 46000000
|
||||
#define CONFIG_UART_PCLKDIV 1
|
||||
#define CONFIG_UART_TX_BUF_SHIFT 1
|
||||
#define CONFIG_UART_BAUDRATE 921600
|
||||
#define CONFIG_UART_DEADLOCKABLE
|
||||
|
||||
#define SSP_CLK_DIVISOR_FAST 2
|
||||
#define SSP_CLK_DIVISOR_SLOW 250
|
||||
|
||||
#define SSP_CLK_DIVISOR_FPGA_FAST 6
|
||||
#define SSP_CLK_DIVISOR_FPGA_SLOW 20
|
||||
|
||||
#define SNES_RESET_REG LPC_GPIO1
|
||||
#define SNES_RESET_BIT 29
|
||||
/* XXX Rev.B: 1.26 */
|
||||
#define SNES_CIC_D0_REG LPC_GPIO1
|
||||
#define SNES_CIC_D0_BIT 26
|
||||
/* XXX Rev.B: 0.1 */
|
||||
#define SNES_CIC_D1_REG LPC_GPIO1
|
||||
#define SNES_CIC_D1_BIT 25
|
||||
/* XXX Rev.B: 0.0 */
|
||||
#define SNES_CIC_STATUS_REG LPC_GPIO0
|
||||
#define SNES_CIC_STATUS_BIT 1
|
||||
/* XXX Rev.B: 1.29 */
|
||||
#define SNES_CIC_PAIR_REG LPC_GPIO0
|
||||
#define SNES_CIC_PAIR_BIT 0
|
||||
/* XXX Rev.B: 1.25 */
|
||||
|
||||
#define QSORT_MAXELEM 1024
|
||||
|
||||
#define SSP_REGS LPC_SSP0
|
||||
#define SSP_PCLKREG PCLKSEL1
|
||||
// 1: PCLKSEL0
|
||||
#define SSP_PCLKBIT 10
|
||||
// 1: 20
|
||||
#define SSP_DMAID_TX 0
|
||||
// 1: 2
|
||||
#define SSP_DMAID_RX 1
|
||||
// 1: 3
|
||||
#define SSP_DMACH LPC_GPDMACH0
|
||||
|
||||
#define SD_CLKREG LPC_GPIO0
|
||||
#define SD_CMDREG LPC_GPIO0
|
||||
#define SD_DAT0REG LPC_GPIO0
|
||||
#define SD_DAT1REG LPC_GPIO1
|
||||
#define SD_DAT2REG LPC_GPIO1
|
||||
#define SD_DAT3REG LPC_GPIO0
|
||||
|
||||
#define SD_CLKPIN (7)
|
||||
#define SD_CMDPIN (9)
|
||||
#define SD_DAT0PIN (8)
|
||||
#define SD_DAT1PIN (14)
|
||||
#define SD_DAT2PIN (15)
|
||||
#define SD_DAT3PIN (6)
|
||||
|
||||
#define SD_DAT ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))\
|
||||
|((SD_DAT1REG->FIOPIN1 >> 5) & 0x6)\
|
||||
|((BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN)) << 3))
|
||||
|
||||
#endif
|
||||
92
src/bootldr/crc.S
Normal file
92
src/bootldr/crc.S
Normal file
@ -0,0 +1,92 @@
|
||||
/* CRC-7/CRC-16 (XModem) implementation for Cortex M3
|
||||
*
|
||||
* Written 2010 by Ingo Korb
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.section .text
|
||||
|
||||
/* uint8_t crc7update(uint8_t crc, const uint8_t data) */
|
||||
.global crc7update
|
||||
.thumb_func
|
||||
crc7update:
|
||||
mov r2, #8 // number of bits to process
|
||||
lsl r1, r1, #24 // pre-shift data byte to top of word
|
||||
|
||||
loop:
|
||||
lsl r0, r0, #1 // shift CRC
|
||||
lsls r1, r1, #1 // shift data byte (highest bit now in C)
|
||||
bcc 0f // jump if bit was 0
|
||||
eor r0, r0, #0x80 // invert top bit of CRC if not
|
||||
0: tst r0, #0x80 // test top bit of CRC
|
||||
beq 1f // skip if top bit is clear
|
||||
eor r0, r0, #0x09 // apply polinomial
|
||||
1: subs r2, r2, #1 // decrememt bit cointer
|
||||
bne loop // loop for next bit
|
||||
uxtb r0, r0 // clear top bits of result
|
||||
bx lr // return
|
||||
|
||||
|
||||
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
|
||||
.global crc_xmodem_block
|
||||
.thumb_func
|
||||
crc_xmodem_block:
|
||||
adr r12, crc_table // load address of crc table
|
||||
blockloop:
|
||||
ldrb.w r3, [r1], #1 // read data byte
|
||||
eor r3, r3, r0, lsr #8 // EOR data byte
|
||||
ldrh r3, [r12, r3, lsl #1] // load value from CRC table
|
||||
eor r0, r3, r0, lsl #8 // update CRC
|
||||
uxth r0, r0 // clear top bits of result
|
||||
subs r2, r2, #1 // decrement length
|
||||
bne blockloop // loop while length > 0
|
||||
bx lr // return
|
||||
|
||||
/* uint16_t crc_xmodem_block(uint16_t crc, uint8_t *data, uint32_t len) */
|
||||
.global crc_xmodem_update
|
||||
.thumb_func
|
||||
crc_xmodem_update:
|
||||
adr r2, crc_table // load address of crc table
|
||||
eor r1, r1, r0, lsr #8 // EOR data byte
|
||||
ldrh r3, [r2, r1, lsl #1] // load value from CRC table
|
||||
eor r0, r3, r0, lsl #8 // update CRC
|
||||
uxth r0, r0 // clear top bits of result
|
||||
bx lr // return
|
||||
|
||||
|
||||
crc_table:
|
||||
.short 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7
|
||||
.short 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
|
||||
.short 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6
|
||||
.short 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de
|
||||
.short 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485
|
||||
.short 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d
|
||||
.short 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4
|
||||
.short 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc
|
||||
.short 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823
|
||||
.short 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b
|
||||
.short 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12
|
||||
.short 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a
|
||||
.short 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41
|
||||
.short 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49
|
||||
.short 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70
|
||||
.short 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78
|
||||
.short 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f
|
||||
.short 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067
|
||||
.short 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e
|
||||
.short 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256
|
||||
.short 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d
|
||||
.short 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405
|
||||
.short 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c
|
||||
.short 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634
|
||||
.short 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab
|
||||
.short 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3
|
||||
.short 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a
|
||||
.short 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92
|
||||
.short 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9
|
||||
.short 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1
|
||||
.short 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8
|
||||
.short 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
|
||||
|
||||
.end
|
||||
11
src/bootldr/crc.h
Normal file
11
src/bootldr/crc.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef CRC_H
|
||||
#define CRC_H
|
||||
|
||||
uint8_t crc7update(uint8_t crc, uint8_t data);
|
||||
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data);
|
||||
uint16_t crc_xmodem_block(uint16_t crc, const uint8_t *data, uint32_t length);
|
||||
|
||||
// AVR-libc compatibility
|
||||
#define _crc_xmodem_update(crc,data) crc_xmodem_update(crc,data)
|
||||
|
||||
#endif
|
||||
110
src/bootldr/crc32.c
Normal file
110
src/bootldr/crc32.c
Normal file
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* \file crc32.c
|
||||
* Functions and types for CRC checks.
|
||||
*
|
||||
* Generated on Sat Sep 25 18:06:34 2010,
|
||||
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||
* using the configuration:
|
||||
* Width = 32
|
||||
* Poly = 0x04c11db7
|
||||
* XorIn = 0xffffffff
|
||||
* ReflectIn = True
|
||||
* XorOut = 0xffffffff
|
||||
* ReflectOut = True
|
||||
* Algorithm = table-driven
|
||||
* Direct = True
|
||||
*****************************************************************************/
|
||||
#include "crc32.h"
|
||||
#include "config.h"
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Static table used for the table_driven implementation.
|
||||
*****************************************************************************/
|
||||
static const uint32_t crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the crc value with new data.
|
||||
*
|
||||
* \param crc The current crc value.
|
||||
* \param data Pointer to a buffer of \a data_len bytes.
|
||||
* \param data_len Number of bytes in the \a data buffer.
|
||||
* \return The updated crc value.
|
||||
*****************************************************************************/
|
||||
uint32_t crc32_update(uint32_t crc, const unsigned char data)
|
||||
{
|
||||
unsigned int tbl_idx;
|
||||
|
||||
tbl_idx = (crc ^ data) & 0xff;
|
||||
crc = (crc32_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
|
||||
|
||||
return crc & 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
68
src/bootldr/crc32.h
Normal file
68
src/bootldr/crc32.h
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* \file crc32.h
|
||||
* Functions and types for CRC checks.
|
||||
*
|
||||
* Generated on Sat Sep 25 18:06:37 2010,
|
||||
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||
* using the configuration:
|
||||
* Width = 32
|
||||
* Poly = 0x04c11db7
|
||||
* XorIn = 0xffffffff
|
||||
* ReflectIn = True
|
||||
* XorOut = 0xffffffff
|
||||
* ReflectOut = True
|
||||
* Algorithm = table-driven
|
||||
* Direct = True
|
||||
*****************************************************************************/
|
||||
#ifndef __CRC___H__
|
||||
#define __CRC___H__
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The definition of the used algorithm.
|
||||
*****************************************************************************/
|
||||
#define CRC_ALGO_TABLE_DRIVEN 1
|
||||
|
||||
/**
|
||||
* Calculate the initial crc value.
|
||||
*
|
||||
* \return The initial crc value.
|
||||
*****************************************************************************/
|
||||
static inline uint32_t crc_init(void)
|
||||
{
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the crc value with new data.
|
||||
*
|
||||
* \param crc The current crc value.
|
||||
* \param data Pointer to a buffer of \a data_len bytes.
|
||||
* \param data_len Number of bytes in the \a data buffer.
|
||||
* \return The updated crc value.
|
||||
*****************************************************************************/
|
||||
uint32_t crc32_update(uint32_t crc, const unsigned char data);
|
||||
|
||||
/**
|
||||
* Calculate the final crc value.
|
||||
*
|
||||
* \param crc The current crc value.
|
||||
* \return The final crc value.
|
||||
*****************************************************************************/
|
||||
static inline uint32_t crc32_finalize(uint32_t crc)
|
||||
{
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* closing brace for extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* __CRC___H__ */
|
||||
119
src/bootldr/diskio.h
Normal file
119
src/bootldr/diskio.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2010
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO
|
||||
|
||||
#define _READONLY 0 /* 1: Remove write functions */
|
||||
#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
|
||||
#include "integer.h"
|
||||
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
|
||||
/* Results of Disk Functions */
|
||||
typedef enum {
|
||||
RES_OK = 0, /* 0: Successful */
|
||||
RES_ERROR, /* 1: R/W Error */
|
||||
RES_WRPRT, /* 2: Write Protected */
|
||||
RES_NOTRDY, /* 3: Not Ready */
|
||||
RES_PARERR /* 4: Invalid Parameter */
|
||||
} DRESULT;
|
||||
|
||||
/**
|
||||
* struct diskinfo0_t - disk info data structure for page 0
|
||||
* @validbytes : Number of valid bytes in this struct
|
||||
* @maxpage : Highest diskinfo page supported
|
||||
* @disktype : type of the disk (DISK_TYPE_* values)
|
||||
* @sectorsize : sector size divided by 256
|
||||
* @sectorcount: number of sectors on the disk
|
||||
*
|
||||
* This is the struct returned in the data buffer when disk_getinfo
|
||||
* is called with page=0.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t validbytes;
|
||||
uint8_t maxpage;
|
||||
uint8_t disktype;
|
||||
uint8_t sectorsize; /* divided by 256 */
|
||||
uint32_t sectorcount; /* 2 TB should be enough... (512 byte sectors) */
|
||||
} diskinfo0_t;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
int assign_drives (int, int);
|
||||
DSTATUS disk_initialize (BYTE);
|
||||
DSTATUS disk_status (BYTE);
|
||||
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
||||
#if _READONLY == 0
|
||||
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
||||
#endif
|
||||
#define disk_ioctl(a,b,c) RES_OK
|
||||
#define get_fattime() (0)
|
||||
|
||||
void disk_init(void);
|
||||
|
||||
/* Will be set to DISK_ERROR if any access on the card fails */
|
||||
enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR };
|
||||
|
||||
extern int sd_offload, ff_sd_offload, sd_offload_tgt, newcard;
|
||||
extern int sd_offload_partial;
|
||||
extern uint16_t sd_offload_partial_start;
|
||||
extern uint16_t sd_offload_partial_end;
|
||||
extern volatile enum diskstates disk_state;
|
||||
|
||||
/* Disk type - part of the external API except for ATA2! */
|
||||
#define DISK_TYPE_ATA 0
|
||||
#define DISK_TYPE_ATA2 1
|
||||
#define DISK_TYPE_SD 2
|
||||
#define DISK_TYPE_DF 3
|
||||
#define DISK_TYPE_NONE 7
|
||||
|
||||
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
#define STA_PROTECT 0x04 /* Write protected */
|
||||
|
||||
|
||||
/* Command code for disk_ioctrl fucntion */
|
||||
|
||||
/* Generic command (defined for FatFs) */
|
||||
#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */
|
||||
#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */
|
||||
#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
|
||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */
|
||||
#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */
|
||||
|
||||
/* Generic command */
|
||||
#define CTRL_POWER 5 /* Get/Set power status */
|
||||
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
|
||||
#define CTRL_EJECT 7 /* Eject media */
|
||||
|
||||
/* MMC/SDC specific ioctl command */
|
||||
#define MMC_GET_TYPE 10 /* Get card type */
|
||||
#define MMC_GET_CSD 11 /* Get CSD */
|
||||
#define MMC_GET_CID 12 /* Get CID */
|
||||
#define MMC_GET_OCR 13 /* Get OCR */
|
||||
#define MMC_GET_SDSTAT 14 /* Get SD status */
|
||||
|
||||
/* ATA/CF specific ioctl command */
|
||||
#define ATA_GET_REV 20 /* Get F/W revision */
|
||||
#define ATA_GET_MODEL 21 /* Get model name */
|
||||
#define ATA_GET_SN 22 /* Get serial number */
|
||||
|
||||
/* NAND specific ioctl command */
|
||||
#define NAND_FORMAT 30 /* Create physical format */
|
||||
|
||||
|
||||
#define _DISKIO
|
||||
#endif
|
||||
4
src/bootldr/erase.cfg
Normal file
4
src/bootldr/erase.cfg
Normal file
@ -0,0 +1,4 @@
|
||||
# script running on reset
|
||||
init
|
||||
script erase.script
|
||||
|
||||
12
src/bootldr/erase.script
Normal file
12
src/bootldr/erase.script
Normal file
@ -0,0 +1,12 @@
|
||||
# mthomas 4/2008, tested with OpenOCD SVN555
|
||||
|
||||
#flash probe 0
|
||||
#flash erase_check 0
|
||||
#flash protect_check 0
|
||||
#flash info 0
|
||||
|
||||
reset init
|
||||
flash erase_sector 0 0 last
|
||||
reset run
|
||||
shutdown
|
||||
|
||||
20
src/bootldr/faulthandler.c
Normal file
20
src/bootldr/faulthandler.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "uart.h"
|
||||
|
||||
void HardFault_Handler(void) {
|
||||
printf("HFSR: %lx\n", SCB->HFSR);
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
void MemManage_Handler(void) {
|
||||
printf("MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR);
|
||||
}
|
||||
|
||||
void BusFault_Handler(void) {
|
||||
printf("BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR);
|
||||
}
|
||||
|
||||
void UsageFault_Handler(void) {
|
||||
printf("UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR);
|
||||
}
|
||||
|
||||
3757
src/bootldr/ff.c
Normal file
3757
src/bootldr/ff.c
Normal file
File diff suppressed because it is too large
Load Diff
546
src/bootldr/ff.h
Normal file
546
src/bootldr/ff.h
Normal file
@ -0,0 +1,546 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module include file R0.08a (C)ChaN, 2010
|
||||
/----------------------------------------------------------------------------/
|
||||
/ FatFs module is a generic FAT file system module for small embedded systems.
|
||||
/ This is a free software that opened for education, research and commercial
|
||||
/ developments under license policy of following trems.
|
||||
/
|
||||
/ Copyright (C) 2010, ChaN, all right reserved.
|
||||
/
|
||||
/ * The FatFs module is a free software and there is NO WARRANTY.
|
||||
/ * No restriction on use. You can use, modify and redistribute it for
|
||||
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
|
||||
/ * Redistributions of source code must retain the above copyright notice.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _FATFS
|
||||
#define _FATFS 8255 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "integer.h" /* Basic integer types */
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
|
||||
#if _FATFS != _FFCONF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
#endif
|
||||
|
||||
|
||||
/* DBCS code ranges and SBCS extend char conversion table */
|
||||
|
||||
#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
|
||||
#define _DF1S 0x81 /* DBC 1st byte range 1 start */
|
||||
#define _DF1E 0x9F /* DBC 1st byte range 1 end */
|
||||
#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
|
||||
#define _DF2E 0xFC /* DBC 1st byte range 2 end */
|
||||
#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
|
||||
#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
|
||||
#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
|
||||
#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
|
||||
|
||||
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
|
||||
#define _DF1S 0x81
|
||||
#define _DF1E 0xFE
|
||||
#define _DS1S 0x40
|
||||
#define _DS1E 0x7E
|
||||
#define _DS2S 0x80
|
||||
#define _DS2E 0xFE
|
||||
|
||||
#elif _CODE_PAGE == 949 /* Korean */
|
||||
#define _DF1S 0x81
|
||||
#define _DF1E 0xFE
|
||||
#define _DS1S 0x41
|
||||
#define _DS1E 0x5A
|
||||
#define _DS2S 0x61
|
||||
#define _DS2E 0x7A
|
||||
#define _DS3S 0x81
|
||||
#define _DS3E 0xFE
|
||||
|
||||
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
|
||||
#define _DF1S 0x81
|
||||
#define _DF1E 0xFE
|
||||
#define _DS1S 0x40
|
||||
#define _DS1E 0x7E
|
||||
#define _DS2S 0xA1
|
||||
#define _DS2E 0xFE
|
||||
|
||||
#elif _CODE_PAGE == 437 /* U.S. (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 720 /* Arabic (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 737 /* Greek (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
|
||||
0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 775 /* Baltic (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
|
||||
0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
|
||||
0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 857 /* Turkish (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 862 /* Hebrew (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 866 /* Russian (OEM) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
|
||||
0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
|
||||
|
||||
#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
|
||||
|
||||
#elif _CODE_PAGE == 1253 /* Greek (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
|
||||
0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
|
||||
|
||||
#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
|
||||
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
|
||||
|
||||
#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
|
||||
#define _DF1S 0
|
||||
#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
|
||||
0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
|
||||
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
|
||||
|
||||
#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
|
||||
#define _DF1S 0
|
||||
|
||||
#else
|
||||
#error Unknown code page
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Definitions of volume management */
|
||||
|
||||
#if _MULTI_PARTITION /* Multiple partition configuration */
|
||||
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
|
||||
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
|
||||
typedef struct {
|
||||
BYTE pd; /* Physical drive# */
|
||||
BYTE pt; /* Partition # (0-3) */
|
||||
} PARTITION;
|
||||
extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */
|
||||
|
||||
#else /* Single partition configuration */
|
||||
#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */
|
||||
#define LD2PT(vol) 0 /* Always mounts the 1st partition */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Type of path name strings on FatFs API */
|
||||
|
||||
#if _LFN_UNICODE /* Unicode string */
|
||||
#if !_USE_LFN
|
||||
#error _LFN_UNICODE must be 0 in non-LFN cfg.
|
||||
#endif
|
||||
#ifndef _INC_TCHAR
|
||||
typedef WCHAR TCHAR;
|
||||
#define _T(x) L ## x
|
||||
#define _TEXT(x) L ## x
|
||||
#endif
|
||||
|
||||
#else /* ANSI/OEM string */
|
||||
#ifndef _INC_TCHAR
|
||||
typedef char TCHAR;
|
||||
#define _T(x) x
|
||||
#define _TEXT(x) x
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* File system object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
|
||||
BYTE drv; /* Physical drive number */
|
||||
BYTE csize; /* Sectors per cluster (1,2,4...128) */
|
||||
BYTE n_fats; /* Number of FAT copies (1,2) */
|
||||
BYTE wflag; /* win[] dirty flag (1:must be written back) */
|
||||
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
|
||||
WORD id; /* File system mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
#if _MAX_SS != 512
|
||||
WORD ssize; /* Bytes per sector (512,1024,2048,4096) */
|
||||
#endif
|
||||
#if _FS_REENTRANT
|
||||
_SYNC_t sobj; /* Identifier of sync object */
|
||||
#endif
|
||||
#if !_FS_READONLY
|
||||
DWORD last_clust; /* Last allocated cluster */
|
||||
DWORD free_clust; /* Number of free clusters */
|
||||
DWORD fsi_sector; /* fsinfo sector (FAT32) */
|
||||
#endif
|
||||
#if _FS_RPATH
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#endif
|
||||
DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
|
||||
DWORD fsize; /* Sectors per FAT */
|
||||
DWORD fatbase; /* FAT start sector */
|
||||
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
|
||||
DWORD database; /* Data start sector */
|
||||
DWORD winsect; /* Current sector appearing in the win[] */
|
||||
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the owner file system object */
|
||||
WORD id; /* Owner file system mount ID */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE pad1;
|
||||
DWORD fptr; /* File read/write pointer (0 on file open) */
|
||||
DWORD fsize; /* File size */
|
||||
DWORD org_clust; /* File start cluster (0 when fsize==0) */
|
||||
DWORD curr_clust; /* Current cluster */
|
||||
DWORD dsect; /* Current data sector */
|
||||
#if !_FS_READONLY
|
||||
DWORD dir_sect; /* Sector containing the directory entry */
|
||||
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
|
||||
#endif
|
||||
#if _USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
|
||||
#endif
|
||||
#if _FS_SHARE
|
||||
UINT lockid; /* File lock ID (index of file semaphore table) */
|
||||
#endif
|
||||
#if !_FS_TINY
|
||||
BYTE buf[_MAX_SS]; /* File data read/write buffer */
|
||||
#endif
|
||||
} FIL;
|
||||
|
||||
|
||||
|
||||
/* Directory object structure (DIR) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the owner file system object */
|
||||
WORD id; /* Owner file system mount ID */
|
||||
WORD index; /* Current read/write index number */
|
||||
DWORD sclust; /* Table start cluster (0:Root dir) */
|
||||
DWORD clust; /* Current cluster */
|
||||
DWORD sect; /* Current sector */
|
||||
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
|
||||
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
||||
#if _USE_LFN
|
||||
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
||||
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
|
||||
#endif
|
||||
} DIR;
|
||||
|
||||
|
||||
|
||||
/* File status structure (FILINFO) */
|
||||
|
||||
typedef struct {
|
||||
DWORD fsize; /* File size */
|
||||
WORD fdate; /* Last modified date */
|
||||
WORD ftime; /* Last modified time */
|
||||
BYTE fattrib; /* Attribute */
|
||||
TCHAR fname[13]; /* Short file name (8.3 format) */
|
||||
DWORD clust; /* start cluster */
|
||||
#if _USE_LFN
|
||||
TCHAR* lfname; /* Pointer to the LFN buffer */
|
||||
UINT lfsize; /* Size of LFN buffer in TCHAR */
|
||||
#endif
|
||||
} FILINFO;
|
||||
|
||||
|
||||
|
||||
/* File function return code (FRESULT) */
|
||||
|
||||
typedef enum {
|
||||
FR_OK = 0, /* (0) Succeeded */
|
||||
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
|
||||
FR_INT_ERR, /* (2) Assertion failed */
|
||||
FR_NOT_READY, /* (3) The physical drive cannot work */
|
||||
FR_NO_FILE, /* (4) Could not find the file */
|
||||
FR_NO_PATH, /* (5) Could not find the path */
|
||||
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
||||
FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */
|
||||
FR_EXIST, /* (8) Acces denied due to prohibited access */
|
||||
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
||||
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
||||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
|
||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
||||
FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */
|
||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||
FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */
|
||||
} FRESULT;
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* FatFs module application interface */
|
||||
|
||||
/* Low Level functions */
|
||||
FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */
|
||||
|
||||
/* application level functions */
|
||||
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
||||
FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */
|
||||
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
|
||||
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
|
||||
FRESULT f_close (FIL*); /* Close an open file object */
|
||||
FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */
|
||||
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
|
||||
FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */
|
||||
|
||||
#if !_FS_READONLY
|
||||
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
|
||||
FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
|
||||
FRESULT f_truncate (FIL*); /* Truncate file */
|
||||
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
|
||||
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
|
||||
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
|
||||
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */
|
||||
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */
|
||||
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
|
||||
#endif
|
||||
|
||||
#if _USE_FORWARD
|
||||
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
|
||||
#endif
|
||||
|
||||
#if _USE_MKFS
|
||||
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
|
||||
#endif
|
||||
|
||||
#if _FS_RPATH
|
||||
FRESULT f_chdrive (BYTE); /* Change current drive */
|
||||
FRESULT f_chdir (const TCHAR*); /* Change current directory */
|
||||
FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
|
||||
#endif
|
||||
|
||||
#if _USE_STRFUNC
|
||||
int f_putc (TCHAR, FIL*); /* Put a character to the file */
|
||||
int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
|
||||
int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
|
||||
TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
|
||||
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
|
||||
#define f_tell(fp) ((fp)->fptr)
|
||||
#define f_size(fp) ((fp)->fsize)
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Additional user defined functions */
|
||||
|
||||
/* RTC function */
|
||||
#if !_FS_READONLY
|
||||
DWORD get_fattime (void);
|
||||
#endif
|
||||
|
||||
/* Unicode support functions */
|
||||
#if _USE_LFN /* Unicode - OEM code conversion */
|
||||
WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */
|
||||
WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */
|
||||
#if _USE_LFN == 3 /* Memory functions */
|
||||
void* ff_memalloc (UINT); /* Allocate memory block */
|
||||
void ff_memfree (void*); /* Free memory block */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Sync functions */
|
||||
#if _FS_REENTRANT
|
||||
int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */
|
||||
int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
|
||||
int ff_req_grant (_SYNC_t); /* Lock sync object */
|
||||
void ff_rel_grant (_SYNC_t); /* Unlock sync object */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Flags and offset address */
|
||||
|
||||
|
||||
/* File access control and file status flags (FIL.flag) */
|
||||
|
||||
#define FA_READ 0x01
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
#define FA__ERROR 0x80
|
||||
|
||||
#if !_FS_READONLY
|
||||
#define FA_WRITE 0x02
|
||||
#define FA_CREATE_NEW 0x04
|
||||
#define FA_CREATE_ALWAYS 0x08
|
||||
#define FA_OPEN_ALWAYS 0x10
|
||||
#define FA__WRITTEN 0x20
|
||||
#define FA__DIRTY 0x40
|
||||
#endif
|
||||
|
||||
|
||||
/* FAT sub type (FATFS.fs_type) */
|
||||
|
||||
#define FS_FAT12 1
|
||||
#define FS_FAT16 2
|
||||
#define FS_FAT32 3
|
||||
|
||||
|
||||
/* File attribute bits for directory entry */
|
||||
|
||||
#define AM_RDO 0x01 /* Read only */
|
||||
#define AM_HID 0x02 /* Hidden */
|
||||
#define AM_SYS 0x04 /* System */
|
||||
#define AM_VOL 0x08 /* Volume label */
|
||||
#define AM_LFN 0x0F /* LFN entry */
|
||||
#define AM_DIR 0x10 /* Directory */
|
||||
#define AM_ARC 0x20 /* Archive */
|
||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||
|
||||
|
||||
/* Fast seek function */
|
||||
#define CREATE_LINKMAP 0xFFFFFFFF
|
||||
|
||||
|
||||
/*--------------------------------*/
|
||||
/* Multi-byte word access macros */
|
||||
|
||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||
#else /* Use byte-by-byte access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FATFS */
|
||||
188
src/bootldr/ffconf.h
Normal file
188
src/bootldr/ffconf.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.08a (C)ChaN, 2010
|
||||
/----------------------------------------------------------------------------/
|
||||
/
|
||||
/ CAUTION! Do not forget to make clean the project after any changes to
|
||||
/ the configuration options.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
#ifndef _FFCONF
|
||||
#define _FFCONF 8255 /* Revision ID */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function and Buffer Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
|
||||
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
|
||||
/ object instead of the sector buffer in the individual file object for file
|
||||
/ data transfer. This reduces memory consumption 512 bytes each file object. */
|
||||
|
||||
|
||||
#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
|
||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
||||
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
||||
/ f_truncate and useless f_getfree. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 2 /* 0 to 3 */
|
||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||
/
|
||||
/ 0: Full function.
|
||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
||||
/ are removed.
|
||||
/ 2: f_opendir and f_readdir are removed in addition to 1.
|
||||
/ 3: f_lseek is removed in addition to 2. */
|
||||
|
||||
|
||||
#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */
|
||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||
|
||||
|
||||
#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
||||
|
||||
|
||||
#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
||||
|
||||
|
||||
#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _CODE_PAGE 1252
|
||||
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
|
||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||
/ 949 - Korean (DBCS, OEM, Windows)
|
||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||
/ 1250 - Central Europe (Windows)
|
||||
/ 1251 - Cyrillic (Windows)
|
||||
/ 1252 - Latin 1 (Windows)
|
||||
/ 1253 - Greek (Windows)
|
||||
/ 1254 - Turkish (Windows)
|
||||
/ 1255 - Hebrew (Windows)
|
||||
/ 1256 - Arabic (Windows)
|
||||
/ 1257 - Baltic (Windows)
|
||||
/ 1258 - Vietnam (OEM, Windows)
|
||||
/ 437 - U.S. (OEM)
|
||||
/ 720 - Arabic (OEM)
|
||||
/ 737 - Greek (OEM)
|
||||
/ 775 - Baltic (OEM)
|
||||
/ 850 - Multilingual Latin 1 (OEM)
|
||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||
/ 852 - Latin 2 (OEM)
|
||||
/ 855 - Cyrillic (OEM)
|
||||
/ 866 - Russian (OEM)
|
||||
/ 857 - Turkish (OEM)
|
||||
/ 862 - Hebrew (OEM)
|
||||
/ 874 - Thai (OEM, Windows)
|
||||
/ 1 - ASCII only (Valid for non LFN cfg.)
|
||||
*/
|
||||
|
||||
|
||||
#define _USE_LFN 0 /* 0 to 3 */
|
||||
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
|
||||
/* The _USE_LFN option switches the LFN support.
|
||||
/
|
||||
/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
|
||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
|
||||
/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
|
||||
/ to the project. When enable to use heap, memory control functions
|
||||
/ ff_memalloc() and ff_memfree() must be added to the project. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
|
||||
/* To switch the character code set on FatFs API to Unicode,
|
||||
/ enable LFN feature and set _LFN_UNICODE to 1. */
|
||||
|
||||
|
||||
#define _FS_RPATH 0 /* 0 to 2 */
|
||||
/* The _FS_RPATH option configures relative path feature.
|
||||
/
|
||||
/ 0: Disable relative path feature and remove related functions.
|
||||
/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
|
||||
/ 2: f_getcwd() is available in addition to 1.
|
||||
/
|
||||
/ Note that output of the f_readdir fnction is affected by this option. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Physical Drive Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _VOLUMES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
|
||||
|
||||
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
|
||||
/* Maximum sector size to be handled.
|
||||
/ Always set 512 for memory card and hard disk but a larger value may be
|
||||
/ required for floppy disk (512/1024) and optical disk (512/2048).
|
||||
/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted
|
||||
/ to the disk_ioctl function. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */
|
||||
/* When set to 0, each volume is bound to the same physical drive number and
|
||||
/ it can mount only first primaly partition. When it is set to 1, each volume
|
||||
/ is tied to the partitions listed in VolToPart[]. */
|
||||
|
||||
|
||||
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable sector erase feature, set _USE_ERASE to 1. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _WORD_ACCESS 0 /* 0 or 1 */
|
||||
/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
|
||||
/ option defines which access method is used to the word data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access.
|
||||
/ 1: Word access. Do not choose this unless following condition is met.
|
||||
/
|
||||
/ When the byte order on the memory is big-endian or address miss-aligned word
|
||||
/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
|
||||
/ If it is not the case, the value can also be set to 1 to improve the
|
||||
/ performance and code size. */
|
||||
|
||||
|
||||
/* Include a header file here to define sync object types on the O/S */
|
||||
/* #include <windows.h>, <ucos_ii.h.h>, <semphr.h> or ohters. */
|
||||
|
||||
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
|
||||
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
||||
#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
|
||||
|
||||
/* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
|
||||
/
|
||||
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
|
||||
/ 1: Enable reentrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
|
||||
/ function must be added to the project. */
|
||||
|
||||
|
||||
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
|
||||
/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
|
||||
defines how many files can be opened simultaneously. */
|
||||
|
||||
|
||||
#endif /* _FFCONFIG */
|
||||
109
src/bootldr/fileops.c
Normal file
109
src/bootldr/fileops.c
Normal file
@ -0,0 +1,109 @@
|
||||
/* 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
|
||||
|
||||
fileops.c: simple file access functions
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "uart.h"
|
||||
#include "ff.h"
|
||||
#include "fileops.h"
|
||||
#include "diskio.h"
|
||||
|
||||
/*
|
||||
WCHAR ff_convert(WCHAR w, UINT dir) {
|
||||
return w;
|
||||
}*/
|
||||
|
||||
int newcard;
|
||||
|
||||
void file_init() {
|
||||
file_res=f_mount(0, &fatfs);
|
||||
newcard = 0;
|
||||
}
|
||||
|
||||
void file_reinit(void) {
|
||||
disk_init();
|
||||
file_init();
|
||||
}
|
||||
|
||||
void file_open_by_filinfo(FILINFO* fno) {
|
||||
file_res = l_openfilebycluster(&fatfs, &file_handle, (TCHAR*)"", fno->clust, fno->fsize);
|
||||
}
|
||||
|
||||
void file_open(uint8_t* filename, BYTE flags) {
|
||||
if (disk_state == DISK_CHANGED) {
|
||||
file_reinit();
|
||||
newcard = 1;
|
||||
}
|
||||
file_res = f_open(&file_handle, (TCHAR*)filename, flags);
|
||||
file_block_off = sizeof(file_buf);
|
||||
file_block_max = sizeof(file_buf);
|
||||
file_status = file_res ? FILE_ERR : FILE_OK;
|
||||
}
|
||||
|
||||
void file_close() {
|
||||
file_res = f_close(&file_handle);
|
||||
}
|
||||
|
||||
UINT file_read() {
|
||||
UINT bytes_read;
|
||||
file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
UINT file_write() {
|
||||
UINT bytes_written;
|
||||
file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written);
|
||||
if(bytes_written < sizeof(file_buf)) {
|
||||
printf("wrote less than expected - card full?\n");
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
|
||||
UINT bytes_read;
|
||||
file_res = f_lseek(&file_handle, addr);
|
||||
if(file_handle.fptr != addr) {
|
||||
return 0;
|
||||
}
|
||||
file_res = f_read(&file_handle, buf, size, &bytes_read);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
|
||||
UINT bytes_written;
|
||||
file_res = f_lseek(&file_handle, addr);
|
||||
if(file_res) return 0;
|
||||
file_res = f_write(&file_handle, buf, size, &bytes_written);
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
uint8_t file_getc() {
|
||||
if(file_block_off == file_block_max) {
|
||||
file_block_max = file_read();
|
||||
if(file_block_max == 0) file_status = FILE_EOF;
|
||||
file_block_off = 0;
|
||||
}
|
||||
return file_buf[file_block_off++];
|
||||
}
|
||||
52
src/bootldr/fileops.h
Normal file
52
src/bootldr/fileops.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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
|
||||
|
||||
fileops.h: simple file access functions
|
||||
*/
|
||||
|
||||
#ifndef FILEOPS_H
|
||||
#define FILEOPS_H
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "ff.h"
|
||||
|
||||
enum filestates { FILE_OK=0, FILE_ERR, FILE_EOF };
|
||||
|
||||
BYTE file_buf[512];
|
||||
FATFS fatfs;
|
||||
FIL file_handle;
|
||||
FRESULT file_res;
|
||||
uint8_t file_lfn[258];
|
||||
uint16_t file_block_off, file_block_max;
|
||||
enum filestates file_status;
|
||||
|
||||
void file_init(void);
|
||||
void file_open(uint8_t* filename, BYTE flags);
|
||||
void file_open_by_filinfo(FILINFO* fno);
|
||||
void file_close(void);
|
||||
UINT file_read(void);
|
||||
UINT file_write(void);
|
||||
UINT file_readblock(void* buf, uint32_t addr, uint16_t size);
|
||||
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size);
|
||||
|
||||
uint8_t file_getc(void);
|
||||
#endif
|
||||
4
src/bootldr/flash.cfg
Normal file
4
src/bootldr/flash.cfg
Normal file
@ -0,0 +1,4 @@
|
||||
# script running on reset
|
||||
init
|
||||
script flash.script
|
||||
|
||||
12
src/bootldr/flash.script
Normal file
12
src/bootldr/flash.script
Normal file
@ -0,0 +1,12 @@
|
||||
# mthomas 4/2008, tested with OpenOCD SVN555
|
||||
|
||||
#flash probe 0
|
||||
#flash erase_check 0
|
||||
#flash protect_check 0
|
||||
#flash info 0
|
||||
|
||||
reset init
|
||||
flash write_image erase unlock obj/sd2snes_bootldr.elf
|
||||
reset run
|
||||
shutdown
|
||||
|
||||
184
src/bootldr/iap.c
Normal file
184
src/bootldr/iap.c
Normal file
@ -0,0 +1,184 @@
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include <string.h>
|
||||
#include "bits.h"
|
||||
#include "iap.h"
|
||||
#include "config.h"
|
||||
#include "uart.h"
|
||||
#include "fileops.h"
|
||||
#include "crc32.h"
|
||||
|
||||
uint32_t iap_cmd[5];
|
||||
uint32_t iap_res[5];
|
||||
uint32_t flash_sig[4];
|
||||
|
||||
IAP iap_entry = (IAP) IAP_LOCATION;
|
||||
|
||||
uint32_t calc_flash_crc(uint32_t start, uint32_t len) {
|
||||
printf("calc_flash_crc(%08lx, %08lx) {\n", start, len);
|
||||
uint32_t end = start + len;
|
||||
if(end > 0x20000) {
|
||||
len = 0x1ffff - start;
|
||||
end = 0x20000;
|
||||
}
|
||||
uint32_t crc = 0xffffffff;
|
||||
uint32_t s = start;
|
||||
while(s < end) {
|
||||
crc = crc32_update(crc, *(const unsigned char*)(s));
|
||||
s++;
|
||||
}
|
||||
crc ^= 0xffffffff;
|
||||
printf(" crc generated. result=%08lx\n", crc);
|
||||
printf("} //calc_flash_crc\n");
|
||||
return crc;
|
||||
}
|
||||
|
||||
void test_iap() {
|
||||
iap_cmd[0]=54;
|
||||
iap_entry(iap_cmd, iap_res);
|
||||
printf("Part ID=%08lx\n", iap_res[1]);
|
||||
}
|
||||
|
||||
void print_header(sd2snes_fw_header *header) {
|
||||
printf(" magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n",
|
||||
header->magic, header->version, header->size,
|
||||
header->crc, header->crcc);
|
||||
}
|
||||
|
||||
int check_header(sd2snes_fw_header *header, uint32_t crc) {
|
||||
if((header->magic != FW_MAGIC)
|
||||
|| (header->size < 0x200)
|
||||
|| (header->size > (0x1ffff - FW_START))
|
||||
|| ((header->crc ^ header->crcc) != 0xffffffff)) {
|
||||
return ERR_FLASHHD;
|
||||
}
|
||||
if(header->crc != crc) {
|
||||
return ERR_FLASHCRC;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
FLASH_RES check_flash() {
|
||||
sd2snes_fw_header *fw_header = (sd2snes_fw_header*) FW_START;
|
||||
uint32_t flash_addr = FW_START;
|
||||
if(flash_addr != FW_START) {
|
||||
printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
|
||||
return ERR_HW;
|
||||
}
|
||||
printf("Current flash contents:\n");
|
||||
print_header(fw_header);
|
||||
uint32_t crc = calc_flash_crc(flash_addr + 0x100, (fw_header->size & 0x1ffff));
|
||||
return check_header(fw_header, crc);
|
||||
}
|
||||
|
||||
IAP_RES iap_wrap(uint32_t *iap_cmd, uint32_t *iap_res) {
|
||||
NVIC_DisableIRQ(RIT_IRQn);
|
||||
NVIC_DisableIRQ(UART_IRQ);
|
||||
iap_entry(iap_cmd, iap_res);
|
||||
NVIC_EnableIRQ(RIT_IRQn);
|
||||
NVIC_EnableIRQ(UART_IRQ);
|
||||
return iap_res[0];
|
||||
}
|
||||
|
||||
IAP_RES iap_prepare_for_write(uint32_t start, uint32_t end) {
|
||||
if(start < (FW_START / 0x1000)) return INVALID_SECTOR;
|
||||
iap_cmd[0] = 50;
|
||||
iap_cmd[1] = start;
|
||||
iap_cmd[2] = end;
|
||||
iap_wrap(iap_cmd, iap_res);
|
||||
return iap_res[0];
|
||||
}
|
||||
|
||||
IAP_RES iap_erase(uint32_t start, uint32_t end) {
|
||||
if(start < (FW_START / 0x1000)) return INVALID_SECTOR;
|
||||
iap_cmd[0] = 52;
|
||||
iap_cmd[1] = start;
|
||||
iap_cmd[2] = end;
|
||||
iap_cmd[3] = CONFIG_CPU_FREQUENCY / 1000L;
|
||||
iap_wrap(iap_cmd, iap_res);
|
||||
return iap_res[0];
|
||||
}
|
||||
|
||||
IAP_RES iap_ram2flash(uint32_t tgt, uint8_t *src, int num) {
|
||||
iap_cmd[0] = 51;
|
||||
iap_cmd[1] = tgt;
|
||||
iap_cmd[2] = (uint32_t)src;
|
||||
iap_cmd[3] = num;
|
||||
iap_cmd[4] = CONFIG_CPU_FREQUENCY / 1000L;
|
||||
iap_wrap(iap_cmd, iap_res);
|
||||
return iap_res[0];
|
||||
}
|
||||
|
||||
FLASH_RES flash_file(uint8_t *filename) {
|
||||
sd2snes_fw_header *fw_header = (sd2snes_fw_header*) FW_START;
|
||||
uint32_t flash_addr = FW_START;
|
||||
uint32_t file_crc = 0xffffffff;
|
||||
uint16_t count;
|
||||
sd2snes_fw_header file_header;
|
||||
UINT bytes_read;
|
||||
if(flash_addr != FW_START) {
|
||||
printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
|
||||
return ERR_HW;
|
||||
}
|
||||
file_open(filename, FA_READ);
|
||||
if(file_res) {
|
||||
printf("file_open: error %d\n", file_res);
|
||||
return ERR_FS;
|
||||
}
|
||||
printf("firmware image found. file size: %ld\n", file_handle.fsize);
|
||||
printf("reading header...\n");
|
||||
f_read(&file_handle, &file_header, 32, &bytes_read);
|
||||
print_header(&file_header);
|
||||
if(check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC || fw_header->version == FW_MAGIC) {
|
||||
f_lseek(&file_handle, 0x100);
|
||||
for(;;) {
|
||||
bytes_read = file_read();
|
||||
if(file_res || !bytes_read) break;
|
||||
for(count = 0; count < bytes_read; count++) {
|
||||
file_crc = crc32_update(file_crc, file_buf[count]);
|
||||
}
|
||||
}
|
||||
file_crc ^= 0xffffffff;
|
||||
printf("file crc=%08lx\n", file_crc);
|
||||
if(check_header(&file_header, file_header.crc) != ERR_OK) {
|
||||
printf("Invalid firmware file (header corrupted).\n");
|
||||
return ERR_FILEHD;
|
||||
}
|
||||
if(file_header.crc != file_crc) {
|
||||
printf("Firmware file checksum error.\n");
|
||||
return ERR_FILECHK;
|
||||
}
|
||||
|
||||
uint32_t res;
|
||||
|
||||
printf("erasing flash...\n");
|
||||
if((res = iap_prepare_for_write(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
|
||||
printf("error %ld while preparing for erase\n", res);
|
||||
return ERR_FLASHPREP;
|
||||
};
|
||||
if((res = iap_erase(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
|
||||
printf("error %ld while erasing\n", res);
|
||||
return ERR_FLASHERASE;
|
||||
}
|
||||
printf("writing... @%08lx\n", flash_addr);
|
||||
f_lseek(&file_handle, 0);
|
||||
uint8_t current_sec;
|
||||
|
||||
for(flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200) {
|
||||
bytes_read = file_read();
|
||||
if(file_res || !bytes_read) break;
|
||||
current_sec = flash_addr & 0x10000 ? (16 + ((flash_addr >> 15) & 1))
|
||||
: (flash_addr >> 12);
|
||||
printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
|
||||
if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
|
||||
if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
|
||||
printf("error %ld while preparing sector %d for write\n", res, current_sec);
|
||||
}
|
||||
if((res = iap_ram2flash(flash_addr, file_buf, 512)) != CMD_SUCCESS) {
|
||||
printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
40
src/bootldr/iap.h
Normal file
40
src/bootldr/iap.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef IAP_H
|
||||
#define IAP_H
|
||||
|
||||
#define IAP_LOCATION 0x1fff1ff1
|
||||
typedef void (*IAP)(uint32_t*, uint32_t*);
|
||||
|
||||
typedef enum {ERR_OK = 0, ERR_HW, ERR_FS, ERR_FILEHD, ERR_FILECHK, ERR_FLASHHD, ERR_FLASHCRC, ERR_FLASHPREP, ERR_FLASHERASE, ERR_FLASH} FLASH_RES;
|
||||
|
||||
typedef enum {
|
||||
/* 0*/ CMD_SUCCESS = 0,
|
||||
/* 1*/ INVALID_COMMAND,
|
||||
/* 2*/ SRC_ADDR_ERROR,
|
||||
/* 3*/ DST_ADDR_ERROR,
|
||||
/* 4*/ SRC_ADDR_NOT_MAPPED,
|
||||
/* 5*/ DST_ADDR_NOT_MAPPED,
|
||||
/* 6*/ COUNT_ERROR,
|
||||
/* 7*/ INVALID_SECTOR,
|
||||
/* 8*/ SECTOR_NOT_BLANK,
|
||||
/* 9*/ SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
|
||||
/*10*/ COMPARE_ERROR,
|
||||
/*11*/ BUSY
|
||||
} IAP_RES;
|
||||
|
||||
#define FW_MAGIC (0x44534E53)
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint32_t size;
|
||||
uint32_t crc;
|
||||
uint32_t crcc;
|
||||
} sd2snes_fw_header;
|
||||
|
||||
uint32_t calc_flash_crc(uint32_t start, uint32_t end);
|
||||
void test_iap(void);
|
||||
FLASH_RES check_flash(void);
|
||||
FLASH_RES flash_file(uint8_t* filename);
|
||||
|
||||
|
||||
#endif
|
||||
37
src/bootldr/integer.h
Normal file
37
src/bootldr/integer.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*-------------------------------------------*/
|
||||
/* Integer type definitions for FatFs module */
|
||||
/*-------------------------------------------*/
|
||||
|
||||
#ifndef _INTEGER
|
||||
#define _INTEGER
|
||||
|
||||
#ifdef _WIN32 /* FatFs development platform */
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#else /* Embedded platform */
|
||||
|
||||
/* These types must be 16-bit, 32-bit or larger integer */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* These types must be 8-bit integer */
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
/* These types must be 16-bit integer */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
/* These types must be 32-bit integer */
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
131
src/bootldr/led.c
Normal file
131
src/bootldr/led.c
Normal file
@ -0,0 +1,131 @@
|
||||
/* ___DISCLAIMER___ */
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "bits.h"
|
||||
#include "timer.h"
|
||||
#include "led.h"
|
||||
|
||||
static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0};
|
||||
|
||||
int led_rdyledstate = 0;
|
||||
int led_readledstate = 0;
|
||||
int led_writeledstate = 0;
|
||||
int led_pwmstate = 0;
|
||||
|
||||
void rdyled(unsigned int state) {
|
||||
if(led_pwmstate) {
|
||||
rdybright(state?15:0);
|
||||
} else {
|
||||
BITBAND(LPC_GPIO2->FIODIR, 0) = state;
|
||||
}
|
||||
led_rdyledstate = state;
|
||||
}
|
||||
|
||||
void readled(unsigned int state) {
|
||||
if(led_pwmstate) {
|
||||
readbright(state?15:0);
|
||||
} else {
|
||||
BITBAND(LPC_GPIO2->FIODIR, 1) = state;
|
||||
}
|
||||
led_readledstate = state;
|
||||
}
|
||||
|
||||
void writeled(unsigned int state) {
|
||||
if(led_pwmstate) {
|
||||
writebright(state?15:0);
|
||||
} else {
|
||||
BITBAND(LPC_GPIO2->FIODIR, 2) = state;
|
||||
}
|
||||
led_writeledstate = state;
|
||||
}
|
||||
|
||||
void rdybright(uint8_t bright) {
|
||||
LPC_PWM1->MR1 = led_bright[(bright & 15)];
|
||||
BITBAND(LPC_PWM1->LER, 1) = 1;
|
||||
}
|
||||
void readbright(uint8_t bright) {
|
||||
LPC_PWM1->MR2 = led_bright[(bright & 15)];
|
||||
BITBAND(LPC_PWM1->LER, 2) = 1;
|
||||
}
|
||||
void writebright(uint8_t bright) {
|
||||
LPC_PWM1->MR3 = led_bright[(bright & 15)];
|
||||
BITBAND(LPC_PWM1->LER, 3) = 1;
|
||||
}
|
||||
|
||||
void led_clkout32(uint32_t val) {
|
||||
while(1) {
|
||||
rdyled(1);
|
||||
delay_ms(400);
|
||||
readled((val & BV(31))>>31);
|
||||
rdyled(0);
|
||||
val<<=1;
|
||||
delay_ms(400);
|
||||
}
|
||||
}
|
||||
|
||||
void toggle_rdy_led() {
|
||||
rdyled(~led_rdyledstate);
|
||||
}
|
||||
|
||||
void toggle_read_led() {
|
||||
readled(~led_readledstate);
|
||||
}
|
||||
|
||||
void toggle_write_led() {
|
||||
writeled(~led_writeledstate);
|
||||
}
|
||||
|
||||
void led_panic() {
|
||||
while(1) {
|
||||
LPC_GPIO2->FIODIR |= BV(0) | BV(1) | BV(2);
|
||||
delay_ms(350);
|
||||
LPC_GPIO2->FIODIR &= ~(BV(0) | BV(1) | BV(2));
|
||||
delay_ms(350);
|
||||
}
|
||||
}
|
||||
|
||||
void led_pwm() {
|
||||
/* connect PWM to P2.0 - P2.2 */
|
||||
/* XXX Rev.B P2.???? */
|
||||
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
|
||||
|
||||
BITBAND(LPC_PINCON->PINSEL4, 0) = 1;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 2) = 1;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 4) = 1;
|
||||
|
||||
BITBAND(LPC_PWM1->PCR, 9) = 1;
|
||||
BITBAND(LPC_PWM1->PCR, 10) = 1;
|
||||
BITBAND(LPC_PWM1->PCR, 11) = 1;
|
||||
|
||||
led_pwmstate = 1;
|
||||
}
|
||||
|
||||
void led_std() {
|
||||
BITBAND(LPC_PINCON->PINSEL4, 1) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 3) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 5) = 0;
|
||||
|
||||
BITBAND(LPC_PINCON->PINSEL4, 0) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 2) = 0;
|
||||
BITBAND(LPC_PINCON->PINSEL4, 4) = 0;
|
||||
|
||||
BITBAND(LPC_PWM1->PCR, 9) = 0;
|
||||
BITBAND(LPC_PWM1->PCR, 10) = 0;
|
||||
BITBAND(LPC_PWM1->PCR, 11) = 0;
|
||||
|
||||
led_pwmstate = 0;
|
||||
}
|
||||
|
||||
void led_init() {
|
||||
/* power is already connected by default */
|
||||
/* set PCLK divider to 8 */
|
||||
BITBAND(LPC_SC->PCLKSEL1, 21) = 1;
|
||||
BITBAND(LPC_SC->PCLKSEL1, 20) = 1;
|
||||
LPC_PWM1->MR0 = 255;
|
||||
BITBAND(LPC_PWM1->LER, 0) = 1;
|
||||
BITBAND(LPC_PWM1->TCR, 0) = 1;
|
||||
BITBAND(LPC_PWM1->TCR, 3) = 1;
|
||||
BITBAND(LPC_PWM1->MCR, 1) = 1;
|
||||
}
|
||||
21
src/bootldr/led.h
Normal file
21
src/bootldr/led.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* ___DISCLAIMER___ */
|
||||
|
||||
#ifndef _LED_H
|
||||
#define _LED_H
|
||||
|
||||
void readbright(uint8_t bright);
|
||||
void writebright(uint8_t bright);
|
||||
void rdybright(uint8_t bright);
|
||||
void readled(unsigned int state);
|
||||
void writeled(unsigned int state);
|
||||
void rdyled(unsigned int state);
|
||||
void led_clkout32(uint32_t val);
|
||||
void toggle_rdy_led(void);
|
||||
void toggle_read_led(void);
|
||||
void toggle_write_led(void);
|
||||
void led_panic(void);
|
||||
void led_pwm(void);
|
||||
void led_std(void);
|
||||
void led_init(void);
|
||||
|
||||
#endif
|
||||
75
src/bootldr/lpc1754.cfg
Normal file
75
src/bootldr/lpc1754.cfg
Normal file
@ -0,0 +1,75 @@
|
||||
# NXP LPC1754 Cortex-M3 with 128kB Flash and 16kB+16kB Local On-Chip SRAM,
|
||||
# reset_config trst_and_srst
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME lpc1754
|
||||
}
|
||||
|
||||
# After reset the chip is clocked by the ~4MHz internal RC oscillator.
|
||||
# When board-specific code (reset-init handler or device firmware)
|
||||
# configures another oscillator and/or PLL0, set CCLK to match; if
|
||||
# you don't, then flash erase and write operations may misbehave.
|
||||
# (The ROM code doing those updates cares about core clock speed...)
|
||||
#
|
||||
# CCLK is the core clock frequency in KHz
|
||||
if { [info exists CCLK ] } {
|
||||
set _CCLK $CCLK
|
||||
} else {
|
||||
set _CCLK 4000
|
||||
}
|
||||
if { [info exists CPUTAPID ] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
set _CPUTAPID 0x4ba00477
|
||||
}
|
||||
|
||||
#delays on reset lines
|
||||
adapter_nsrst_delay 200
|
||||
jtag_ntrst_delay 200
|
||||
|
||||
# LPC2000 & LPC1700 -> SRST causes TRST
|
||||
#reset_config srst_pulls_trst
|
||||
reset_config trst_and_srst srst_push_pull trst_push_pull
|
||||
|
||||
jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
|
||||
#jtag newtap x3s tap -irlen 6 -ircapture 0x11 -irmask 0x11 -expected-id 0x0141c093
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0
|
||||
|
||||
# LPC1754 has 16kB of SRAM In the ARMv7-M "Code" area (at 0x10000000)
|
||||
# and 16K more on AHB, in the ARMv7-M "SRAM" area, (at 0x2007c000).
|
||||
$_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size 0x4000
|
||||
$_TARGETNAME configure -work-area-phys 0x2007c000 -work-area-size 0x4000
|
||||
|
||||
# LPC1754 has 128kB of flash memory, managed by ROM code (including a
|
||||
# boot loader which verifies the flash exception table's checksum).
|
||||
# flash bank <name> lpc2000 <base> <size> 0 0 <target#> <variant> <clock> [calc checksum]
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \
|
||||
lpc1700 $_CCLK calc_checksum
|
||||
|
||||
# Run with *real slow* clock by default since the
|
||||
# boot rom could have been playing with the PLL, so
|
||||
# we have no idea what clock the target is running at.
|
||||
jtag_khz 1000
|
||||
|
||||
$_TARGETNAME configure -event reset-init {
|
||||
# Do not remap 0x0000-0x0020 to anything but the flash (i.e. select
|
||||
# "User Flash Mode" where interrupt vectors are _not_ remapped,
|
||||
# and reside in flash instead).
|
||||
#
|
||||
# See Table 612. Memory Mapping Control register (MEMMAP - 0x400F C040) bit description
|
||||
# Bit Symbol Value Description Reset
|
||||
# value
|
||||
# 0 MAP Memory map control. 0
|
||||
# 0 Boot mode. A portion of the Boot ROM is mapped to address 0.
|
||||
# 1 User mode. The on-chip Flash memory is mapped to address 0.
|
||||
# 31:1 - Reserved. The value read from a reserved bit is not defined. NA
|
||||
#
|
||||
# http://ics.nxp.com/support/documents/microcontrollers/?scope=LPC1768&type=user
|
||||
|
||||
mww 0x400FC040 0x01
|
||||
}
|
||||
131
src/bootldr/lpc1754boot.ld
Normal file
131
src/bootldr/lpc1754boot.ld
Normal file
@ -0,0 +1,131 @@
|
||||
/* Linker script for LPC1754
|
||||
*
|
||||
* Written 2010 by Ingo Korb
|
||||
*
|
||||
* Partially based on the linker scripts of avr-libc
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT(elf32-littlearm)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x05000
|
||||
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x03fe0 /* leave room for IAP */
|
||||
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.vectors))
|
||||
KEEP(*(.init))
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
|
||||
/* C++ con-/destructors */
|
||||
__ctors_start = . ;
|
||||
*(.ctors)
|
||||
__ctors_end = . ;
|
||||
__dtors_start = . ;
|
||||
*(.dtors)
|
||||
__dtors_end = . ;
|
||||
KEEP(SORT(*)(.ctors))
|
||||
KEEP(SORT(*)(.dtors))
|
||||
|
||||
KEEP(*(.fini))
|
||||
|
||||
__text_end = .;
|
||||
} > flash
|
||||
|
||||
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} >flash
|
||||
__exidx_end = .;
|
||||
|
||||
/* I hope this does what I think it does */
|
||||
.rodata : AT (ALIGN(__exidx_end,4))
|
||||
{
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
__rodata_end = .;
|
||||
} > flash
|
||||
|
||||
/* Data section */
|
||||
.data : AT (ALIGN(__rodata_end,4))
|
||||
{
|
||||
__data_start = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
__data_end = .;
|
||||
} > ram
|
||||
|
||||
/* Addresses of in-rom data section */
|
||||
__data_load_start = LOADADDR(.data);
|
||||
__data_load_end = __data_load_start + SIZEOF(.data);
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
/* BSS */
|
||||
.bss :
|
||||
{
|
||||
__bss_start__ = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
__bss_end__ = .;
|
||||
} > ram
|
||||
|
||||
/* second BSS in AHB ram */
|
||||
.ahbram (NOLOAD) :
|
||||
{
|
||||
__ahbram_start__ = .;
|
||||
*(.ahbram)
|
||||
*(.ahbram.*)
|
||||
__ahbram_end__ = .;
|
||||
} > ahbram
|
||||
|
||||
__heap_start = ALIGN(__bss_end__, 4);
|
||||
|
||||
/* Default stack starts at end of ram */
|
||||
PROVIDE(__stack = ORIGIN(ram) + LENGTH(ram)) ;
|
||||
|
||||
|
||||
/* Everyone seems to copy the stuff below straight from somewhere else, so I'll do that too */
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
}
|
||||
25
src/bootldr/lpc17xx_flash.h
Normal file
25
src/bootldr/lpc17xx_flash.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef LPC17XX_FLASH_H
|
||||
#define LPC17XX_FLASH_H
|
||||
|
||||
#include <arm/core_cm3.h>
|
||||
|
||||
/*------------- Flash Control (FMC) -------------*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t RESERVED0[8];
|
||||
__IO uint32_t FMSSTART;
|
||||
__IO uint32_t FMSSTOP;
|
||||
__I uint32_t FMSW0;
|
||||
__I uint32_t FMSW1;
|
||||
__I uint32_t FMSW2;
|
||||
__I uint32_t FMSW3;
|
||||
uint32_t RESERVED1[1002];
|
||||
__I uint32_t FMSTAT;
|
||||
uint32_t RESERVED2;
|
||||
__O uint32_t FMSTATCLR;
|
||||
} LPC_FMC_TypeDef;
|
||||
|
||||
#define LPC_FMC_BASE (LPC_APB1_BASE + 0x04000)
|
||||
#define LPC_FMC ((LPC_FMC_TypeDef*) LPC_FMC_BASE)
|
||||
|
||||
#endif
|
||||
78
src/bootldr/main.c
Normal file
78
src/bootldr/main.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "obj/autoconf.h"
|
||||
#include "clock.h"
|
||||
#include "uart.h"
|
||||
#include "bits.h"
|
||||
#include "power.h"
|
||||
#include "timer.h"
|
||||
#include "ff.h"
|
||||
#include "diskio.h"
|
||||
#include "led.h"
|
||||
#include "sdnative.h"
|
||||
#include "crc.h"
|
||||
#include "fileops.h"
|
||||
#include "iap.h"
|
||||
|
||||
#define EMC0TOGGLE (3<<4)
|
||||
#define MR0R (1<<1)
|
||||
|
||||
int i;
|
||||
|
||||
volatile enum diskstates disk_state;
|
||||
extern volatile tick_t ticks;
|
||||
|
||||
int (*chain)(void) = (void*)(FW_START+0x000001c5);
|
||||
|
||||
int main(void) {
|
||||
LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2);
|
||||
LPC_GPIO1->FIODIR = 0;
|
||||
LPC_GPIO0->FIODIR = BV(16);
|
||||
|
||||
/* connect UART3 on P0[25:26] + SSP0 on P0[15:18] + MAT3.0 on P0[10] */
|
||||
LPC_PINCON->PINSEL1 = BV(18) | BV(19) | BV(20) | BV(21) /* UART3 */
|
||||
| BV(3) | BV(5); /* SSP0 (FPGA) except SS */
|
||||
LPC_PINCON->PINSEL0 = BV(31); /* SSP0 */
|
||||
/* | BV(13) | BV(15) | BV(17) | BV(19) SSP1 (SD) */
|
||||
|
||||
/* pull-down CIC data lines */
|
||||
LPC_PINCON->PINMODE3 = BV(18) | BV(19) | BV(20) | BV(21);
|
||||
|
||||
clock_disconnect();
|
||||
power_init();
|
||||
timer_init();
|
||||
uart_init();
|
||||
led_init();
|
||||
/* do this last because the peripheral init()s change PCLK dividers */
|
||||
clock_init();
|
||||
LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
|
||||
led_pwm();
|
||||
sdn_init();
|
||||
printf("chksum=%08lx\n", *(uint32_t*)28);
|
||||
printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY);
|
||||
printf("PCONP=%lx\n", LPC_SC->PCONP);
|
||||
/* setup timer (fpga clk) */
|
||||
LPC_TIM3->CTCR=0;
|
||||
LPC_TIM3->EMR=EMC0TOGGLE;
|
||||
LPC_TIM3->MCR=MR0R;
|
||||
LPC_TIM3->MR0=1;
|
||||
LPC_TIM3->TCR=1;
|
||||
|
||||
test_iap();
|
||||
FLASH_RES res = flash_file((uint8_t*)"/sd2snes/firmware.img");
|
||||
printf("flash result = %d\n", res);
|
||||
if(res != ERR_OK) {
|
||||
if((res = check_flash()) != ERR_OK) {
|
||||
printf("check_flash() failed with error %d, not booting.\n", res);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
NVIC_DisableIRQ(RIT_IRQn);
|
||||
NVIC_DisableIRQ(UART_IRQ);
|
||||
|
||||
SCB->VTOR=FW_START+0x00000100;
|
||||
chain();
|
||||
while(1);
|
||||
}
|
||||
|
||||
12
src/bootldr/openocd-usb.cfg
Normal file
12
src/bootldr/openocd-usb.cfg
Normal file
@ -0,0 +1,12 @@
|
||||
#
|
||||
# Hubert Hoegl's USB to JTAG
|
||||
#
|
||||
# http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html
|
||||
#
|
||||
|
||||
interface ft2232
|
||||
ft2232_vid_pid 0x0403 0x6010
|
||||
ft2232_device_desc "Dual RS232"
|
||||
ft2232_layout "oocdlink"
|
||||
ft2232_latency 2
|
||||
adapter_khz 10
|
||||
26
src/bootldr/power.c
Normal file
26
src/bootldr/power.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* ___DISCLAIMER___ */
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "bits.h"
|
||||
#include "power.h"
|
||||
|
||||
/*
|
||||
required units:
|
||||
* SSP0 (FPGA interface) [enabled via spi_init]
|
||||
* UART3 (debug console) [enabled via uart_init]
|
||||
* TIM3 (FPGA clock)
|
||||
* RTC
|
||||
* GPIO
|
||||
* GPDMA [enabled via spi_init]
|
||||
* USB [enabled via usb_init]
|
||||
* PWM1
|
||||
*/
|
||||
void power_init() {
|
||||
LPC_SC->PCONP = BV(PCSSP0)
|
||||
| BV(PCTIM3)
|
||||
| BV(PCRTC)
|
||||
| BV(PCGPIO)
|
||||
| BV(PCPWM1)
|
||||
// | BV(PCUSB)
|
||||
;
|
||||
}
|
||||
43
src/bootldr/power.h
Normal file
43
src/bootldr/power.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* ___DISCLAIMER___ */
|
||||
|
||||
#ifndef _POWER_H
|
||||
#define _POWER_H
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
#define PCUART0 (3)
|
||||
#define PCUART1 (4)
|
||||
#define PCUART2 (24)
|
||||
#define PCUART3 (25)
|
||||
|
||||
#define PCTIM0 (1)
|
||||
#define PCTIM1 (2)
|
||||
#define PCTIM2 (22)
|
||||
#define PCTIM3 (23)
|
||||
#define PCRTC (9)
|
||||
#define PCRIT (16)
|
||||
|
||||
#define PCCAN1 (13)
|
||||
#define PCCAN2 (14)
|
||||
|
||||
#define PCPWM1 (6)
|
||||
#define PCMCPWM (17)
|
||||
|
||||
#define PCSSP0 (21)
|
||||
#define PCSSP1 (10)
|
||||
#define PCSPI (8)
|
||||
|
||||
#define PCI2C0 (7)
|
||||
#define PCI2C1 (19)
|
||||
#define PCI2C2 (26)
|
||||
|
||||
#define PCI2S (27)
|
||||
#define PCGPDMA (29)
|
||||
#define PCENET (30)
|
||||
#define PCUSB (31)
|
||||
#define PCQEI (18)
|
||||
#define PCGPIO (15)
|
||||
|
||||
void power_init(void);
|
||||
|
||||
#endif
|
||||
291
src/bootldr/printf.c
Normal file
291
src/bootldr/printf.c
Normal file
@ -0,0 +1,291 @@
|
||||
/* Small, noncompliant, not-full-featured printf implementation
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2010, Ingo Korb
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ingo Korb nor the
|
||||
* names of the contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* FIXME: Selection of output function should be more flexible
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "uart.h"
|
||||
|
||||
#define outfunc(x) uart_putc(x)
|
||||
|
||||
#define FLAG_ZEROPAD 1
|
||||
#define FLAG_LEFTADJ 2
|
||||
#define FLAG_BLANK 4
|
||||
#define FLAG_FORCESIGN 8
|
||||
#define FLAG_WIDTH 16
|
||||
#define FLAG_LONG 32
|
||||
#define FLAG_UNSIGNED 64
|
||||
#define FLAG_NEGATIVE 128
|
||||
|
||||
/* Digits used for conversion */
|
||||
static const char hexdigits[] = "0123456789abcdef";
|
||||
|
||||
/* Temporary buffer used for numbers - just large enough for 32 bit in octal */
|
||||
static char buffer[12];
|
||||
|
||||
/* Output string length */
|
||||
static unsigned int outlength;
|
||||
|
||||
/* Output pointer */
|
||||
static char *outptr;
|
||||
static int maxlen;
|
||||
|
||||
/* printf */
|
||||
static void outchar(char x) {
|
||||
if (maxlen) {
|
||||
maxlen--;
|
||||
outfunc(x);
|
||||
outlength++;
|
||||
}
|
||||
}
|
||||
|
||||
/* sprintf */
|
||||
static void outstr(char x) {
|
||||
if (maxlen) {
|
||||
maxlen--;
|
||||
*outptr++ = x;
|
||||
outlength++;
|
||||
}
|
||||
}
|
||||
|
||||
static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) {
|
||||
unsigned int width;
|
||||
unsigned int flags;
|
||||
unsigned int base = 0;
|
||||
char *ptr = NULL;
|
||||
|
||||
outlength = 0;
|
||||
|
||||
while (*fmt) {
|
||||
while (1) {
|
||||
if (*fmt == 0)
|
||||
goto end;
|
||||
|
||||
if (*fmt == '%') {
|
||||
fmt++;
|
||||
if (*fmt != '%')
|
||||
break;
|
||||
}
|
||||
|
||||
output_function(*fmt++);
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
width = 0;
|
||||
|
||||
/* read all flags */
|
||||
do {
|
||||
if (flags < FLAG_WIDTH) {
|
||||
switch (*fmt) {
|
||||
case '0':
|
||||
flags |= FLAG_ZEROPAD;
|
||||
continue;
|
||||
|
||||
case '-':
|
||||
flags |= FLAG_LEFTADJ;
|
||||
continue;
|
||||
|
||||
case ' ':
|
||||
flags |= FLAG_BLANK;
|
||||
continue;
|
||||
|
||||
case '+':
|
||||
flags |= FLAG_FORCESIGN;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags < FLAG_LONG) {
|
||||
if (*fmt >= '0' && *fmt <= '9') {
|
||||
unsigned char tmp = *fmt - '0';
|
||||
width = 10*width + tmp;
|
||||
flags |= FLAG_WIDTH;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*fmt == 'h')
|
||||
continue;
|
||||
|
||||
if (*fmt == 'l') {
|
||||
flags |= FLAG_LONG;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
} while (*fmt++);
|
||||
|
||||
/* Strings */
|
||||
if (*fmt == 'c' || *fmt == 's') {
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
buffer[0] = va_arg(ap, int);
|
||||
ptr = buffer;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
ptr = va_arg(ap, char *);
|
||||
break;
|
||||
}
|
||||
|
||||
goto output;
|
||||
}
|
||||
|
||||
/* Numbers */
|
||||
switch (*fmt) {
|
||||
case 'u':
|
||||
flags |= FLAG_UNSIGNED;
|
||||
case 'd':
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
base = 8;
|
||||
flags |= FLAG_UNSIGNED;
|
||||
break;
|
||||
|
||||
case 'p': // pointer
|
||||
output_function('0');
|
||||
output_function('x');
|
||||
width -= 2;
|
||||
case 'x':
|
||||
case 'X':
|
||||
base = 16;
|
||||
flags |= FLAG_UNSIGNED;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int num;
|
||||
|
||||
if (!(flags & FLAG_UNSIGNED)) {
|
||||
int tmp = va_arg(ap, int);
|
||||
if (tmp < 0) {
|
||||
num = -tmp;
|
||||
flags |= FLAG_NEGATIVE;
|
||||
} else
|
||||
num = tmp;
|
||||
} else {
|
||||
num = va_arg(ap, unsigned int);
|
||||
}
|
||||
|
||||
/* Convert number into buffer */
|
||||
ptr = buffer + sizeof(buffer);
|
||||
*--ptr = 0;
|
||||
do {
|
||||
*--ptr = hexdigits[num % base];
|
||||
num /= base;
|
||||
} while (num != 0);
|
||||
|
||||
/* Sign */
|
||||
if (flags & FLAG_NEGATIVE) {
|
||||
output_function('-');
|
||||
width--;
|
||||
} else if (flags & FLAG_FORCESIGN) {
|
||||
output_function('+');
|
||||
width--;
|
||||
} else if (flags & FLAG_BLANK) {
|
||||
output_function(' ');
|
||||
width--;
|
||||
}
|
||||
|
||||
output:
|
||||
/* left padding */
|
||||
if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) {
|
||||
while (strlen(ptr) < width) {
|
||||
if (flags & FLAG_ZEROPAD)
|
||||
output_function('0');
|
||||
else
|
||||
output_function(' ');
|
||||
width--;
|
||||
}
|
||||
}
|
||||
|
||||
/* data */
|
||||
while (*ptr) {
|
||||
output_function(*ptr++);
|
||||
if (width)
|
||||
width--;
|
||||
}
|
||||
|
||||
/* right padding */
|
||||
if (flags & FLAG_WIDTH) {
|
||||
while (width) {
|
||||
output_function(' ');
|
||||
width--;
|
||||
}
|
||||
}
|
||||
|
||||
fmt++;
|
||||
}
|
||||
|
||||
end:
|
||||
return outlength;
|
||||
}
|
||||
|
||||
int printf(const char *format, ...) {
|
||||
va_list ap;
|
||||
int res;
|
||||
|
||||
maxlen = -1;
|
||||
va_start(ap, format);
|
||||
res = internal_nprintf(outchar, format, ap);
|
||||
va_end(ap);
|
||||
return res;
|
||||
}
|
||||
|
||||
int snprintf(char *str, size_t size, const char *format, ...) {
|
||||
va_list ap;
|
||||
int res;
|
||||
|
||||
maxlen = size;
|
||||
outptr = str;
|
||||
va_start(ap, format);
|
||||
res = internal_nprintf(outstr, format, ap);
|
||||
va_end(ap);
|
||||
if (res < size)
|
||||
str[res] = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Required for gcc compatibility */
|
||||
int puts(const char *str) {
|
||||
uart_puts(str);
|
||||
uart_putc('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef putchar
|
||||
int putchar(int c) {
|
||||
uart_putc(c);
|
||||
return 0;
|
||||
}
|
||||
901
src/bootldr/sdnative.c
Normal file
901
src/bootldr/sdnative.c
Normal file
@ -0,0 +1,901 @@
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "crc.h"
|
||||
#include "diskio.h"
|
||||
#include "timer.h"
|
||||
#include "uart.h"
|
||||
#include "led.h"
|
||||
#include "sdnative.h"
|
||||
#include "bits.h"
|
||||
|
||||
#define MAX_CARDS 1
|
||||
|
||||
// SD/MMC commands
|
||||
#define GO_IDLE_STATE 0
|
||||
#define SEND_OP_COND 1
|
||||
#define ALL_SEND_CID 2
|
||||
#define SEND_RELATIVE_ADDR 3
|
||||
#define SWITCH_FUNC 6
|
||||
#define SELECT_CARD 7
|
||||
#define SEND_IF_COND 8
|
||||
#define SEND_CSD 9
|
||||
#define SEND_CID 10
|
||||
#define STOP_TRANSMISSION 12
|
||||
#define SEND_STATUS 13
|
||||
#define SET_BLOCKLEN 16
|
||||
#define READ_SINGLE_BLOCK 17
|
||||
#define READ_MULTIPLE_BLOCK 18
|
||||
#define WRITE_BLOCK 24
|
||||
#define WRITE_MULTIPLE_BLOCK 25
|
||||
#define PROGRAM_CSD 27
|
||||
#define SET_WRITE_PROT 28
|
||||
#define CLR_WRITE_PROT 29
|
||||
#define SEND_WRITE_PROT 30
|
||||
#define ERASE_WR_BLK_STAR_ADDR 32
|
||||
#define ERASE_WR_BLK_END_ADDR 33
|
||||
#define ERASE 38
|
||||
#define LOCK_UNLOCK 42
|
||||
#define APP_CMD 55
|
||||
#define GEN_CMD 56
|
||||
#define READ_OCR 58
|
||||
#define CRC_ON_OFF 59
|
||||
|
||||
// SD ACMDs
|
||||
#define SD_SET_BUS_WIDTH 6
|
||||
#define SD_STATUS 13
|
||||
#define SD_SEND_NUM_WR_BLOCKS 22
|
||||
#define SD_SET_WR_BLK_ERASE_COUNT 23
|
||||
#define SD_SEND_OP_COND 41
|
||||
#define SD_SET_CLR_CARD_DETECT 42
|
||||
#define SD_SEND_SCR 51
|
||||
|
||||
// R1 status bits
|
||||
#define STATUS_IN_IDLE 1
|
||||
#define STATUS_ERASE_RESET 2
|
||||
#define STATUS_ILLEGAL_COMMAND 4
|
||||
#define STATUS_CRC_ERROR 8
|
||||
#define STATUS_ERASE_SEQ_ERROR 16
|
||||
#define STATUS_ADDRESS_ERROR 32
|
||||
#define STATUS_PARAMETER_ERROR 64
|
||||
|
||||
|
||||
/* Card types - cardtype == 0 is MMC */
|
||||
#define CARD_SD (1<<0)
|
||||
#define CARD_SDHC (1<<1)
|
||||
|
||||
/*
|
||||
1 DAT3/SS P0.6
|
||||
2 CMD/DI P0.9
|
||||
5 Clock P0.7
|
||||
7 DAT0/DO P0.8
|
||||
8 DAT1/IRQ P1.14
|
||||
9 DAT2/NC P1.15
|
||||
*/
|
||||
|
||||
/* SD init procedure
|
||||
=================
|
||||
- initial clock frequency: ~100kHz
|
||||
- cycle the clock for at least 74 cycles (some more may be safer)
|
||||
- send CMD0
|
||||
- send CMD8 (SEND_OP_COND); if no response -> HCS=0; else HCS=1
|
||||
- send ACMD41 until OCR[31] (busy) becomes 1 (means: ready)
|
||||
- if OCR[30] (CCS) set -> SDHC; else SDSC
|
||||
- send CMD2 (read CID) (maybe log some stuff from the CID)
|
||||
- send CMD3 (read RCA), store RCA
|
||||
== end of initialisation ==
|
||||
- send CMD9 (read CSD) with RCA, maybe do sth with TRAN_SPEED
|
||||
- send CMD7 with RCA, select card, put card in tran
|
||||
- maybe send CMD13 with RCA to check state (tran)
|
||||
- send ACMD51 with RCA to read SCR (maybe, to check 4bit support)
|
||||
- increase clock speed
|
||||
- send ACMD6 with RCA to set 4bit bus width
|
||||
- send transfer cmds
|
||||
*/
|
||||
|
||||
/*
|
||||
static CMD payloads. (no CRC calc required)
|
||||
- CMD0: 0x40 0x00 0x00 0x00 0x00 0x95
|
||||
- CMD8: 0x48 0x00 0x00 0x01 0xaa 0x87
|
||||
- CMD2: 0x42 0x00 0x00 0x00 0x00 0x4d
|
||||
- CMD3: 0x43 0x00 0x00 0x00 0x00 0x21
|
||||
- CMD55: 0x77 0x00 0x00 0x00 0x00 0x65
|
||||
*/
|
||||
|
||||
uint8_t cmd[6]={0,0,0,0,0,0};
|
||||
uint8_t rsp[17];
|
||||
uint8_t csd[17];
|
||||
uint8_t ccs=0;
|
||||
uint32_t rca;
|
||||
|
||||
enum trans_state { TRANS_NONE = 0, TRANS_READ, TRANS_WRITE };
|
||||
enum cmd_state { CMD_RSP = 0, CMD_RSPDAT, CMD_DAT };
|
||||
|
||||
int during_blocktrans = TRANS_NONE;
|
||||
uint32_t last_block = 0;
|
||||
|
||||
volatile int sd_changed;
|
||||
|
||||
/**
|
||||
* getbits - read value from bit buffer
|
||||
* @buffer: pointer to the data buffer
|
||||
* @start : index of the first bit in the value
|
||||
* @bits : number of bits in the value
|
||||
*
|
||||
* This function returns a value from the memory region passed as
|
||||
* buffer, starting with bit "start" and "bits" bit long. The buffer
|
||||
* is assumed to be MSB first, passing 0 for start will read starting
|
||||
* from the highest-value bit of the first byte of the buffer.
|
||||
*/
|
||||
static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) {
|
||||
uint8_t *buf = buffer;
|
||||
uint32_t result = 0;
|
||||
|
||||
if ((start % 8) != 0) {
|
||||
/* Unaligned start */
|
||||
result += buf[start / 8] & (0xff >> (start % 8));
|
||||
bits -= 8 - (start % 8);
|
||||
start += 8 - (start % 8);
|
||||
}
|
||||
while (bits >= 8) {
|
||||
result = (result << 8) + buf[start / 8];
|
||||
start += 8;
|
||||
bits -= 8;
|
||||
}
|
||||
if (bits > 0) {
|
||||
result = result << bits;
|
||||
result = result + (buf[start / 8] >> (8-bits));
|
||||
} else if (bits < 0) {
|
||||
/* Fraction of a single byte */
|
||||
result = result >> -bits;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void wiggle_slow_pos(uint16_t times) {
|
||||
while(times--) {
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_slow_neg(uint16_t times) {
|
||||
while(times--) {
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
delay_us(2);
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_fast_pos(uint16_t times) {
|
||||
while(times--) {
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_fast_neg(uint16_t times) {
|
||||
while(times--) {
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wiggle_fast_neg1(void) {
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
}
|
||||
|
||||
static inline void wiggle_fast_pos1(void) {
|
||||
BITBAND(SD_CLKREG->FIOSET, SD_CLKPIN) = 1;
|
||||
BITBAND(SD_CLKREG->FIOCLR, SD_CLKPIN) = 1;
|
||||
}
|
||||
|
||||
static inline void wait_busy(void) {
|
||||
while(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
wiggle_fast_neg(4);
|
||||
}
|
||||
|
||||
/*
|
||||
send_command_slow
|
||||
send SD command and put response in rsp.
|
||||
returns length of response or 0 if there was no response
|
||||
*/
|
||||
int send_command_slow(uint8_t* cmd, uint8_t* rsp){
|
||||
uint8_t shift, i=6;
|
||||
int rsplen;
|
||||
uint8_t cmdno = *cmd & 0x3f;
|
||||
wiggle_slow_pos(5);
|
||||
switch(*cmd & 0x3f) {
|
||||
case 0:
|
||||
rsplen = 0;
|
||||
break;
|
||||
case 2:
|
||||
case 9:
|
||||
case 10:
|
||||
rsplen = 17;
|
||||
break;
|
||||
default:
|
||||
rsplen = 6;
|
||||
}
|
||||
/* send command */
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
|
||||
|
||||
while(i--) {
|
||||
shift = 8;
|
||||
do {
|
||||
shift--;
|
||||
uint8_t data = *cmd;
|
||||
*cmd<<=1;
|
||||
if(data&0x80) {
|
||||
BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
|
||||
}
|
||||
wiggle_slow_pos(1);
|
||||
} while (shift);
|
||||
cmd++;
|
||||
}
|
||||
|
||||
wiggle_slow_pos(1);
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
|
||||
|
||||
if(rsplen) {
|
||||
uint16_t timeout=1000;
|
||||
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
|
||||
wiggle_slow_neg(1);
|
||||
}
|
||||
if(!timeout) {
|
||||
printf("CMD%d timed out\n", cmdno);
|
||||
return 0; /* no response within timeout */
|
||||
}
|
||||
|
||||
i=rsplen;
|
||||
while(i--) {
|
||||
shift = 8;
|
||||
uint8_t data=0;
|
||||
do {
|
||||
shift--;
|
||||
data |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << shift;
|
||||
wiggle_slow_neg(1);
|
||||
} while (shift);
|
||||
*rsp=data;
|
||||
rsp++;
|
||||
}
|
||||
}
|
||||
return rsplen;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
send_command_fast
|
||||
send SD command and put response in rsp.
|
||||
returns length of response or 0 if there was no response
|
||||
*/
|
||||
int send_command_fast(uint8_t* cmd, uint8_t* rsp, uint8_t* buf){
|
||||
uint8_t datshift=8, cmdshift, i=6;
|
||||
uint8_t cmdno = *cmd & 0x3f;
|
||||
int rsplen, dat=0, waitbusy=0, datcnt=512, j=0;
|
||||
static int state=CMD_RSP;
|
||||
wiggle_fast_pos(9); /* give the card >=8 cycles after last command */
|
||||
DBG_SD printf("send_command_fast: sending CMD%d; payload=%02x%02x%02x%02x%02x%02x...\n", cmdno, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
|
||||
switch(*cmd & 0x3f) {
|
||||
case 0:
|
||||
rsplen = 0;
|
||||
break;
|
||||
case 2:
|
||||
case 9:
|
||||
case 10:
|
||||
rsplen = 17;
|
||||
break;
|
||||
case 12:
|
||||
rsplen = 6;
|
||||
waitbusy = 1;
|
||||
break;
|
||||
case 13:
|
||||
case 17:
|
||||
case 18:
|
||||
dat = 1;
|
||||
default:
|
||||
rsplen = 6;
|
||||
}
|
||||
if(dat && (buf==NULL)) {
|
||||
printf("send_command_fast error: buf is null but data transfer expected.\n");
|
||||
return 0;
|
||||
}
|
||||
/* send command */
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
|
||||
|
||||
while(i--) {
|
||||
uint8_t data = *cmd;
|
||||
cmdshift = 8;
|
||||
do {
|
||||
cmdshift--;
|
||||
if(data&0x80) {
|
||||
BITBAND(SD_CMDREG->FIOSET, SD_CMDPIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_CMDREG->FIOCLR, SD_CMDPIN) = 1;
|
||||
}
|
||||
data<<=1;
|
||||
wiggle_fast_pos1();
|
||||
} while (cmdshift);
|
||||
cmd++;
|
||||
}
|
||||
|
||||
wiggle_fast_pos1();
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 0;
|
||||
|
||||
if(rsplen) {
|
||||
uint32_t timeout=2000000;
|
||||
/* wait for response */
|
||||
while((BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) && --timeout) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
if(!timeout) {
|
||||
printf("CMD%d timed out\n", cmdno);
|
||||
return 0; /* no response within timeout */
|
||||
}
|
||||
|
||||
i=rsplen;
|
||||
uint8_t cmddata=0, datdata=0;
|
||||
while(i--) { /* process response */
|
||||
cmdshift = 8;
|
||||
do {
|
||||
if(dat) {
|
||||
if(!(BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN))) {
|
||||
printf("data start during response\n");
|
||||
j=datcnt;
|
||||
state=CMD_RSPDAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmdshift--;
|
||||
cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift;
|
||||
wiggle_fast_neg1();
|
||||
} while (cmdshift);
|
||||
if(state==CMD_RSPDAT)break;
|
||||
*rsp=cmddata;
|
||||
cmddata=0;
|
||||
rsp++;
|
||||
}
|
||||
|
||||
if(state==CMD_RSPDAT) { /* process response+data */
|
||||
int startbit=1;
|
||||
DBG_SD printf("processing rsp+data cmdshift=%d i=%d j=%d\n", cmdshift, i, j);
|
||||
datshift=8;
|
||||
while(1) {
|
||||
cmdshift--;
|
||||
cmddata |= (BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN)) << cmdshift;
|
||||
if(!cmdshift) {
|
||||
cmdshift=8;
|
||||
*rsp=cmddata;
|
||||
cmddata=0;
|
||||
rsp++;
|
||||
i--;
|
||||
if(!i) {
|
||||
DBG_SD printf("response end\n");
|
||||
if(j) state=CMD_DAT; /* response over, remaining data */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!startbit) {
|
||||
datshift-=4;
|
||||
datdata |= SD_DAT << datshift;
|
||||
if(!datshift) {
|
||||
datshift=8;
|
||||
*buf=datdata;
|
||||
datdata=0;
|
||||
buf++;
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
}
|
||||
startbit=0;
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
}
|
||||
|
||||
if(dat && state != CMD_DAT) { /* response ended before data */
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
|
||||
state=CMD_DAT;
|
||||
j=datcnt;
|
||||
datshift=8;
|
||||
DBG_SD printf("response over, waiting for data...\n");
|
||||
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
wiggle_fast_neg1(); /* eat the start bit */
|
||||
}
|
||||
|
||||
if(state==CMD_DAT) { /* transfer rest of data */
|
||||
DBG_SD printf("remaining data: %d\n", j);
|
||||
if(datshift==8) {
|
||||
while(1) {
|
||||
datdata |= SD_DAT << 4;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
datdata |= SD_DAT;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
*buf=datdata;
|
||||
datdata=0;
|
||||
buf++;
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
} else {
|
||||
|
||||
while(1) {
|
||||
datshift-=4;
|
||||
datdata |= SD_DAT << datshift;
|
||||
if(!datshift) {
|
||||
datshift=8;
|
||||
*buf=datdata;
|
||||
datdata=0;
|
||||
buf++;
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* just eat the crcs for now */
|
||||
if(dat) wiggle_fast_neg(17);
|
||||
|
||||
if(waitbusy) {
|
||||
DBG_SD printf("waitbusy after send_cmd\n");
|
||||
wait_busy();
|
||||
}
|
||||
state=CMD_RSP;
|
||||
}
|
||||
rsp-=rsplen;
|
||||
DBG_SD printf("send_command_fast: CMD%d response: %02x%02x%02x%02x%02x%02x\n", cmdno, rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]);
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
|
||||
return rsplen;
|
||||
}
|
||||
|
||||
|
||||
static inline void make_crc7(uint8_t* cmd) {
|
||||
cmd[5]=crc7update(0, cmd[0]);
|
||||
cmd[5]=crc7update(cmd[5], cmd[1]);
|
||||
cmd[5]=crc7update(cmd[5], cmd[2]);
|
||||
cmd[5]=crc7update(cmd[5], cmd[3]);
|
||||
cmd[5]=crc7update(cmd[5], cmd[4]);
|
||||
cmd[5]=(cmd[5] << 1) | 1;
|
||||
}
|
||||
|
||||
int cmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
uint8_t cmdbuf[6];
|
||||
cmdbuf[0] = 0x40 | cmd;
|
||||
cmdbuf[1] = param >> 24;
|
||||
cmdbuf[2] = param >> 16;
|
||||
cmdbuf[3] = param >> 8;
|
||||
cmdbuf[4] = param;
|
||||
if(!crc) {
|
||||
make_crc7(cmdbuf);
|
||||
} else {
|
||||
cmdbuf[5] = crc;
|
||||
}
|
||||
return send_command_slow(cmdbuf, rsp);
|
||||
}
|
||||
|
||||
int acmd_slow(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
if(!(cmd_slow(APP_CMD, rca, 0, NULL, rsp))) {
|
||||
return 0;
|
||||
}
|
||||
return cmd_slow(cmd, param, crc, dat, rsp);
|
||||
}
|
||||
|
||||
int cmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
uint8_t cmdbuf[6];
|
||||
cmdbuf[0] = 0x40 | cmd;
|
||||
cmdbuf[1] = param >> 24;
|
||||
cmdbuf[2] = param >> 16;
|
||||
cmdbuf[3] = param >> 8;
|
||||
cmdbuf[4] = param;
|
||||
if(!crc) {
|
||||
make_crc7(cmdbuf);
|
||||
} else {
|
||||
cmdbuf[5] = crc;
|
||||
}
|
||||
return send_command_fast(cmdbuf, rsp, dat);
|
||||
}
|
||||
|
||||
int acmd_fast(uint8_t cmd, uint32_t param, uint8_t crc, uint8_t* dat, uint8_t* rsp) {
|
||||
if(!(cmd_fast(APP_CMD, rca, 0, NULL, rsp))) {
|
||||
return 0;
|
||||
}
|
||||
return cmd_fast(cmd, param, crc, dat, rsp);
|
||||
}
|
||||
|
||||
void stream_datablock(uint8_t *buf) {
|
||||
// uint8_t datshift=8;
|
||||
int j=512;
|
||||
uint8_t datdata=0;
|
||||
uint32_t timeout=1000000;
|
||||
|
||||
while((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) && --timeout) {
|
||||
wiggle_fast_neg1();
|
||||
}
|
||||
wiggle_fast_neg1(); /* eat the start bit */
|
||||
while(1) {
|
||||
datdata = SD_DAT << 4;
|
||||
wiggle_fast_neg1();
|
||||
datdata |= SD_DAT;
|
||||
wiggle_fast_neg1();
|
||||
|
||||
*buf=datdata;
|
||||
buf++;
|
||||
j--;
|
||||
if(!j) break;
|
||||
}
|
||||
/* eat the crc for now */
|
||||
wiggle_fast_neg(17);
|
||||
}
|
||||
|
||||
void send_datablock(uint8_t *buf) {
|
||||
uint16_t crc0=0, crc1=0, crc2=0, crc3=0, cnt=512;
|
||||
uint8_t dat0=0, dat1=0, dat2=0, dat3=0, crcshift, datshift;
|
||||
|
||||
wiggle_fast_pos1();
|
||||
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 1;
|
||||
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 1;
|
||||
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 1;
|
||||
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 1;
|
||||
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
|
||||
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
|
||||
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
|
||||
wiggle_fast_pos1(); /* send start bit to card */
|
||||
crcshift=8;
|
||||
while(cnt--) {
|
||||
datshift=8;
|
||||
do {
|
||||
datshift-=4;
|
||||
if(((*buf)>>datshift) & 0x8) {
|
||||
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
}
|
||||
if(((*buf)>>datshift) & 0x4) {
|
||||
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
|
||||
}
|
||||
if(((*buf)>>datshift) & 0x2){
|
||||
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
|
||||
}
|
||||
if(((*buf)>>datshift) & 0x1){
|
||||
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
}
|
||||
wiggle_fast_pos1();
|
||||
} while (datshift);
|
||||
|
||||
crcshift-=2;
|
||||
dat0 |= (((*buf)&0x01) | (((*buf)&0x10) >> 3)) << crcshift;
|
||||
dat1 |= ((((*buf)&0x02) >> 1) | (((*buf)&0x20) >> 4)) << crcshift;
|
||||
dat2 |= ((((*buf)&0x04) >> 2) | (((*buf)&0x40) >> 5)) << crcshift;
|
||||
dat3 |= ((((*buf)&0x08) >> 3) | (((*buf)&0x80) >> 6)) << crcshift;
|
||||
if(!crcshift) {
|
||||
crc0 = crc_xmodem_update(crc0, dat0);
|
||||
crc1 = crc_xmodem_update(crc1, dat1);
|
||||
crc2 = crc_xmodem_update(crc2, dat2);
|
||||
crc3 = crc_xmodem_update(crc3, dat3);
|
||||
crcshift=8;
|
||||
dat0=0;
|
||||
dat1=0;
|
||||
dat2=0;
|
||||
dat3=0;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
// printf("crc0=%04x crc1=%04x crc2=%04x crc3=%04x ", crc0, crc1, crc2, crc3);
|
||||
/* send crcs */
|
||||
datshift=16;
|
||||
do {
|
||||
datshift--;
|
||||
if((crc0 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT0REG->FIOCLR, SD_DAT0PIN) = 1;
|
||||
}
|
||||
if((crc1 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT1REG->FIOCLR, SD_DAT1PIN) = 1;
|
||||
}
|
||||
if((crc2 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT2REG->FIOCLR, SD_DAT2PIN) = 1;
|
||||
}
|
||||
if((crc3 >> datshift) & 1) {
|
||||
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
} else {
|
||||
BITBAND(SD_DAT3REG->FIOCLR, SD_DAT3PIN) = 1;
|
||||
}
|
||||
wiggle_fast_pos1();
|
||||
} while(datshift);
|
||||
/* send end bit */
|
||||
BITBAND(SD_DAT0REG->FIOSET, SD_DAT0PIN) = 1;
|
||||
BITBAND(SD_DAT1REG->FIOSET, SD_DAT1PIN) = 1;
|
||||
BITBAND(SD_DAT2REG->FIOSET, SD_DAT2PIN) = 1;
|
||||
BITBAND(SD_DAT3REG->FIOSET, SD_DAT3PIN) = 1;
|
||||
|
||||
wiggle_fast_pos1();
|
||||
|
||||
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0;
|
||||
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0;
|
||||
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0;
|
||||
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0;
|
||||
|
||||
wiggle_fast_neg(3);
|
||||
dat0=0;
|
||||
|
||||
datshift=4;
|
||||
do {
|
||||
datshift--;
|
||||
dat0 |= ((BITBAND(SD_DAT0REG->FIOPIN, SD_DAT0PIN)) << datshift);
|
||||
wiggle_fast_neg1();
|
||||
} while (datshift);
|
||||
DBG_SD printf("crc %02x\n", dat0);
|
||||
if((dat0 & 7) != 2) {
|
||||
printf("crc error! %02x\n", dat0);
|
||||
while(1);
|
||||
}
|
||||
if(dat0 & 8) {
|
||||
printf("missing start bit in CRC status response...\n");
|
||||
}
|
||||
wiggle_fast_neg(2);
|
||||
wait_busy();
|
||||
}
|
||||
|
||||
void read_block(uint32_t address, uint8_t *buf) {
|
||||
if(during_blocktrans == TRANS_READ && (last_block == address-1)) {
|
||||
//uart_putc('r');
|
||||
stream_datablock(buf);
|
||||
last_block=address;
|
||||
} else {
|
||||
if(during_blocktrans) {
|
||||
// uart_putc('_');
|
||||
//printf("nonseq read (%lx -> %lx), restarting transmission\n", last_block, address);
|
||||
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
|
||||
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
|
||||
}
|
||||
last_block=address;
|
||||
if(!ccs) {
|
||||
address <<= 9;
|
||||
}
|
||||
cmd_fast(READ_MULTIPLE_BLOCK, address, 0, buf, rsp);
|
||||
during_blocktrans = TRANS_READ;
|
||||
}
|
||||
}
|
||||
|
||||
void write_block(uint32_t address, uint8_t* buf) {
|
||||
if(during_blocktrans == TRANS_WRITE && (last_block == address-1)) {
|
||||
wait_busy();
|
||||
send_datablock(buf);
|
||||
last_block=address;
|
||||
} else {
|
||||
if(during_blocktrans) {
|
||||
/* send STOP_TRANSMISSION to end an open READ/WRITE_MULTIPLE_BLOCK */
|
||||
cmd_fast(STOP_TRANSMISSION, 0, 0x61, NULL, rsp);
|
||||
}
|
||||
wait_busy();
|
||||
last_block=address;
|
||||
if(!ccs) {
|
||||
address <<= 9;
|
||||
}
|
||||
/* only send cmd & get response */
|
||||
cmd_fast(WRITE_MULTIPLE_BLOCK, address, 0, NULL, rsp);
|
||||
DBG_SD printf("write_block: CMD25 response = %02x%02x%02x%02x%02x%02x\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5]);
|
||||
wiggle_fast_pos(8);
|
||||
send_datablock(buf);
|
||||
during_blocktrans = TRANS_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Public functions
|
||||
//
|
||||
|
||||
DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
|
||||
uint8_t sec;
|
||||
if(drv >= MAX_CARDS) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
readled(1);
|
||||
for(sec=0; sec<count; sec++) {
|
||||
read_block(sector+sec, buffer);
|
||||
buffer+=512;
|
||||
}
|
||||
readled(0);
|
||||
return RES_OK;
|
||||
}
|
||||
DRESULT disk_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_read")));
|
||||
|
||||
DRESULT sdn_initialize(BYTE drv) {
|
||||
|
||||
uint8_t rsp[17]; /* space for response */
|
||||
int rsplen;
|
||||
uint8_t hcs=0;
|
||||
rca = 0;
|
||||
if(drv>=MAX_CARDS) {
|
||||
return STA_NOINIT|STA_NODISK;
|
||||
}
|
||||
|
||||
if(sdn_status(drv) & STA_NODISK) {
|
||||
return STA_NOINIT|STA_NODISK;
|
||||
}
|
||||
/* if the card is sending data from before a reset we try to deselect it
|
||||
prior to initialization */
|
||||
for(rsplen=0; rsplen<2042; rsplen++) {
|
||||
if(!(BITBAND(SD_DAT3REG->FIOPIN, SD_DAT3PIN))) {
|
||||
printf("card seems to be sending data, attempting deselect\n");
|
||||
cmd_slow(SELECT_CARD, 0, 0, NULL, rsp);
|
||||
}
|
||||
wiggle_slow_neg(1);
|
||||
}
|
||||
printf("sd_init start\n");
|
||||
cmd_slow(GO_IDLE_STATE, 0, 0x95, NULL, rsp);
|
||||
|
||||
if((rsplen=cmd_slow(SEND_IF_COND, 0x000001aa, 0x87, NULL, rsp))) {
|
||||
DBG_SD printf("CMD8 response:\n");
|
||||
DBG_SD uart_trace(rsp, 0, rsplen);
|
||||
hcs=1;
|
||||
}
|
||||
while(1) {
|
||||
if(!(acmd_slow(SD_SEND_OP_COND, (hcs << 30) | 0xfc0000, 0, NULL, rsp))) {
|
||||
printf("ACMD41 no response!\n");
|
||||
}
|
||||
if(rsp[1]&0x80) break;
|
||||
}
|
||||
|
||||
ccs = (rsp[1]>>6) & 1; /* SDHC/XC */
|
||||
|
||||
cmd_slow(ALL_SEND_CID, 0, 0x4d, NULL, rsp);
|
||||
if(cmd_slow(SEND_RELATIVE_ADDR, 0, 0x21, NULL, rsp)) {
|
||||
rca=(rsp[1]<<24) | (rsp[2]<<16);
|
||||
printf("RCA: %04lx\n", rca>>16);
|
||||
} else {
|
||||
printf("CMD3 no response!\n");
|
||||
rca=0;
|
||||
}
|
||||
|
||||
/* record CSD for getinfo */
|
||||
cmd_slow(SEND_CSD, rca, 0, NULL, rsp);
|
||||
|
||||
/* select the card */
|
||||
if(cmd_slow(SELECT_CARD, rca, 0, NULL, rsp)) {
|
||||
printf("card selected!\n");
|
||||
} else {
|
||||
printf("CMD7 no response!\n");
|
||||
}
|
||||
|
||||
/* get card status */
|
||||
cmd_slow(SEND_STATUS, rca, 0, NULL, rsp);
|
||||
|
||||
/* set bus width */
|
||||
acmd_slow(SD_SET_BUS_WIDTH, 0x2, 0, NULL, rsp);
|
||||
|
||||
/* set block length */
|
||||
cmd_slow(SET_BLOCKLEN, 0x200, 0, NULL, rsp);
|
||||
|
||||
printf("SD init complete. SDHC/XC=%d\n", ccs);
|
||||
disk_state = DISK_OK;
|
||||
during_blocktrans = TRANS_NONE;
|
||||
return sdn_status(drv);
|
||||
}
|
||||
|
||||
DSTATUS disk_initialize(BYTE drv) __attribute__ ((weak, alias("sdn_initialize")));
|
||||
|
||||
void sdn_init(void) {
|
||||
/* enable GPIO interrupt on SD detect pin, both edges */
|
||||
/* NVIC_EnableIRQ(EINT3_IRQn);
|
||||
SD_DT_INT_SETUP(); */
|
||||
/* disconnect SSP1 */
|
||||
LPC_PINCON->PINSEL0 &= ~(BV(13) | BV(15) | BV(17) | BV(19));
|
||||
/* prepare GPIOs */
|
||||
BITBAND(SD_DAT3REG->FIODIR, SD_DAT3PIN) = 0;
|
||||
BITBAND(SD_DAT2REG->FIODIR, SD_DAT2PIN) = 0;
|
||||
BITBAND(SD_DAT1REG->FIODIR, SD_DAT1PIN) = 0;
|
||||
BITBAND(SD_DAT0REG->FIODIR, SD_DAT0PIN) = 0;
|
||||
BITBAND(SD_CLKREG->FIODIR, SD_CLKPIN) = 1;
|
||||
BITBAND(SD_CMDREG->FIODIR, SD_CMDPIN) = 1;
|
||||
BITBAND(SD_CMDREG->FIOPIN, SD_CMDPIN) = 1;
|
||||
}
|
||||
void disk_init(void) __attribute__ ((weak, alias("sdn_init")));
|
||||
|
||||
|
||||
DSTATUS sdn_status(BYTE drv) {
|
||||
if (SDCARD_DETECT) {
|
||||
if (SDCARD_WP) {
|
||||
return STA_PROTECT;
|
||||
} else {
|
||||
return RES_OK;
|
||||
}
|
||||
} else {
|
||||
return STA_NOINIT|STA_NODISK;
|
||||
}
|
||||
}
|
||||
DSTATUS disk_status(BYTE drv) __attribute__ ((weak, alias("sdn_status")));
|
||||
|
||||
DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer) {
|
||||
uint32_t capacity;
|
||||
|
||||
if (drv >= MAX_CARDS) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
if (sdn_status(drv) & STA_NODISK) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
if (page != 0) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
if (ccs) {
|
||||
/* Special CSD for SDHC cards */
|
||||
capacity = (1 + getbits(csd,127-69+8,22)) * 1024;
|
||||
} else {
|
||||
/* Assume that MMC-CSD 1.0/1.1/1.2 and SD-CSD 1.1 are the same... */
|
||||
uint8_t exponent = 2 + getbits(csd, 127-49+8, 3);
|
||||
capacity = 1 + getbits(csd, 127-73+8, 12);
|
||||
exponent += getbits(csd, 127-83+8,4) - 9;
|
||||
while (exponent--) capacity *= 2;
|
||||
}
|
||||
|
||||
diskinfo0_t *di = buffer;
|
||||
di->validbytes = sizeof(diskinfo0_t);
|
||||
di->disktype = DISK_TYPE_SD;
|
||||
di->sectorsize = 2;
|
||||
di->sectorcount = capacity;
|
||||
|
||||
printf("card capacity: %lu sectors\n", capacity);
|
||||
return RES_OK;
|
||||
}
|
||||
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sdn_getinfo")));
|
||||
|
||||
DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
|
||||
uint8_t sec;
|
||||
uint8_t *buf = (uint8_t*)buffer;
|
||||
if(drv >= MAX_CARDS) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
if (sdn_status(drv) & STA_NODISK) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
writeled(1);
|
||||
for(sec=0; sec<count; sec++) {
|
||||
write_block(sector+sec, buf);
|
||||
buf+=512;
|
||||
}
|
||||
writeled(0);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sdn_write")));
|
||||
|
||||
/* Detect changes of SD card 0 */
|
||||
void sdn_changed() {
|
||||
if (sd_changed) {
|
||||
printf("ch ");
|
||||
if(SDCARD_DETECT) {
|
||||
disk_state = DISK_CHANGED;
|
||||
} else {
|
||||
disk_state = DISK_REMOVED;
|
||||
}
|
||||
sd_changed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
25
src/bootldr/sdnative.h
Normal file
25
src/bootldr/sdnative.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* DISCLAIMER */
|
||||
|
||||
#ifndef SDNATIVE_H
|
||||
#define SDNATIVE_H
|
||||
|
||||
#ifdef DEBUG_SD
|
||||
#define DBG_SD
|
||||
#else
|
||||
#define DBG_SD while(0)
|
||||
#endif
|
||||
|
||||
#include "diskio.h"
|
||||
|
||||
/* These functions are weak-aliased to disk_... */
|
||||
void sdn_init(void);
|
||||
DSTATUS sdn_status(BYTE drv);
|
||||
DSTATUS sdn_initialize(BYTE drv);
|
||||
DRESULT sdn_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count);
|
||||
DRESULT sdn_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count);
|
||||
DRESULT sdn_getinfo(BYTE drv, BYTE page, void *buffer);
|
||||
|
||||
void sdn_changed(void);
|
||||
|
||||
#endif
|
||||
|
||||
101
src/bootldr/startup.S
Normal file
101
src/bootldr/startup.S
Normal file
@ -0,0 +1,101 @@
|
||||
/* startup code for LPC17xx
|
||||
*
|
||||
* Written 2010 by Ingo Korb
|
||||
*/
|
||||
.syntax unified
|
||||
|
||||
.section .vectors
|
||||
|
||||
.macro except label
|
||||
.weak \label
|
||||
.set \label, __unhandled_exception
|
||||
.word \label
|
||||
.endm
|
||||
|
||||
/* Cortex M3 standard except vectors */
|
||||
.word __stack
|
||||
.word _start
|
||||
except NMI_Handler
|
||||
except HardFault_Handler
|
||||
except MemManage_Handler
|
||||
except BusFault_Handler
|
||||
except UsageFault_Handler
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
.word 0
|
||||
except SVC_Handler
|
||||
except DebugMon_Handler
|
||||
.word 0
|
||||
except PendSV_Handler
|
||||
except SysTick_Handler
|
||||
|
||||
/* External interrupt vectors */
|
||||
except WDT_IRQHandler
|
||||
except TIMER0_IRQHandler
|
||||
except TIMER1_IRQHandler
|
||||
except TIMER2_IRQHandler
|
||||
except TIMER3_IRQHandler
|
||||
except UART0_IRQHandler
|
||||
except UART1_IRQHandler
|
||||
except UART2_IRQHandler
|
||||
except UART3_IRQHandler
|
||||
except PWM1_IRQHandler
|
||||
except I2C0_IRQHandler
|
||||
except I2C1_IRQHandler
|
||||
except I2C2_IRQHandler
|
||||
except SPI_IRQHandler
|
||||
except SSP0_IRQHandler
|
||||
except SSP1_IRQHandler
|
||||
except PLL0_IRQHandler
|
||||
except RTC_IRQHandler
|
||||
except EINT0_IRQHandler
|
||||
except EINT1_IRQHandler
|
||||
except EINT2_IRQHandler
|
||||
except EINT3_IRQHandler
|
||||
except ADC_IRQHandler
|
||||
except BOD_IRQHandler
|
||||
except USB_IRQHandler
|
||||
except CAN_IRQHandler
|
||||
except DMA_IRQHandler
|
||||
except I2S_IRQHandler
|
||||
except ENET_IRQHandler
|
||||
except RIT_IRQHandler
|
||||
except MCPWM_IRQHandler
|
||||
except QEI_IRQHandler
|
||||
except PLL1_IRQHandler
|
||||
|
||||
.section .text
|
||||
|
||||
.global _start
|
||||
.thumb_func
|
||||
_start:
|
||||
/* copy data section to ram */
|
||||
ldr r0, =__data_load_start
|
||||
ldr r1, =__data_load_end
|
||||
ldr r2, =__data_start
|
||||
dataloop:
|
||||
ldr.w r3, [r0], #4
|
||||
str.w r3, [r2], #4
|
||||
cmp r0, r1
|
||||
blo dataloop
|
||||
|
||||
/* clear bss section */
|
||||
ldr r0, =__bss_start__
|
||||
ldr r1, =__bss_end__
|
||||
ldr r2, =0
|
||||
bssloop:
|
||||
str.w r2, [r0], #4
|
||||
cmp r0, r1
|
||||
blo bssloop
|
||||
|
||||
/* start main() */
|
||||
b main
|
||||
|
||||
/* endless loop */
|
||||
.weak __unhandled_exception
|
||||
.thumb_func
|
||||
__unhandled_exception:
|
||||
b __unhandled_exception
|
||||
|
||||
.end
|
||||
104
src/bootldr/timer.c
Normal file
104
src/bootldr/timer.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* ___INGO___ */
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "bits.h"
|
||||
#include "config.h"
|
||||
#include "timer.h"
|
||||
#include "clock.h"
|
||||
#include "uart.h"
|
||||
#include "sdnative.h"
|
||||
|
||||
/* bit definitions */
|
||||
#define RITINT 0
|
||||
#define RITEN 3
|
||||
|
||||
#define PCRIT 16
|
||||
|
||||
extern volatile int sd_changed;
|
||||
volatile tick_t ticks;
|
||||
volatile int wokefromrit;
|
||||
|
||||
void __attribute__((weak,noinline)) SysTick_Hook(void) {
|
||||
/* Empty function for hooking the systick handler */
|
||||
}
|
||||
|
||||
/* Systick interrupt handler */
|
||||
void SysTick_Handler(void) {
|
||||
ticks++;
|
||||
static uint16_t sdch_state = 0;
|
||||
sdch_state = (sdch_state << 1) | SDCARD_DETECT | 0xe000;
|
||||
if((sdch_state == 0xf000) || (sdch_state == 0xefff)) {
|
||||
sd_changed = 1;
|
||||
}
|
||||
sdn_changed();
|
||||
SysTick_Hook();
|
||||
}
|
||||
|
||||
void __attribute__((weak,noinline)) RIT_Hook(void) {
|
||||
}
|
||||
|
||||
void RIT_IRQHandler(void) {
|
||||
LPC_RIT->RICTRL = BV(RITINT);
|
||||
NVIC_ClearPendingIRQ(RIT_IRQn);
|
||||
wokefromrit = 1;
|
||||
RIT_Hook();
|
||||
}
|
||||
|
||||
void timer_init(void) {
|
||||
/* turn on power to RIT */
|
||||
BITBAND(LPC_SC->PCONP, PCRIT) = 1;
|
||||
|
||||
/* clear RIT mask */
|
||||
LPC_RIT->RIMASK = 0; /*xffffffff;*/
|
||||
|
||||
/* PCLK = CCLK */
|
||||
BITBAND(LPC_SC->PCLKSEL1, 26) = 1;
|
||||
BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1;
|
||||
/* enable SysTick */
|
||||
SysTick_Config((SysTick->CALIB & SysTick_CALIB_TENMS_Msk));
|
||||
}
|
||||
|
||||
void delay_us(unsigned int time) {
|
||||
/* Prepare RIT */
|
||||
LPC_RIT->RICOUNTER = 0;
|
||||
LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000000) * time;
|
||||
LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT);
|
||||
|
||||
/* Wait until RIT signals an interrupt */
|
||||
while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ;
|
||||
|
||||
/* Disable RIT */
|
||||
LPC_RIT->RICTRL = 0;
|
||||
}
|
||||
|
||||
void delay_ms(unsigned int time) {
|
||||
/* Prepare RIT */
|
||||
LPC_RIT->RICOUNTER = 0;
|
||||
LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000) * time;
|
||||
LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT);
|
||||
|
||||
/* Wait until RIT signals an interrupt */
|
||||
while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ;
|
||||
|
||||
/* Disable RIT */
|
||||
LPC_RIT->RICTRL = 0;
|
||||
}
|
||||
|
||||
void sleep_ms(unsigned int time) {
|
||||
|
||||
wokefromrit = 0;
|
||||
/* Prepare RIT */
|
||||
LPC_RIT->RICOUNTER = 0;
|
||||
LPC_RIT->RICOMPVAL = (CONFIG_CPU_FREQUENCY / 1000) * time;
|
||||
LPC_RIT->RICTRL = BV(RITEN) | BV(RITINT);
|
||||
NVIC_EnableIRQ(RIT_IRQn);
|
||||
|
||||
/* Wait until RIT signals an interrupt */
|
||||
//uart_putc(';');
|
||||
while(!wokefromrit) {
|
||||
__WFI();
|
||||
}
|
||||
NVIC_DisableIRQ(RIT_IRQn);
|
||||
/* Disable RIT */
|
||||
LPC_RIT->RICTRL = BV(RITINT);
|
||||
}
|
||||
51
src/bootldr/timer.h
Normal file
51
src/bootldr/timer.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned int tick_t;
|
||||
|
||||
extern volatile tick_t ticks;
|
||||
#define HZ 100
|
||||
|
||||
/**
|
||||
* getticks - return the current system tick count
|
||||
*
|
||||
* This inline function returns the current system tick count.
|
||||
*/
|
||||
static inline tick_t getticks(void) {
|
||||
return ticks;
|
||||
}
|
||||
|
||||
#define MS_TO_TICKS(x) (x/10)
|
||||
|
||||
/* Adapted from Linux 2.6 include/linux/jiffies.h:
|
||||
*
|
||||
* These inlines deal with timer wrapping correctly. You are
|
||||
* strongly encouraged to use them
|
||||
* 1. Because people otherwise forget
|
||||
* 2. Because if the timer wrap changes in future you won't have to
|
||||
* alter your driver code.
|
||||
*
|
||||
* time_after(a,b) returns true if the time a is after time b.
|
||||
*
|
||||
* Do this with "<0" and ">=0" to only test the sign of the result. A
|
||||
* good compiler would generate better code (and a really good compiler
|
||||
* wouldn't care). Gcc is currently neither.
|
||||
* (">=0" refers to the time_after_eq macro which wasn't copied)
|
||||
*/
|
||||
#define time_after(a,b) \
|
||||
((int)(b) - (int)(a) < 0)
|
||||
#define time_before(a,b) time_after(b,a)
|
||||
|
||||
|
||||
void timer_init(void);
|
||||
|
||||
/* delay for "time" microseconds - uses the RIT */
|
||||
void delay_us(unsigned int time);
|
||||
|
||||
/* delay for "time" milliseconds - uses the RIT */
|
||||
void delay_ms(unsigned int time);
|
||||
void sleep_ms(unsigned int time);
|
||||
|
||||
#endif
|
||||
257
src/bootldr/uart.c
Normal file
257
src/bootldr/uart.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
|
||||
uart.c: UART access routines
|
||||
|
||||
*/
|
||||
|
||||
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
||||
#include "bits.h"
|
||||
#include "config.h"
|
||||
#include "uart.h"
|
||||
#include "led.h"
|
||||
|
||||
static uint8_t uart_lookupratio(float f_fr) {
|
||||
uint16_t errors[72]={0,67,71,77,83,91,100,111,125,
|
||||
133,143,154,167,182,200,214,222,231,
|
||||
250,267,273,286,300,308,333,357,364,
|
||||
375,385,400,417,429,444,455,462,467,
|
||||
500,533,538,545,556,571,583,600,615,
|
||||
625,636,643,667,692,700,714,727,733,
|
||||
750,769,778,786,800,818,833,846,857,
|
||||
867,875,889,900,909,917,923,929,933};
|
||||
|
||||
uint8_t ratios[72]={0x10,0xf1,0xe1,0xd1,0xc1,0xb1,0xa1,0x91,0x81,
|
||||
0xf2,0x71,0xd2,0x61,0xb2,0x51,0xe3,0x92,0xd3,
|
||||
0x41,0xf4,0xb3,0x72,0xa3,0xd4,0x31,0xe5,0xb4,
|
||||
0x83,0xd5,0x52,0xc5,0x73,0x94,0xb5,0xd6,0xf7,
|
||||
0x21,0xf8,0xd7,0xb6,0x95,0x74,0xc7,0x53,0xd8,
|
||||
0x85,0xb7,0xe9,0x32,0xd9,0xa7,0x75,0xb8,0xfb,
|
||||
0x43,0xda,0x97,0xeb,0x54,0xb9,0x65,0xdb,0x76,
|
||||
0xfd,0x87,0x98,0xa9,0xba,0xcb,0xdc,0xed,0xfe};
|
||||
|
||||
int fr = (f_fr-1)*1000;
|
||||
int i=0, i_result=0;
|
||||
int err=0, lasterr=1000;
|
||||
for(i=0; i<72; i++) {
|
||||
if(fr<errors[i]) {
|
||||
err=errors[i]-fr;
|
||||
} else {
|
||||
err=fr-errors[i];
|
||||
}
|
||||
if(err<lasterr) {
|
||||
i_result=i;
|
||||
lasterr=err;
|
||||
}
|
||||
}
|
||||
return ratios[i_result];
|
||||
}
|
||||
|
||||
static uint32_t baud2divisor(unsigned int baudrate) {
|
||||
uint32_t int_ratio;
|
||||
uint32_t error;
|
||||
uint32_t dl=0;
|
||||
float f_ratio;
|
||||
float f_fr;
|
||||
float f_dl;
|
||||
float f_pclk = (float)CONFIG_CPU_FREQUENCY / CONFIG_UART_PCLKDIV;
|
||||
uint8_t fract_ratio;
|
||||
f_ratio=(f_pclk / 16 / baudrate);
|
||||
int_ratio = (int)f_ratio;
|
||||
error=(f_ratio*1000)-(int_ratio*1000);
|
||||
if(error>990) {
|
||||
int_ratio++;
|
||||
} else if(error>10) {
|
||||
f_fr=1.5;
|
||||
f_dl=f_pclk / (16 * baudrate * (f_fr));
|
||||
dl = (int)f_dl;
|
||||
f_fr=f_pclk / (16 * baudrate * dl);
|
||||
fract_ratio = uart_lookupratio(f_fr);
|
||||
}
|
||||
if(!dl) {
|
||||
return int_ratio;
|
||||
} else {
|
||||
return ((fract_ratio<<16)&0xff0000) | dl;
|
||||
}
|
||||
}
|
||||
|
||||
static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT];
|
||||
static volatile unsigned int read_idx,write_idx;
|
||||
|
||||
void UART_HANDLER(void) {
|
||||
int iir = UART_REGS->IIR;
|
||||
if (!(iir & 1)) {
|
||||
/* Interrupt is pending */
|
||||
switch (iir & 14) {
|
||||
#if CONFIG_UART_NUM == 1
|
||||
case 0: /* modem status */
|
||||
(void) UART_REGS->MSR; // dummy read to clear
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 2: /* THR empty - send */
|
||||
if (read_idx != write_idx) {
|
||||
int maxchars = 16;
|
||||
while (read_idx != write_idx && --maxchars > 0) {
|
||||
UART_REGS->THR = (unsigned char)txbuf[read_idx];
|
||||
read_idx = (read_idx+1) & (sizeof(txbuf)-1);
|
||||
}
|
||||
if (read_idx == write_idx) {
|
||||
/* buffer empty - turn off THRE interrupt */
|
||||
BITBAND(UART_REGS->IER, 1) = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 12: /* RX timeout */
|
||||
case 4: /* data received - not implemented yet */
|
||||
(void) UART_REGS->RBR; // dummy read to clear
|
||||
break;
|
||||
|
||||
case 6: /* RX error */
|
||||
(void) UART_REGS->LSR; // dummy read to clear
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uart_putc(char c) {
|
||||
if (c == '\n')
|
||||
uart_putc('\r');
|
||||
|
||||
unsigned int tmp = (write_idx+1) & (sizeof(txbuf)-1) ;
|
||||
|
||||
if (read_idx == write_idx && (BITBAND(UART_REGS->LSR, 5))) {
|
||||
/* buffer empty, THR empty -> send immediately */
|
||||
UART_REGS->THR = (unsigned char)c;
|
||||
} else {
|
||||
#ifdef CONFIG_UART_DEADLOCKABLE
|
||||
while (tmp == read_idx) ;
|
||||
#endif
|
||||
BITBAND(UART_REGS->IER, 1) = 0; // turn off UART interrupt
|
||||
txbuf[write_idx] = c;
|
||||
write_idx = tmp;
|
||||
BITBAND(UART_REGS->IER, 1) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Polling version only */
|
||||
unsigned char uart_getc(void) {
|
||||
/* wait for character */
|
||||
while (!(BITBAND(UART_REGS->LSR, 0))) ;
|
||||
return UART_REGS->RBR;
|
||||
}
|
||||
|
||||
/* Returns true if a char is ready */
|
||||
unsigned char uart_gotc(void) {
|
||||
return BITBAND(UART_REGS->LSR, 0);
|
||||
}
|
||||
|
||||
void uart_init(void) {
|
||||
uint32_t div;
|
||||
|
||||
/* Turn on power to UART */
|
||||
BITBAND(LPC_SC->PCONP, UART_PCONBIT) = 1;
|
||||
|
||||
/* UART clock = CPU clock - this block is reduced at compile-time */
|
||||
if (CONFIG_UART_PCLKDIV == 1) {
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0;
|
||||
} else if (CONFIG_UART_PCLKDIV == 2) {
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1;
|
||||
} else if (CONFIG_UART_PCLKDIV == 4) {
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0;
|
||||
} else { // Fallback: Divide by 8
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
|
||||
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1;
|
||||
}
|
||||
|
||||
/* set baud rate - no fractional stuff for now */
|
||||
UART_REGS->LCR = BV(7) | 3; // always 8n1
|
||||
div = baud2divisor(CONFIG_UART_BAUDRATE);
|
||||
|
||||
UART_REGS->DLL = div & 0xff;
|
||||
UART_REGS->DLM = (div >> 8) & 0xff;
|
||||
BITBAND(UART_REGS->LCR, 7) = 0;
|
||||
|
||||
if (div & 0xff0000) {
|
||||
UART_REGS->FDR = (div >> 16) & 0xff;
|
||||
}
|
||||
|
||||
/* reset and enable FIFO */
|
||||
UART_REGS->FCR = BV(0);
|
||||
|
||||
/* enable transmit interrupt */
|
||||
BITBAND(UART_REGS->IER, 1) = 1;
|
||||
NVIC_EnableIRQ(UART_IRQ);
|
||||
|
||||
UART_REGS->THR = '?';
|
||||
}
|
||||
|
||||
/* --- generic code below --- */
|
||||
void uart_puthex(uint8_t num) {
|
||||
uint8_t tmp;
|
||||
tmp = (num & 0xf0) >> 4;
|
||||
if (tmp < 10)
|
||||
uart_putc('0'+tmp);
|
||||
else
|
||||
uart_putc('a'+tmp-10);
|
||||
|
||||
tmp = num & 0x0f;
|
||||
if (tmp < 10)
|
||||
uart_putc('0'+tmp);
|
||||
else
|
||||
uart_putc('a'+tmp-10);
|
||||
}
|
||||
|
||||
void uart_trace(void *ptr, uint16_t start, uint16_t len) {
|
||||
uint16_t i;
|
||||
uint8_t j;
|
||||
uint8_t ch;
|
||||
uint8_t *data = ptr;
|
||||
|
||||
data+=start;
|
||||
for(i=0;i<len;i+=16) {
|
||||
|
||||
uart_puthex(start>>8);
|
||||
uart_puthex(start&0xff);
|
||||
uart_putc('|');
|
||||
uart_putc(' ');
|
||||
for(j=0;j<16;j++) {
|
||||
if(i+j<len) {
|
||||
ch=*(data + j);
|
||||
uart_puthex(ch);
|
||||
} else {
|
||||
uart_putc(' ');
|
||||
uart_putc(' ');
|
||||
}
|
||||
uart_putc(' ');
|
||||
}
|
||||
uart_putc('|');
|
||||
for(j=0;j<16;j++) {
|
||||
if(i+j<len) {
|
||||
ch=*(data++);
|
||||
if(ch<32 || ch>0x7e)
|
||||
ch='.';
|
||||
uart_putc(ch);
|
||||
} else {
|
||||
uart_putc(' ');
|
||||
}
|
||||
}
|
||||
uart_putc('|');
|
||||
uart_putcrlf();
|
||||
start+=16;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_flush(void) {
|
||||
while (read_idx != write_idx) ;
|
||||
}
|
||||
|
||||
void uart_puts(const char *text) {
|
||||
while (*text) {
|
||||
uart_putc(*text++);
|
||||
}
|
||||
}
|
||||
83
src/bootldr/uart.h
Normal file
83
src/bootldr/uart.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
|
||||
uart.h: Definitions for the UART access routines
|
||||
|
||||
*/
|
||||
|
||||
#ifndef UART_H
|
||||
#define UART_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
|
||||
//#ifdef CONFIG_UART_DEBUG
|
||||
#if 1
|
||||
|
||||
#ifdef __AVR__
|
||||
# include <avr/pgmspace.h>
|
||||
void uart_puts_P(prog_char *text);
|
||||
#else
|
||||
# define uart_puts_P(str) uart_puts(str)
|
||||
#endif
|
||||
|
||||
void uart_init(void);
|
||||
unsigned char uart_getc(void);
|
||||
unsigned char uart_gotc(void);
|
||||
void uart_putc(char c);
|
||||
void uart_puts(const char *str);
|
||||
void uart_puthex(uint8_t num);
|
||||
void uart_trace(void *ptr, uint16_t start, uint16_t len);
|
||||
void uart_flush(void);
|
||||
int printf(const char *fmt, ...);
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
#define uart_putcrlf() uart_putc('\n')
|
||||
|
||||
/* A few symbols to make this code work for all four UARTs */
|
||||
#if defined(CONFIG_UART_NUM) && CONFIG_UART_NUM == 0
|
||||
# define UART_PCONBIT 3
|
||||
# define UART_PCLKREG PCLKSEL0
|
||||
# define UART_PCLKBIT 6
|
||||
# define UART_REGS LPC_UART0
|
||||
# define UART_HANDLER UART0_IRQHandler
|
||||
# define UART_IRQ UART0_IRQn
|
||||
#elif CONFIG_UART_NUM == 1
|
||||
# define UART_PCONBIT 4
|
||||
# define UART_PCLKREG PCLKSEL0
|
||||
# define UART_PCLKBIT 8
|
||||
# define UART_REGS LPC_UART1
|
||||
# define UART_HANDLER UART1_IRQHandler
|
||||
# define UART_IRQ UART1_IRQn
|
||||
#elif CONFIG_UART_NUM == 2
|
||||
# define UART_PCONBIT 24
|
||||
# define UART_PCLKREG PCLKSEL1
|
||||
# define UART_PCLKBIT 16
|
||||
# define UART_REGS LPC_UART2
|
||||
# define UART_HANDLER UART2_IRQHandler
|
||||
# define UART_IRQ UART2_IRQn
|
||||
#elif CONFIG_UART_NUM == 3
|
||||
# define UART_PCONBIT 25
|
||||
# define UART_PCLKREG PCLKSEL1
|
||||
# define UART_PCLKBIT 18
|
||||
# define UART_REGS LPC_UART3
|
||||
# define UART_HANDLER UART3_IRQHandler
|
||||
# define UART_IRQ UART3_IRQn
|
||||
#else
|
||||
# error CONFIG_UART_NUM is not set or has an invalid value!
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define uart_init() do {} while(0)
|
||||
#define uart_getc() 0
|
||||
#define uart_putc(x) do {} while(0)
|
||||
#define uart_puthex(x) do {} while(0)
|
||||
#define uart_flush() do {} while(0)
|
||||
#define uart_puts_P(x) do {} while(0)
|
||||
#define uart_puts(x) do {} while(0)
|
||||
#define uart_putcrlf() do {} while(0)
|
||||
#define uart_trace(a,b,c) do {} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,2 +1,3 @@
|
||||
CONFIG_VERSION=0.0.1
|
||||
CONFIG_FWVER=1
|
||||
CONFIG_MCU_FOSC=12000000
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#flash info 0
|
||||
|
||||
reset init
|
||||
flash write_image erase unlock obj/sd2snes.bin 0 bin
|
||||
flash write_image erase unlock obj/sd2snes.elf
|
||||
reset run
|
||||
shutdown
|
||||
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
OUTPUT_FORMAT(elf32-littlearm)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x20000
|
||||
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x03fe0 /* leave room for IAP */
|
||||
flash (rx) : ORIGIN = 0x00004100, LENGTH = 0x1bf00 /* leave room for bootldr + metadata */
|
||||
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x04000
|
||||
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Wstrict-prototypes -Werror
|
||||
|
||||
all: lpcchksum
|
||||
all: lpcchksum genhdr
|
||||
|
||||
genhdr: genhdr.o
|
||||
$(CC) $(CFLAGS) $^ --output $@
|
||||
|
||||
lpcchksum: lpcchksum.o
|
||||
$(CC) $(CFLAGS) $^ --output $@
|
||||
|
||||
126
src/utils/genhdr.c
Normal file
126
src/utils/genhdr.c
Normal file
@ -0,0 +1,126 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ll8(x) (x & 0xff)
|
||||
#define lh8(x) ((x >> 8) & 0xff)
|
||||
#define hl8(x) ((x >> 16) & 0xff)
|
||||
#define hh8(x) ((x >> 24) & 0xff)
|
||||
|
||||
/* Generated on Thu Feb 17 10:57:01 2011,
|
||||
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||
*/
|
||||
uint32_t crc_reflect(uint32_t data, size_t data_len)
|
||||
{
|
||||
unsigned int i;
|
||||
uint32_t ret;
|
||||
|
||||
ret = data & 0x01;
|
||||
for (i = 1; i < data_len; i++)
|
||||
{
|
||||
data >>= 1;
|
||||
ret = (ret << 1) | (data & 0x01);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t crc_update(uint32_t crc, const uint8_t *buf, uint32_t len) {
|
||||
unsigned int i;
|
||||
uint32_t bit;
|
||||
uint8_t c;
|
||||
|
||||
while (len--) {
|
||||
c = *buf++;
|
||||
for (i = 0x01; i & 0xff; i <<= 1) {
|
||||
bit = crc & 0x80000000;
|
||||
if (c & i) {
|
||||
bit = bit ? 0 : 1;
|
||||
}
|
||||
crc <<= 1;
|
||||
if (bit) {
|
||||
crc ^= 0x04c11db7;
|
||||
}
|
||||
}
|
||||
crc &= 0xffffffff;
|
||||
}
|
||||
return crc & 0xffffffff;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *f;
|
||||
size_t flen;
|
||||
|
||||
if(argc < 3) {
|
||||
printf("Usage: genhdr <input file> <signature> <version>\n"
|
||||
" input file: file to be headered\n"
|
||||
" signature : magic value at start of header (4-char string)\n"
|
||||
" version : firmware version (decimal uint32)\n"
|
||||
"Output is written in place.\n");
|
||||
return 1;
|
||||
}
|
||||
if((f=fopen(argv[1], "rb+"))==NULL) {
|
||||
printf("Unable to open input file %s", argv[1]);
|
||||
perror("");
|
||||
return 1;
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
flen=ftell(f);
|
||||
|
||||
if(flen+256 < flen) {
|
||||
printf("File too large ;)\n");
|
||||
return 1;
|
||||
}
|
||||
char *remaining = NULL;
|
||||
uint32_t version = (uint32_t)strtol(argv[3], &remaining, 10);
|
||||
if(*remaining) {
|
||||
printf("could not parse version number (remaining portion: %s)\n", remaining);
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(strlen(argv[2]) > 4) {
|
||||
printf("Magic string '%s' too long. Truncated to 4 characters.\n", argv[2]);
|
||||
}
|
||||
uint8_t *buf = malloc(flen+256);
|
||||
if(!buf) {
|
||||
perror("malloc");
|
||||
}
|
||||
memset(buf, 0xff, 256);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fread(buf+256, 1, flen, f);
|
||||
|
||||
uint32_t crcc = 0xffffffff, crc;
|
||||
crcc = crc_update(crcc, buf+256, flen);
|
||||
crcc = crc_reflect(crcc, 32);
|
||||
crc = crcc ^ 0xffffffff;
|
||||
|
||||
memset(buf, 0, 4);
|
||||
strncpy((char*)buf, argv[2], 4);
|
||||
|
||||
buf[4] = ll8(version);
|
||||
buf[5] = lh8(version);
|
||||
buf[6] = hl8(version);
|
||||
buf[7] = hh8(version);
|
||||
|
||||
buf[8] = ll8(flen);
|
||||
buf[9] = lh8(flen);
|
||||
buf[10] = hl8(flen);
|
||||
buf[11] = hh8(flen);
|
||||
|
||||
buf[12] = ll8(crc);
|
||||
buf[13] = lh8(crc);
|
||||
buf[14] = hl8(crc);
|
||||
buf[15] = hh8(crc);
|
||||
|
||||
buf[16] = ll8(crcc);
|
||||
buf[17] = lh8(crcc);
|
||||
buf[18] = hl8(crcc);
|
||||
buf[19] = hh8(crcc);
|
||||
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fwrite(buf, 1, 256+flen, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user