Help Compiling "Blinky"

Status
Not open for further replies.

gudenau

New member
I am attempting to compile Blinky for my USB Teensy 2. I just installed winAVR on Windows 10 x64, an when I execute make it fails.

Code:
      0 [main] sh 4192 sync_with_child: child 5676(0x1AC) died before initialization with status code 0xC0000142
    235 [main] sh 4192 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
      0 [main] sh 3264 sync_with_child: child 2344(0x1BC) died before initialization with status code 0xC0000142
    474 [main] sh 3264 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling C: blinky.c
avr-gcc -c -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./blinky.lst  -std=gnu99 -MMD -MP -MF .dep/blinky.o.d blinky.c -o blinky.o
blinky.c:158: fatal error: opening dependency file .dep/blinky.o.d: No such file or directory
compilation terminated.
make: *** [blinky.o] Error 1
 
A partial solution to the identical problem--Need more help

I also have identical results as op in make output running Windows 10 pro version 1151. I have laboriously found a partial solution. Manually creating a /.dep directory in the code directory gets us much of the way through the compilation and linking. I now get this output:
Code:
C:_________\blinky>make
      0 [main] sh 5808 sync_with_child: child 4516(0x174) died before initialization with status code 0xC0000142
    651 [main] sh 5808 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
      0 [main] sh 4040 sync_with_child: child 5156(0x174) died before initialization with status code 0xC0000142
    244 [main] sh 4040 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling C: blinky.c
avr-gcc -c -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./blinky.lst  -std=gnu99 -MMD -MP -MF .dep/blinky.o.d blinky.c -o blinky.o

Compiling C: usb_debug_only.c
avr-gcc -c -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./usb_debug_only.lst  -std=gnu99 -MMD -MP -MF .dep/usb_debug_only.o.d usb_debug_only.c -o usb_debug_only.o

Compiling C: print.c
avr-gcc -c -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./print.lst  -std=gnu99 -MMD -MP -MF .dep/print.o.d print.c -o print.o

Linking: blinky.elf
avr-gcc -mmcu=atmega32u4         -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=blinky.o  -std=gnu99 -MMD -MP -MF .dep/blinky.elf.d blinky.o usb_debug_only.o print.o --output blinky.elf -Wl,-Map=blinky.map,--cref -Wl,--relax -Wl,--gc-sections     -lm

Creating load file for Flash: blinky.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature blinky.elf blinky.hex

Creating load file for EEPROM: blinky.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
        --change-section-lma .eeprom=0 --no-change-warnings -O ihex blinky.elf blinky.eep || exit 0
      0 [main] sh 4480 sync_with_child: child 3504(0x178) died before initialization with status code 0xC0000142
    675 [main] sh 4480 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
make: [blinky.eep] Error 128 (ignored)

Creating Extended Listing: blinky.lss
avr-objdump -h -S -z blinky.elf > blinky.lss
      0 [main] sh 5688 sync_with_child: child 1144(0x170) died before initialization with status code 0xC0000142
    678 [main] sh 5688 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
make: *** [blinky.lss] Error 128

This produces a .hex file that works, but also throws errors I do not recognize. Errors I don't recognize make me very nervous.

Help would be greatly appreciated.

[EDIT] The .dep folder has to be made from the command line: mkdir .dep.[/EDIT]
 
Last edited:
Makefile for blinky

Thanks for your response. This is the makefile that came with the download. I haven't altered it. (I guess I'll have to relearn make; haven't used it for years.)
Code:
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg 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
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
#                Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging, 
#              with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
#                   bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------


# Target file name (without extension).
TARGET = blinky


# List C source files here. (C dependencies are automatically generated.)
SRC =	$(TARGET).c \
	usb_debug_only.c \
	print.c

# MCU name, you MUST set this to match the board you are using
# type "make clean" after changing this, so all files will be rebuilt
#
#MCU = at90usb162       # Teensy 1.0
MCU = atmega32u4        # Teensy 2.0
#MCU = at90usb646       # Teensy++ 1.0
#MCU = at90usb1286      # Teensy++ 2.0


# Processor frequency.
#   Normally the first thing your program should do is set the clock prescaler,
#   so your program will run at the correct speed.  You should also set this
#   variable to same clock speed.  The _delay_ms() macro uses this, and many
#   examples use this variable to calculate timings.  Do not add a "UL" here.
F_CPU = 16000000


