Merge from preempt branch.
authorbatt <batt@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 29 Jan 2008 10:58:04 +0000 (10:58 +0000)
committerbatt <batt@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 29 Jan 2008 10:58:04 +0000 (10:58 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1071 38d2e660-2303-0410-9eaa-f027e97ec537

13 files changed:
app/at91sam7s/appconfig.h
app/at91sam7s/at91sam7s.c
app/at91sam7s/at91sam7s.mk
config.mk
config_kern.h
cpu/arm/drv/ser_at91.c
cpu/arm/drv/sysirq_at91.c
cpu/arm/hw/switch.h [new file with mode: 0644]
cpu/attr.h
cpu/irq.h
drv/timer.c
kern/monitor.c
rules.mk

index 179f5ace5cff8ea9ce8ad16fbba817c6ae2a489d..501b07764dc7b2f0b938fd8790cf6c0cb1da1433 100644 (file)
        /** Default baud rate (set to 0 to disable) */
        #define CONFIG_SER_DEFBAUDRATE   0
 
-       /** Enable ser_gets() and ser_gets_echo() */
-       #define CONFIG_SER_GETS          0
-
        /** Enable second serial port in emulator. */
        #define CONFIG_EMUL_UART1        0
 
 /// Enable smooth scrolling in menus
 #define CONFIG_MENU_SMOOTH  1
 
+/** Enable kfile_gets() and kfile_gets_echo() */
+#define CONFIG_KFILE_GETS 0
+
+/// Disable tests.
+#define CONFIG_TEST 0
+
+
 #endif /* APPCONFIG_COMMON_H */
index dc52b23c22e5183feee384774e571d06c543c74b..29cd9907f722bfd9b1ee42e5c5e1a3f7257204f3 100644 (file)
@@ -46,6 +46,7 @@
 #include <io/arm.h>
 
 Timer leds_timer;
+KFileSerial ser_fd;
 
 static void leds_toggle(void)
 {
@@ -79,12 +80,10 @@ int main(void)
        proc_init();
        ASSERT(!IRQ_ENABLED());
 
-
-
        /* Open the main communication port */
-       Serial *host_port = ser_open(0);
-       ser_setbaudrate(host_port, 115200);
-       ser_setparity(host_port, SER_PARITY_NONE);
+       ser_init(&ser_fd, 0);
+       ser_setbaudrate(&ser_fd, 115200);
+       ser_setparity(&ser_fd, SER_PARITY_NONE);
 
 
        IRQ_ENABLE;
@@ -112,7 +111,7 @@ int main(void)
        for(;;)
        {
                proc_test();
-               ser_printf(host_port, "From serial 0: %s\r\n", msg);
+               kfile_printf(&ser_fd.fd, "From serial 0: %s\r\n", msg);
        }
        return 0;
 }
index bfa4795718687f40fc8ff83a3af74953e8934c49..e346ceb0e53a8aa526a495daaf7b3fb277b826bc 100644 (file)
@@ -9,7 +9,6 @@
 #
 #
 
-
 # Set to 1 for debug builds
 at91sam7s_DEBUG = 1
 
@@ -25,18 +24,21 @@ at91sam7s_CSRC = \
        mware/event.c \
        mware/formatwr.c \
        mware/hex.c \
+       kern/kfile.c \
        kern/proc.c \
        kern/proc_test.c \
        kern/monitor.c \
-       kern/signal.c \
+       kern/signal.c
 
 at91sam7s_CPPASRC = \
-       cpu/arm/hw/crtat91sam7s256_rom.S \
+       cpu/arm/hw/crtat91sam7_rom.S \
        kern/switch_arm.S
 
+at91sam7s_CROSS = arm-elf-
+
 at91sam7s_CPPAFLAGS = -O0 -g -gdwarf-2 -g -gen-debug
 at91sam7s_CPPFLAGS = -O0 -D'ARCH=0' -D__ARM_AT91SAM7S256__ -g3 -gdwarf-2 -fverbose-asm -Iapp/at91sam7s/hw -Iapp/at91sam7s -Icpu/arm
-at91sam7s_LDFLAGS = -nostartfiles -T cpu/arm/scripts/at91sam7s256_ram.ld -Wl,--no-warn-mismatch
+at91sam7s_LDFLAGS = -nostartfiles -T cpu/arm/scripts/at91sam7_256_ram.ld -Wl,--no-warn-mismatch
 
 at91sam7s_CPU = arm7tdmi
 
index a3fd6417829ee1321b5698accb83eb0347ed9110..8c857e4372402a2cedffa1f4954ec1e2cbac0b3c 100644 (file)
--- a/config.mk
+++ b/config.mk
@@ -49,13 +49,13 @@ DEBUGCFLAGS = -ggdb
 #
 # define some variables based on the AVR base path in $(AVR)
 #
-CROSS   = avr-
-CC      = $(CROSS)gcc
-CXX     = $(CROSS)g++
+#CROSS   = avr-
+CC      = gcc
+CXX     = g++
 AS      = $(CC) -x assembler-with-cpp
 LD      = $(CC)
-OBJCOPY = $(CROSS)objcopy
-STRIP   = $(CROSS)strip
+OBJCOPY = objcopy
+STRIP   = strip
 INSTALL = cp -a
 RM      = rm -f
 RM_R    = rm -rf
index 1edbabe9dc389952ec577edca23635638efd86b9..2dcbae90c4eceec7c3e64d87b7d25f0821a7b6fb 100644 (file)
         * usage.
         */
        #define CONFIG_PROC_DEFSTACKSIZE  \
-           (CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
+           (CPU_SAVED_REGS_CNT * 2 * sizeof(cpustack_t) \
            + 32 * sizeof(int))
 #endif
 
 
 /* Memory fill codes to help debugging */
 #if CONFIG_KERN_MONITOR
-       #define CONFIG_KERN_STACKFILLCODE  0xA5A5
-       #define CONFIG_KERN_MEMFILLCODE    0xDBDB
+       #include <cpu/types.h>
+       #if (SIZEOF_CPUSTACK_T == 1)
+               /* 8bit cpustack_t */
+               #define CONFIG_KERN_STACKFILLCODE  0xA5
+               #define CONFIG_KERN_MEMFILLCODE    0xDB
+       #elif (SIZEOF_CPUSTACK_T == 2)
+               /* 16bit cpustack_t */
+               #define CONFIG_KERN_STACKFILLCODE  0xA5A5
+               #define CONFIG_KERN_MEMFILLCODE    0xDBDB
+       #elif (SIZEOF_CPUSTACK_T == 4)
+               /* 16bit cpustack_t */
+               #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5UL
+               #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBUL
+       #else
+               #error No cpustack_t size supported!
+       #endif
 #endif
 
 
index 9f3ed4b9f1ac64a75bb0f7237b737c29cc6b25ef..37a4f1b695470b281c1e61188d32159bd5928a3c 100644 (file)
@@ -703,18 +703,17 @@ static void uart0_irq_rx(void)
 /**
  * Serial IRQ dispatcher for USART0.
  */
-static void uart0_irq_dispatcher(void) __attribute__ ((naked));
+static void uart0_irq_dispatcher(void) __attribute__ ((interrupt));
 static void uart0_irq_dispatcher(void)
 {
-       IRQ_ENTRY();
-
        if (US0_CSR & BV(US_RXRDY))
                uart0_irq_rx();
 
        if (US0_CSR & BV(US_TXRDY))
                uart0_irq_tx();
 
-       IRQ_EXIT();
+       /* Inform hw that we have served the IRQ */
+       AIC_EOICR = 0;
 }
 
 /**
@@ -764,16 +763,15 @@ static void uart1_irq_rx(void)
 /**
  * Serial IRQ dispatcher for USART1.
  */
-static void uart1_irq_dispatcher(void) __attribute__ ((naked));
+static void uart1_irq_dispatcher(void) __attribute__ ((interrupt));
 static void uart1_irq_dispatcher(void)
 {
-       IRQ_ENTRY();
-
        if (US1_CSR & BV(US_RXRDY))
                uart1_irq_rx();
 
        if (US1_CSR & BV(US_TXRDY))
                uart1_irq_tx();
 
-       IRQ_EXIT();
+       /* Inform hw that we have served the IRQ */
+       AIC_EOICR = 0;
 }
index 33e6b0cd21fb56de666624566f3ba3acb0532d2a..281c7963f8afdbee1fb0fc472ca961a3171cd921 100644 (file)
@@ -94,10 +94,9 @@ STATIC_ASSERT(countof(sysirq_tab) == SYSIRQ_CNT);
  * various sources (system timer, etc..) and calls
  * the corresponding handler.
  */
-static void sysirq_dispatcher(void) __attribute__ ((naked));
+static void sysirq_dispatcher(void) __attribute__ ((interrupt));
 static void sysirq_dispatcher(void)
 {
-       IRQ_ENTRY();
        for (unsigned i = 0; i < countof(sysirq_tab); i++)
        {
                if (sysirq_tab[i].enabled
@@ -105,7 +104,8 @@ static void sysirq_dispatcher(void)
                        sysirq_tab[i].handler();
        }
 
-       IRQ_EXIT();
+       /* Inform hw that we have served the IRQ */
+       AIC_EOICR = 0;
 }
 
 #define SYSIRQ_PRIORITY 0 ///< default priority for system irqs.
diff --git a/cpu/arm/hw/switch.h b/cpu/arm/hw/switch.h
new file mode 100644 (file)
index 0000000..9ed15b9
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2008 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief Kernel scheduler macros.
+ *
+ * \version $Id$
+ *
+ * \author Francesco Sacchi <batt@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
+ */
+
+#ifndef CPU_ARM_HW_SWITCH_H
+#define CPU_ARM_HW_SWITCH_H
+
+#include <kern/proc_p.h>
+
+/**
+ * Interrupt entry point.
+ * Needed because AT91 uses an Interrupt Controller with auto-vectoring.
+ */
+#define SCHEDULER_IRQ_ENTRY \
+       asm volatile("sub   lr, lr, #4          \n\t"  /* Adjust LR */ \
+                    "stmfd sp!, {r0}           \n\t"  /* Save r0 */ \
+                    "stmfd sp, {sp}^           \n\t"  /* Save user SP */ \
+                    "sub   sp, sp, #4          \n\t"  /* Decrement irq SP, writeback is illegal */ \
+                    "ldmfd sp!, {r0}           \n\t"  /* Restore user SP immedately in r0 */ \
+                    "stmfd r0!, {lr}           \n\t"  /* Store system LR in user stack */ \
+                    "stmfd r0, {r1-r12,lr}^    \n\t"  /* Store registers on user stack (user LR too) */ \
+                    "sub   r0, r0, #52         \n\t"  /* Decrement r0, writeback is illegal */ \
+                    "ldmfd sp!, {r1}           \n\t"  /* Restore r0 */ \
+                    "stmfd r0!, {r1}           \n\t"  /* Store r0 in user stack too */ \
+                    "mrs   r1, spsr            \n\t"  /* Save SPSR... */ \
+                    "stmfd r0!, {r1}           \n\t"  /*  ... in user stack */ \
+                    "ldr   r1, =CurrentProcess \n\t"  /* Load in r1 &CurrentProcess->stack */ \
+                    "ldr   r1, [r1, %0]        \n\t"  \
+                    "str   r0, [r1]            \n\t"  /* Store the process SP */ \
+                    "sub   fp, sp, #4          \n\t"  /* Store the process SP */ \
+                    : /* no output */ \
+                    : "n" (offsetof(Process, stack)) \
+       )
+
+
+#define SCHEDULER_IRQ_EXIT \
+       asm volatile("ldr   lr, =CurrentProcess \n\t"  /* Load &CurrentProcess->stack */ \
+                    "ldr   lr, [lr, %0]        \n\t"  \
+                    "ldr   lr, [lr]            \n\t"  /* Load current process SP */ \
+                    "ldr   r0, =0xFFFFF000     \n\t"  /* End of interrupt for AT91 */ \
+                    "str   r0, [r0, #0x130]    \n\t"  /* */ \
+                    "ldmfd lr!, {r0}           \n\t"  /* Pop status reg */ \
+                    "msr   spsr, r0            \n\t"  /* ... */ \
+                    "ldmfd lr, {r0-r12,lr}^    \n\t"  /* Restore user regs */ \
+                    "add   lr, lr, #56         \n\t"  /* 52 + irq link register (extracted below) */ \
+                    "stmfd sp!, {lr}           \n\t"  /* Push user stack pointer in irq stack */ \
+                    "ldmfd sp,  {sp}^          \n\t"  /* Restore user SP */ \
+                    "sub   sp, sp, #4          \n\t"  /* Align irq SP */ \
+                    "ldmdb lr, {pc}^           \n\t"  /* And return to user space (We use ldmdb cause lr is sp+4) */ \
+                    : /* no output */ \
+                    : "n" (offsetof(Process, stack))  \
+       )
+
+#endif /* CPU_ARM_HW_SWITCH_H */
index 497f899700d2712816480bd0792a53c4fd177dd9..891f00fdbfe013104ec4297d8dbb2496661a3a91 100644 (file)
        #define CPU_SAVED_REGS_CNT     9
        #define CPU_STACK_GROWS_UPWARD 0
        #define CPU_SP_ON_EMPTY_SLOT   0
-       #define CPU_BYTE_ORDER         (__BIG_ENDIAN__ ? CPU_BIG_ENDIAN : CPU_LITTLE_ENDIAN)
+       #warning Find a way to detect endianess at runtime
+       #define CPU_BYTE_ORDER         CPU_LITTLE_ENDIAN
        #define CPU_HARVARD            0
 
        #ifdef __IAR_SYSTEMS_ICC__
index 438387091dd215bf7d595599ddd8052b1d1aefe1..15609d76363d78ff7642dc78979f9200779589ed 100644 (file)
--- a/cpu/irq.h
+++ b/cpu/irq.h
 
                #define IRQ_ENABLED() ((CPU_READ_FLAGS() & 0xc0) != 0xc0)
 
-               /**
-                * Interrupt entry point.
-                * Needed because AT91 uses an Interrupt Controller with auto-vectoring.
-                */
-               #define IRQ_ENTRY() \
-                       asm volatile("sub   lr, lr, #4"         "\n\t"  /* Adjust LR */ \
-                                    "stmfd sp!, {r0-r12,lr}"   "\n\t"  /* Save registers on IRQ stack. */ \
-                                    "mrs   r1, spsr"           "\n\t"  /* Save SPSR */ \
-                                    "stmfd sp!, {r1}"          "\n\t")     /* */
-
-               /**
-                * Interrupt exit.
-                * Needed because AT91 uses an Interrupt Controller with auto-vectoring.
-                */
-               #define IRQ_EXIT() \
-                       asm volatile("ldmfd sp!, {r1}"          "\n\t"  /* Restore SPSR */ \
-                                    "msr   spsr_c, r1"         "\n\t"  /* */ \
-                                    "ldr   r0, =0xFFFFF000"    "\n\t"  /* End of interrupt. */ \
-                                    "str   r0, [r0, #0x130]"   "\n\t"  /* */ \
-                                    "ldmfd sp!, {r0-r12, pc}^" "\n\t")     /* Restore registers and return. */
-
        #endif /* !__IAR_SYSTEMS_ICC_ */
 
 #elif CPU_PPC
        #define IRQ_ENABLE          FIXME
        #define IRQ_SAVE_DISABLE(x) FIXME
        #define IRQ_RESTORE(x)      FIXME
-       #define IRQ_ENABLED()      FIXME
+       #define IRQ_ENABLED()       FIXME
 
 #elif CPU_DSP56K
 
index a71352676ba789cd7e07696e1985c34c19e4b619..3805e3b0189f9c846738151de8e2a8b658076c57 100644 (file)
@@ -74,6 +74,7 @@
 
 #if CONFIG_KERNEL
        #include <config_kern.h>
+       #include <hw/switch.h>
        #if CONFIG_KERN_SIGNALS
                #include <kern/signal.h> /* sig_wait(), sig_check() */
                #include <kern/proc.h>   /* proc_current() */
@@ -262,6 +263,8 @@ void timer_delayHp(hptime_t delay)
  */
 DEFINE_TIMER_ISR
 {
+       SCHEDULER_IRQ_ENTRY;
+
        /*
         * With the Metrowerks compiler, the only way to force the compiler generate
         * an interrupt service routine is to put a pragma directive within the function
@@ -279,7 +282,7 @@ DEFINE_TIMER_ISR
         * to ensure that IRQ is generated by timer source.
         */
        if (!timer_hw_triggered())
-               return;
+               SCHEDULER_IRQ_EXIT;
 
        TIMER_STROBE_ON;
 
@@ -313,6 +316,8 @@ DEFINE_TIMER_ISR
 #endif /* CONFIG_TIMER_DISABLE_EVENTS */
 
        TIMER_STROBE_OFF;
+
+       SCHEDULER_IRQ_EXIT;
 }
 
 MOD_DEFINE(timer)
index d19b4bdc3ba481b3da1b076b1a74a63b2b4001ed..96b563e1830ff3bc852a8883d80a89bb1581ad46 100644 (file)
@@ -138,7 +138,7 @@ void monitor_report(void)
                 p = MONITOR_NODE_TO_PROCESS(p->monitor.link.succ))
        {
                size_t free = monitor_checkStack(p->monitor.stack_base, p->monitor.stack_size);
-               kprintf("%-24s%-8p%-8p%-8u%-8u\n",
+               kprintf("%-24s%-8p%-8p%-8lu%-8lu\n",
                        p->monitor.name, p, p->monitor.stack_base, p->monitor.stack_size, free);
        }
 }
index 1289740f2471f30d4b225310cd8b4b88bed0be65..e395f053c31cabed468674357d1b3458f57b0d1a 100644 (file)
--- a/rules.mk
+++ b/rules.mk
@@ -83,6 +83,11 @@ ifneq ($$(strip $$($(1)_LDSCRIPT)),)
 $(1)_LDFLAGS += -Wl,-T$$($(1)_LDSCRIPT)
 endif
 
+$(1)_CC      = $$($(1)_CROSS)$$(CC)
+$(1)_CXX     = $$($(1)_CROSS)$$(CXX)
+$(1)_AS      = $$($(1)_CROSS)$$(AS)
+$(1)_OBJCOPY = $$($(1)_CROSS)$$(OBJCOPY)
+
 $(1)_COBJ    = $$(foreach file,$$($(1)_CSRC:%.c=%.o),$$(OBJDIR)/$(1)/$$(file))
 $(1)_CXXOBJ  = $$(foreach file,$$($(1)_CXXSRC:%.cpp=%.o),$$(OBJDIR)/$(1)/$$(file))
 $(1)_PCOBJ   = $$(foreach file,$$($(1)_PCSRC:%.c=%_P.o),$$(OBJDIR)/$(1)/$$(file))
@@ -92,58 +97,64 @@ $(1)_OBJ    := $$($(1)_COBJ) $$($(1)_CXXOBJ) $$($(1)_PCOBJ) $$($(1)_AOBJ) $$($(1
 $(1)_SRC    := $$($(1)_CSRC) $$($(1)_CXXSRC) $$($(1)_PCSRC) $$($(1)_ASRC) $$($(1)_CPPASRC)
 OBJ         += $$($(1)_OBJ)
 
+ifneq ($$(strip $$($(1)_CXXSRC)),)
+$(1)_LD = $$($(1)_CROSS)$$(LDXX)
+else
+$(1)_LD = $$($(1)_CROSS)$$(LD)
+endif
+
 # Compile: instructions to create assembler and/or object files from C source
 $$($(1)_COBJ) : $$(OBJDIR)/$(1)/%.o : %.c
        $L "$(1): Compiling $$< (C)"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(CC) -c $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
+       $Q $$($(1)_CC) -c $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
 
 # Compile: instructions to create assembler and/or object files from C++ source
 $$($(1)_CXXOBJ) : $$(OBJDIR)/$(1)/%.o : %.cpp
        $L "$(1): Compiling $$< (C++)"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(CXX) -c $$(CXXFLAGS) $$($(1)_CXXFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
+       $Q $$($(1)_CXX) -c $$(CXXFLAGS) $$($(1)_CXXFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
 
 # Generate assembly sources from C files (debug)
 $$(OBJDIR)/$(1)/%.s : %.c
        $L "$(1): Generating asm source $$<"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(CC) -S $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$< -o $$@
+       $Q $$($(1)_CC) -S $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$< -o $$@
 
 # Generate special progmem variant of a source file
 $$($(1)_PCOBJ) : $$(OBJDIR)/$(1)/%_P.o : %.c
        $L "$(1): Compiling $$< (PROGMEM)"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(CC) -c -D_PROGMEM $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
+       $Q $$($(1)_CC) -c -D_PROGMEM $$(CFLAGS) $$($(1)_CFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
 
 # Assemble: instructions to create object file from assembler files
 $$($(1)_AOBJ): $$(OBJDIR)/$(1)/%.o : %.s
        $L "$(1): Assembling $$<"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(AS) -c $$(ASFLAGS) $$($(1)_ASFLAGS) $$< -o $$@
+       $Q $$($(1)_AS) -c $$(ASFLAGS) $$($(1)_ASFLAGS) $$< -o $$@
 
 $$($(1)_CPPAOBJ): $$(OBJDIR)/$(1)/%.o : %.S
        $L "$(1): Assembling with CPP $$<"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(CC) -c $$(CPPAFLAGS) $$($(1)_CPPAFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
+       $Q $$($(1)_CC) -c $$(CPPAFLAGS) $$($(1)_CPPAFLAGS) $$($(1)_CPPFLAGS) $$(CPPFLAGS) $$< -o $$@
        
 
 # Link: instructions to create elf output file from object files
 $$(OUTDIR)/$(1).elf $$(OUTDIR)/$(1)_nostrip: bumprev $$($(1)_OBJ) $$($(1)_LDSCRIPT)
        $L "$(1): Linking $$@"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(LD) $$($(1)_OBJ) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@
+       $Q $$($(1)_LD) $$($(1)_OBJ) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@
 
 # Strip debug info
 $$(OUTDIR)/$(1): $$(OUTDIR)/$(1)_nostrip
        $L "$(1): Generating stripped executable $$@"
-       $Q $$(STRIP) -o $$@ $$^
+       $Q $$($(1)_STRIP) -o $$@ $$^
  
 # Compile and link (program-at-a-time)
 $$(OUTDIR)/$(1)_whole.elf: bumprev $$($(1)_SRC) $$($(1)_LDSCRIPT)
        $L "$(1): Compiling and Linking whole program $$@"
        @$$(MKDIR_P) $$(dir $$@)
-       $Q $$(CC) $$($(1)_SRC) $$(CFLAGS) $$($(1)_CFLAGS) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@
+       $Q $$($(1)_CC) $$($(1)_SRC) $$(CFLAGS) $$($(1)_CFLAGS) $$(LIB) $$(LDFLAGS) $$($(1)_LDFLAGS) -o $$@
 
 # Flash target
 # NOTE: we retry in case of failure because the STK500 programmer is crappy
@@ -179,6 +190,23 @@ fuses_$(1):
                     $(AVRDUDE) $(DPROG) -p $$($(1)_MCU) -U lock:w:$$($(1)_lock):m ; \
                fi \
        fi
+
+$$(OUTDIR)/$(1).hex: $$(OUTDIR)/$(1).elf
+       $$($(1)_OBJCOPY) -O ihex $$< $$@
+
+$$(OUTDIR)/$(1).s19: $$(OUTDIR)/$(1).elf
+       $$($(1)_OBJCOPY) -O srec $$< $$@
+
+$$(OUTDIR)/$(1).bin: $$(OUTDIR)/$(1).elf
+       $$($(1)_OBJCOPY) -O binary $$< $$@
+
+$$(OUTDIR)/$(1).obj: $$(OUTDIR)/$(1).elf
+       $$($(1)_OBJCOPY) -O avrobj $$< $$@
+
+$$(OUTDIR)/$(1).rom: $$(OUTDIR)/$(1).elf
+       $$($(1)_OBJCOPY) -O $$(FORMAT) $$< $$@
+#      $$($(1)_OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" -O $$(FORMAT) $$< $$(@:.rom=.eep)
+
 endef
 
 # Generate build rules for all targets
@@ -194,21 +222,6 @@ $(foreach t,$(TRG),$(eval $(call build_target,$(t))))
                exit 1; \
        fi
 
-%.hex: %.elf
-       $(OBJCOPY) -O ihex $< $@
-
-%.s19: %.elf
-       $(OBJCOPY) -O srec $< $@
-
-%.bin: %.elf
-       $(OBJCOPY) -O binary $< $@
-
-%.obj: %.elf
-       $(OBJCOPY) -O avrobj $< $@
-
-%.rom: %.elf
-       $(OBJCOPY) -O $(FORMAT) $< $@
-#      $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" -O $(FORMAT) $< $(@:.rom=.eep)
 
 %.cof: %.elf
        $(COFFCONVERT) -O coff-ext-avr $< $@