# Output format. (can be srec, ihex, binary)
FORMAT = ihex


# Object files directory
#     To put object files in current directory, use a dot (.), do NOT make
#     this an empty or blank macro!
OBJDIR = .


# List C++ source files here. (C dependencies are automatically generated.)
CPPSRC = 


# List Assembler source files here.
#     Make them always end in a capital .S.  Files ending in a lowercase .s
#     will not be considered source files but generated files (assembler
#     output from the compiler), and will be deleted upon "make clean"!
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
#     it will preserve the spelling of the filenames, and gcc itself does
#     care about how the name is spelled on its command-line.
ASRC =


# Optimization level, can be [0, 1, 2, 3, s]. 
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s


# Debugging format.
#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
#     AVR Studio 4.10 requires dwarf-2.
#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2


# List any extra directories to look for include files here.
#     Each directory must be seperated by a space.
#     Use forward slashes for directory separators.
#     For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS = 


# Compiler flag to set the C Standard level.
#     c89   = "ANSI" C
#     gnu89 = c89 plus GCC extensions
#     c99   = ISO C99 standard (not yet fully implemented)
#     gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99


# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL


# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)


# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS



#---------------- Compiler Options C ----------------
#  -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)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -ffunction-sections
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)


#---------------- Compiler Options C++ ----------------
#  -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
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CPPFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)


#---------------- Assembler Options ----------------
#  -Wa,...:   tell GCC to pass this to the assembler.
#  -adhlns:   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]
#  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
#       dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100


#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt

# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB = 
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)


# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min

# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt

# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB = 
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)


MATH_LIB = -lm


# List any extra directories to look for libraries 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.
EXTRALIBDIRS = 



#---------------- External Memory Options ----------------

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff

# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff

EXTMEMOPTS =



#---------------- Linker Options ----------------
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += -Wl,--relax
LDFLAGS += -Wl,--gc-sections
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -T linker_script.x



#---------------- Programming Options (avrdude) ----------------

# Programming hardware
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500v2

# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = com1    # programmer connected to serial device

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep


# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y

# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V

# Increase verbosity level.  Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v

AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)



#---------------- Debugging Options ----------------

# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)

# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight

# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr

# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit

# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1

# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242

# Debugging host used to communicate between GDB / avarice / simulavr, normally
#     just set to localhost unless doing some sort of crazy debugging when 
#     avarice is running on a different computer.
DEBUG_HOST = localhost



#============================================================================


# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd


# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = --------  end  --------
MSG_SIZE_BEFORE = Size before: 
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:




# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) 

# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) 


# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d


# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)





# Default target.
all: begin gccversion sizebefore build sizeafter end

# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib


elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)



# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
	@echo
	@echo $(MSG_BEGIN)

end:
	@echo $(MSG_END)
	@echo


# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
ELFSIZE = $(SIZE) $(TARGET).elf

sizebefore:
	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
	2>/dev/null; echo; fi

sizeafter:
	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
	2>/dev/null; echo; fi



# Display compiler version information.
gccversion : 
	@$(CC) --version



# Program the device.  
program: $(TARGET).hex $(TARGET).eep
	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)


# Generate avr-gdb config/init file which does the following:
#     define the reset signal, load the target file, connect to target, and set 
#     a breakpoint at main().
gdb-config: 
	@$(REMOVE) $(GDBINIT_FILE)
	@echo define reset >> $(GDBINIT_FILE)
	@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
	@echo end >> $(GDBINIT_FILE)
	@echo file $(TARGET).elf >> $(GDBINIT_FILE)
	@echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
	@echo load  >> $(GDBINIT_FILE)
endif
	@echo break main >> $(GDBINIT_FILE)

debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
	@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
	@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
	$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
	@$(WINSHELL) /c pause

else
	@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
	$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
	@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)




# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000



coff: $(TARGET).elf
	@echo
	@echo $(MSG_COFF) $(TARGET).cof
	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof


extcoff: $(TARGET).elf
	@echo
	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof



# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
	@echo
	@echo $(MSG_FLASH) $@
	$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@

%.eep: %.elf
	@echo
	@echo $(MSG_EEPROM) $@
	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
	--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0

# Create extended listing file from ELF output file.
%.lss: %.elf
	@echo
	@echo $(MSG_EXTENDED_LISTING) $@
	$(OBJDUMP) -h -S -z $< > $@

# Create a symbol table from ELF output file.
%.sym: %.elf
	@echo
	@echo $(MSG_SYMBOL_TABLE) $@
	$(NM) -n $< > $@



# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
	@echo
	@echo $(MSG_CREATING_LIBRARY) $@
	$(AR) $@ $(OBJ)


# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
	@echo
	@echo $(MSG_LINKING) $@
	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)


# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
	@echo
	@echo $(MSG_COMPILING) $<
	$(CC) -c $(ALL_CFLAGS) $< -o $@ 


# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
	@echo
	@echo $(MSG_COMPILING_CPP) $<
	$(CC) -c $(ALL_CPPFLAGS) $< -o $@ 


# Compile: create assembler files from C source files.
%.s : %.c
	$(CC) -S $(ALL_CFLAGS) $< -o $@


# Compile: create assembler files from C++ source files.
%.s : %.cpp
	$(CC) -S $(ALL_CPPFLAGS) $< -o $@


# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
	@echo
	@echo $(MSG_ASSEMBLING) $<
	$(CC) -c $(ALL_ASFLAGS) $< -o $@


# Create preprocessed source for use in sending a bug report.
%.i : %.c
	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 


# Target: clean project.
clean: begin clean_list end

clean_list :
	@echo
	@echo $(MSG_CLEANING)
	$(REMOVE) $(TARGET).hex
	$(REMOVE) $(TARGET).eep
	$(REMOVE) $(TARGET).cof
	$(REMOVE) $(TARGET).elf
	$(REMOVE) $(TARGET).map
	$(REMOVE) $(TARGET).sym
	$(REMOVE) $(TARGET).lss
	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
	$(REMOVE) $(SRC:.c=.s)
	$(REMOVE) $(SRC:.c=.d)
	$(REMOVE) $(SRC:.c=.i)
	$(REMOVEDIR) .dep


# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)


# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)


# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config
 
No luck with a WinAVR reinstall. I'm going to play with this a little more. I suspect there may be some subtle differences between Windows 10 and earlier versions that are causing the problem. WinAVR doesn't appear to have been update since 2010. If I don't have any luck I'll switch to Linux. I have Debian 8 running on a different machine. I was using Windows because that's what the device (a multi-button input for a physical therapy application for cerebral palsy) will be interacting with when it's working. If I learn anything useful I'll post again.

Thanks for the responses.
 
Well, that's strange. The problem seems to have been longstanding and never fixed. The solution was in a post that refers to the 2007 version of WinAVR. MadWizard.org has a patch for msys-1.0.dll in the WinAVR/utils/bin directory. I applied the patch and the problems disappeared. Explanation and patch at http://www.madwizard.org/electronics/articles/winavrvista Thanks MadWizard for leaving this up since 2007!!!
 
Registered to say thanks to RonBurke. So strange this works, yet so great MadWizard left it up and he posted this answer. I could see some people possibly having last-mile troubles, so I'll just say it: once you download the mysys-1.0.dll from MadWizard, extract the zip, and move the dll to the WinAVR/utils/bin directory, wherever you installed it. I deleted the existing dll of the same name first. Looks like this wasn't the first time this file was patched as my install includes mysys-1.0.dll.old file. I left that alone. In any event, after following RonBurke's instructions, I ran make in my directory again and it compiled without error.
 
Registered just to say jeeeeeeesh, what a load of crap!
In addition to RonBurke's dll patch above, I still had to create the .dep directory in my /blink source folder before it worked.
And even then, the .eep and .lss sections of the make seems to die...
But it did produce the .hex file, and I could flash it to the Teensy 2 with teensy loader, and its blinking morse-code at me right now... so it seems to have worked.
I'm using WinAVR-20100110 for what it's worth...
Good luck people of the future!
 
Yes. Changing seven values in the file usb_debug_only.c allowed blinky to compile without error. Change 'device_descriptor’, ‘hid_report_descriptor’, ‘config1_descriptor’, ‘string0’, ‘string1’, ‘string2’ and ‘descriptor_list' to constant from static and makefile will run.

The demo code blinky.zip at https://www.pjrc.com/teensy/gcc.html did not work with WinAVR on Windows 10, did not work on Ubuntu or Raspbian, did not work from CLI, Netbeans or Geany IDE.

The error messages were all of the nature "usb_debug_only.c:96:24: error: variable ‘device_descriptor’ must be const in order to be put into read-only section". Closer inspection of usb_debug_only.c showed the values declared as static.

Other posters on this forum said to change to const and code would compile. They were correct and makefile began working, generating a hex file and several other fascinating files such as .map and .lst.


Now, I arrive at another matter. The example is written for Teensy's that have AVR chips and I have a Teensy LC with an ARM chip.

When I try to upload to my board with TeensyDuino I get messages that "blinky.hex" is not compiled for this board
Compiled for: "Teensy 2.0 (ATMEGA32U4)"
This board is: "Teensy LC (MKL26Z64)"

My next step will be to modify Makefile so that it calls for ARM compiler tools instead of AVR tools. The boards.txt file from my Arduino folder may show exactly which changes I need to make.

Wish me luck.

CompatibilityError.PNG
 
Code:
// usb_debug_only.c   modified to run by changing seven static values to constants
/* USB Debug Channel Example for Teensy USB Development Board
 * [URL]http://www.pjrc.com/teensy/[/URL]
 * Copyright (c) 2008 PJRC.COM, LLC
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

// Version 1.0: Initial Release
// Version 1.1: Add support for Teensy 2.0
// Version 1.x: Pat Fitzgerald
// modified from original downloaded from [URL]https://www.pjrc.com/teensy/gcc.html[/URL]
// original failed to compile on Ubuntu, Raspbian and Windows error message that 
// static values need to be changed to constants
//   'device_descriptor’, ‘hid_report_descriptor’, ‘config1_descriptor’, 
//   ‘string0’, ‘string1’, ‘string2’ and ‘descriptor_list' 
//    to constant from static

#define USB_SERIAL_PRIVATE_INCLUDE
#include "usb_debug_only.h"

/**************************************************************************
 *
 *  Configurable Options
 *
 **************************************************************************/

// You can change these to give your code its own name.  On Windows,
// these are only used before an INF file (driver install) is loaded.
#define STR_MANUFACTURER    L"Your Name"
#define STR_PRODUCT        L"Your USB Device"


// Mac OS-X and Linux automatically load the correct drivers.  On
// Windows, even though the driver is supplied by Microsoft, an
// INF file is needed to load the driver.  These numbers need to
// match the INF file.
#define VENDOR_ID        0x16C0
#define PRODUCT_ID        0x0479


// USB devices are supposed to implment a halt feature, which is
// rarely (if ever) used.  If you comment this line out, the halt
// code will be removed, saving 102 bytes of space (gcc 4.3.0).
// This is not strictly USB compliant, but works with all major
// operating systems.
#define SUPPORT_ENDPOINT_HALT



/**************************************************************************
 *
 *  Endpoint Buffer Configuration
 *
 **************************************************************************/

// you might want to change the buffer size, up to 64 bytes.
// The host reserves your bandwidth because this is an interrupt
// endpoint, so it won't be available to other interrupt or isync
// endpoints in other devices on the bus.

#define ENDPOINT0_SIZE        32
#define DEBUG_TX_ENDPOINT    3
#define DEBUG_TX_SIZE        32
#define DEBUG_TX_BUFFER        EP_DOUBLE_BUFFER

static const uint8_t PROGMEM endpoint_config_table[] = {
    0,
    0,
    1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER,
    0
};


/**************************************************************************
 *
 *  Descriptor Data
 *
 **************************************************************************/

// Descriptors are the data that your computer reads when it auto-detects
// this USB device (called "enumeration" in USB lingo).  The most commonly
// changed items are editable at the top of this file.  Changing things
// in here should only be done by those who've read chapter 9 of the USB
// spec and relevant portions of any USB class specifications!


const uint8_t PROGMEM device_descriptor[] = {
    18,                    // bLength
    1,                    // bDescriptorType
    0x00, 0x02,                // bcdUSB
    0,                    // bDeviceClass
    0,                    // bDeviceSubClass
    0,                    // bDeviceProtocol
    ENDPOINT0_SIZE,                // bMaxPacketSize0
    LSB(VENDOR_ID), MSB(VENDOR_ID),        // idVendor
    LSB(PRODUCT_ID), MSB(PRODUCT_ID),    // idProduct
    0x00, 0x01,                // bcdDevice
    1,                    // iManufacturer
    2,                    // iProduct
    0,                    // iSerialNumber
    1                    // bNumConfigurations
};

const uint8_t PROGMEM hid_report_descriptor[] = {
    0x06, 0x31, 0xFF,            // Usage Page 0xFF31 (vendor defined)
    0x09, 0x74,                // Usage 0x74
    0xA1, 0x53,                // Collection 0x53
    0x75, 0x08,                // report size = 8 bits
    0x15, 0x00,                // logical minimum = 0
    0x26, 0xFF, 0x00,            // logical maximum = 255
    0x95, DEBUG_TX_SIZE,            // report count
    0x09, 0x75,                // usage
    0x81, 0x02,                // Input (array)
    0xC0                    // end collection
};

#define CONFIG1_DESC_SIZE (9+9+9+7)
#define HID_DESC2_OFFSET  (9+9)
const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
    // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
    9,                     // bLength;
    2,                    // bDescriptorType;
    LSB(CONFIG1_DESC_SIZE),            // wTotalLength
    MSB(CONFIG1_DESC_SIZE),
    1,                    // bNumInterfaces
    1,                    // bConfigurationValue
    0,                    // iConfiguration
    0xC0,                    // bmAttributes
    50,                    // bMaxPower
    // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
    9,                    // bLength
    4,                    // bDescriptorType
    0,                    // bInterfaceNumber
    0,                    // bAlternateSetting
    1,                    // bNumEndpoints
    0x03,                    // bInterfaceClass (0x03 = HID)
    0x00,                    // bInterfaceSubClass
    0x00,                    // bInterfaceProtocol
    0,                    // iInterface
    // HID interface descriptor, HID 1.11 spec, section 6.2.1
    9,                    // bLength
    0x21,                    // bDescriptorType
    0x11, 0x01,                // bcdHID
    0,                    // bCountryCode
    1,                    // bNumDescriptors
    0x22,                    // bDescriptorType
    sizeof(hid_report_descriptor),        // wDescriptorLength
    0,
    // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
    7,                    // bLength
    5,                    // bDescriptorType
    DEBUG_TX_ENDPOINT | 0x80,        // bEndpointAddress
    0x03,                    // bmAttributes (0x03=intr)
    DEBUG_TX_SIZE, 0,            // wMaxPacketSize
    1                    // bInterval
};

// If you're desperate for a little extra code memory, these strings
// can be completely removed if iManufacturer, iProduct, iSerialNumber
// in the device desciptor are changed to zeros.
struct usb_string_descriptor_struct {
    uint8_t bLength;
    uint8_t bDescriptorType;
    int16_t wString[];
};
const struct usb_string_descriptor_struct PROGMEM string0 = {
    4,
    3,
    {0x0409}
};
const struct usb_string_descriptor_struct PROGMEM string1 = {
    sizeof(STR_MANUFACTURER),
    3,
    STR_MANUFACTURER
};
const struct usb_string_descriptor_struct PROGMEM string2 = {
    sizeof(STR_PRODUCT),
    3,
    STR_PRODUCT
};

// This table defines which descriptor data is sent for each specific
// request from the host (in wValue and wIndex).
const struct descriptor_list_struct {
    uint16_t    wValue;
    uint16_t    wIndex;
    const uint8_t    *addr;
    uint8_t        length;
} PROGMEM descriptor_list[] = {
    {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
    {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
    {0x2200, 0x0000, hid_report_descriptor, sizeof(hid_report_descriptor)},
    {0x2100, 0x0000, config1_descriptor+HID_DESC2_OFFSET, 9},
    {0x0300, 0x0000, (const uint8_t *)&string0, 4},
    {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
    {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
};
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))


/**************************************************************************
 *
 *  Variables - these are the only non-stack RAM usage
 *
 **************************************************************************/

// zero when we are not configured, non-zero when enumerated
static volatile uint8_t usb_configuration=0;

// the time remaining before we transmit any partially full
// packet, or send a zero length packet.
static volatile uint8_t debug_flush_timer=0;


/**************************************************************************
 *
 *  Public Functions - these are the API intended for the user
 *
 **************************************************************************/


// initialize USB
void usb_init(void)
{
    HW_CONFIG();
    USB_FREEZE();                // enable USB
    PLL_CONFIG();                // config PLL
        while (!(PLLCSR & (1<<PLOCK))) ;    // wait for PLL lock
        USB_CONFIG();                // start USB clock
        UDCON = 0;                // enable attach resistor
    usb_configuration = 0;
        UDIEN = (1<<EORSTE)|(1<<SOFE);
    sei();
}

// return 0 if the USB is not configured, or the configuration
// number selected by the HOST
uint8_t usb_configured(void)
{
    return usb_configuration;
}

// transmit a character.  0 returned on success, -1 on error
int8_t usb_debug_putchar(uint8_t c)
{
    static uint8_t previous_timeout=0;
    uint8_t timeout, intr_state;

    // if we're not online (enumerated and configured), error
    if (!usb_configuration) return -1;
    // interrupts are disabled so these functions can be
    // used from the main program or interrupt context,
    // even both in the same program!
    intr_state = SREG;
    cli();
    UENUM = DEBUG_TX_ENDPOINT;
    // if we gave up due to timeout before, don't wait again
    if (previous_timeout) {
        if (!(UEINTX & (1<<RWAL))) {
            SREG = intr_state;
            return -1;
        }
        previous_timeout = 0;
    }
    // wait for the FIFO to be ready to accept data
    timeout = UDFNUML + 4;
    while (1) {
        // are we ready to transmit?
        if (UEINTX & (1<<RWAL)) break;
        SREG = intr_state;
        // have we waited too long?
        if (UDFNUML == timeout) {
            previous_timeout = 1;
            return -1;
        }
        // has the USB gone offline?
        if (!usb_configuration) return -1;
        // get ready to try checking again
        intr_state = SREG;
        cli();
        UENUM = DEBUG_TX_ENDPOINT;
    }
    // actually write the byte into the FIFO
    UEDATX = c;
    // if this completed a packet, transmit it now!
    if (!(UEINTX & (1<<RWAL))) {
        UEINTX = 0x3A;
        debug_flush_timer = 0;
    } else {
        debug_flush_timer = 2;
    }
    SREG = intr_state;
    return 0;
}


// immediately transmit any buffered output.
void usb_debug_flush_output(void)
{
    uint8_t intr_state;

    intr_state = SREG;
    cli();
    if (debug_flush_timer) {
        UENUM = DEBUG_TX_ENDPOINT;
        while ((UEINTX & (1<<RWAL))) {
            UEDATX = 0;
        }
        UEINTX = 0x3A;
        debug_flush_timer = 0;
    }
    SREG = intr_state;
}



/**************************************************************************
 *
 *  Private Functions - not intended for general user consumption....
 *
 **************************************************************************/



// USB Device Interrupt - handle all device-level events
// the transmit buffer flushing is triggered by the start of frame
//
ISR(USB_GEN_vect)
{
    uint8_t intbits, t;

        intbits = UDINT;
        UDINT = 0;
        if (intbits & (1<<EORSTI)) {
        UENUM = 0;
        UECONX = 1;
        UECFG0X = EP_TYPE_CONTROL;
        UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
        UEIENX = (1<<RXSTPE);
        usb_configuration = 0;
        }
    if (intbits & (1<<SOFI)) {
        if (usb_configuration) {
            t = debug_flush_timer;
            if (t) {
                debug_flush_timer = -- t;
                if (!t) {
                    UENUM = DEBUG_TX_ENDPOINT;
                    while ((UEINTX & (1<<RWAL))) {
                        UEDATX = 0;
                    }
                    UEINTX = 0x3A;
                }
            }
        }
    }
}


// Misc functions to wait for ready and send/receive packets
static inline void usb_wait_in_ready(void)
{
    while (!(UEINTX & (1<<TXINI))) ;
}
static inline void usb_send_in(void)
{
    UEINTX = ~(1<<TXINI);
}
static inline void usb_wait_receive_out(void)
{
    while (!(UEINTX & (1<<RXOUTI))) ;
}
static inline void usb_ack_out(void)
{
    UEINTX = ~(1<<RXOUTI);
}



// USB Endpoint Interrupt - endpoint 0 is handled here.  The
// other endpoints are manipulated by the user-callable
// functions, and the start-of-frame interrupt.
//
ISR(USB_COM_vect)
{
        uint8_t intbits;
    const uint8_t *list;
        const uint8_t *cfg;
    uint8_t i, n, len, en;
    uint8_t bmRequestType;
    uint8_t bRequest;
    uint16_t wValue;
    uint16_t wIndex;
    uint16_t wLength;
    uint16_t desc_val;
    const uint8_t *desc_addr;
    uint8_t    desc_length;

        UENUM = 0;
        intbits = UEINTX;
        if (intbits & (1<<RXSTPI)) {
                bmRequestType = UEDATX;
                bRequest = UEDATX;
                wValue = UEDATX;
                wValue |= (UEDATX << 8);
                wIndex = UEDATX;
                wIndex |= (UEDATX << 8);
                wLength = UEDATX;
                wLength |= (UEDATX << 8);
                UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
                if (bRequest == GET_DESCRIPTOR) {
            list = (const uint8_t *)descriptor_list;
            for (i=0; ; i++) {
                if (i >= NUM_DESC_LIST) {
                    UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
                    return;
                }
                desc_val = pgm_read_word(list);
                if (desc_val != wValue) {
                    list += sizeof(struct descriptor_list_struct);
                    continue;
                }
                list += 2;
                desc_val = pgm_read_word(list);
                if (desc_val != wIndex) {
                    list += sizeof(struct descriptor_list_struct)-2;
                    continue;
                }
                list += 2;
                desc_addr = (const uint8_t *)pgm_read_word(list);
                list += 2;
                desc_length = pgm_read_byte(list);
                break;
            }
            len = (wLength < 256) ? wLength : 255;
            if (len > desc_length) len = desc_length;
            do {
                // wait for host ready for IN packet
                do {
                    i = UEINTX;
                } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
                if (i & (1<<RXOUTI)) return;    // abort
                // send IN packet
                n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
                for (i = n; i; i--) {
                    UEDATX = pgm_read_byte(desc_addr++);
                }
                len -= n;
                usb_send_in();
            } while (len || n == ENDPOINT0_SIZE);
            return;
                }
        if (bRequest == SET_ADDRESS) {
            usb_send_in();
            usb_wait_in_ready();
            UDADDR = wValue | (1<<ADDEN);
            return;
        }
        if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
            usb_configuration = wValue;
            usb_send_in();
            cfg = endpoint_config_table;
            for (i=1; i<5; i++) {
                UENUM = i;
                en = pgm_read_byte(cfg++);
                UECONX = en;
                if (en) {
                    UECFG0X = pgm_read_byte(cfg++);
                    UECFG1X = pgm_read_byte(cfg++);
                }
            }
                UERST = 0x1E;
                UERST = 0;
            return;
        }
        if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
            usb_wait_in_ready();
            UEDATX = usb_configuration;
            usb_send_in();
            return;
        }

        if (bRequest == GET_STATUS) {
            usb_wait_in_ready();
            i = 0;
            #ifdef SUPPORT_ENDPOINT_HALT
            if (bmRequestType == 0x82) {
                UENUM = wIndex;
                if (UECONX & (1<<STALLRQ)) i = 1;
                UENUM = 0;
            }
            #endif
            UEDATX = i;
            UEDATX = 0;
            usb_send_in();
            return;
        }
        #ifdef SUPPORT_ENDPOINT_HALT
        if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
          && bmRequestType == 0x02 && wValue == 0) {
            i = wIndex & 0x7F;
            if (i >= 1 && i <= MAX_ENDPOINT) {
                usb_send_in();
                UENUM = i;
                if (bRequest == SET_FEATURE) {
                    UECONX = (1<<STALLRQ)|(1<<EPEN);
                } else {
                    UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
                    UERST = (1 << i);
                    UERST = 0;
                }
                return;
            }
        }
        #endif
        if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
            if (wIndex == 0) {
                len = wLength;
                do {
                    // wait for host ready for IN packet
                    do {
                        i = UEINTX;
                    } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
                    if (i & (1<<RXOUTI)) return;    // abort
                    // send IN packet
                    n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
                    for (i = n; i; i--) {
                        UEDATX = 0;
                    }
                    len -= n;
                    usb_send_in();
                } while (len || n == ENDPOINT0_SIZE);
                return;
            }
        }
        }
    UECONX = (1<<STALLRQ) | (1<<EPEN);    // stall
}
 
Last edited by a moderator:
@NBPat, please use the code tags. The code is unreadable without them. I've added them to previous post.
 
Thank you, FrankB. I appreciate you adding the required code tags. How do I do it correctly in the future? Is there a guide?
I see an octothorpe character (#) in the toolbar and it says Wrap CODE tags around selected text. Do I just click one octothorpe at the start and one at the end?
When I posted it looked okay. But I did not look at it after hitting the post reply button.
 
Status
Not open for further replies.
Back
Top