Browse Source

AT91SAM9260 branch
1. Support Keil MDK development environment
2. Modify EMAC driver according to the changes of lwIP API in reversion 1668 and 1669

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1681 bbd45198-f89e-11dd-88c7-29a3b14d5316

luohui2320@gmail.com 13 years ago
parent
commit
da74af2347

+ 11 - 2
bsp/at91sam9260/application.c

@@ -32,6 +32,16 @@
 #endif
 #endif
 
+#if defined(RT_USING_DFS_DEVFS)
+#include <devfs.h>
+#endif
+
+#ifdef RT_USING_LWIP
+#include <netif/ethernetif.h>
+#include <arch/sys_arch_init.h>
+#include "macb.h"
+#endif
+
 #ifdef RT_USING_LED
 #include "led.h"
 #endif
@@ -90,6 +100,7 @@ void rt_init_thread_entry(void* parameter)
 			rt_kprintf("UFFS File System initialzation failed!\n");
 	}
 #endif
+
 	}
 #endif
 
@@ -98,8 +109,6 @@ void rt_init_thread_entry(void* parameter)
 		/* register ethernetif device */
 		eth_system_device_init();
 		rt_hw_macb_init();
-		/* re-init device driver */
-		rt_device_init_all();
 		/* init lwip system */
 		lwip_sys_init();
 		rt_kprintf("TCP/IP initialized!\n");

+ 15 - 16
bsp/at91sam9260/macb.c

@@ -68,7 +68,7 @@ struct rt_macb_eth
 	/* inherit from ethernet device */
 	struct eth_device parent;
 
-	void			*regs;
+	unsigned int		regs;
 
 	unsigned int		rx_tail;
 	unsigned int		tx_head;
@@ -213,9 +213,9 @@ static rt_uint16_t macb_mdio_read(struct rt_macb_eth *macb, rt_uint8_t reg)
 
 static void macb_phy_reset(rt_device_t dev)
 {
-	struct rt_macb_eth *macb = dev->user_data;;
 	int i;
 	rt_uint16_t status, adv;
+	struct rt_macb_eth *macb = dev->user_data;;
 
 	adv = ADVERTISE_CSMA | ADVERTISE_ALL;
 	macb_mdio_write(macb, MII_ADVERTISE, adv);
@@ -322,13 +322,15 @@ void macb_update_link(struct rt_macb_eth *macb)
 				 ? 100 : 10);
 			macb->duplex = (media & ADVERTISE_FULL) ? 1 : 0;
 			rt_kprintf("%s: link up (%dMbps/%s-duplex)\n",
-			       dev->parent.name, macb->speed,
-			       DUPLEX_FULL == macb->duplex ? "Full":"Half");
-			netif_set_link_up(macb->parent.netif);
+					dev->parent.name, macb->speed,
+					DUPLEX_FULL == macb->duplex ? "Full":"Half");
+			macb->parent.link_status = 1;
 		} else {
 			rt_kprintf("%s: link down\n", dev->parent.name);
-			netif_set_link_down(macb->parent.netif);
+					macb->parent.link_status = 0;
 		}
+
+		eth_device_linkchange(&macb->parent, RT_TRUE);
 	}
 
 }
@@ -458,13 +460,11 @@ static rt_err_t rt_macb_control(rt_device_t dev, rt_uint8_t cmd, void *args)
 /* transmit packet. */
 rt_err_t rt_macb_tx( rt_device_t dev, struct pbuf* p)
 {
-	struct rt_macb_eth *macb = dev->user_data;
 	struct pbuf* q;
-	rt_uint32_t len;
 	rt_uint8_t* bufptr, *buf = RT_NULL;
-	unsigned long paddr, ctrl;
+	unsigned long ctrl;
+	struct rt_macb_eth *macb = dev->user_data;
 	unsigned int tx_head = macb->tx_head;
-	int i;
 	
 	/* lock macb device */
 	rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
@@ -500,7 +500,6 @@ rt_err_t rt_macb_tx( rt_device_t dev, struct pbuf* p)
 	/* wait ack */
 	rt_sem_take(&sem_ack, RT_WAITING_FOREVER);
 	rt_free(buf);
-	buf == RT_NULL;
 
 	return RT_EOK;
 }
@@ -555,7 +554,7 @@ struct pbuf *rt_macb_rx(rt_device_t dev)
 		}
 
 		if (status & RXBUF_FRAME_END) {
-			buffer = macb->rx_buffer + 128 * macb->rx_tail;
+			buffer = (void *)((unsigned int)macb->rx_buffer + 128 * macb->rx_tail);
 			len = status & RXBUF_FRMLEN_MASK;
 			p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
 			if (!p)
@@ -579,14 +578,14 @@ struct pbuf *rt_macb_rx(rt_device_t dev)
 				taillen = len - headlen;
 				memcpy((void *)buf,
 				       buffer, headlen);
-				memcpy((void *)buf + headlen,
+				memcpy((void *)((unsigned int)buf + headlen),
 				       macb->rx_buffer, taillen);
 				buffer = (void *)buf;
 				for (q = p; q != RT_NULL; q= q->next)
 				{
 					/* read data from device */
 					memcpy((void *)q->payload, buffer, q->len);
-					buffer += q->len;
+					buffer = (void *)((unsigned int)buffer + q->len);
 				}
 				rt_free(buf);
 				buf = RT_NULL;
@@ -595,7 +594,7 @@ struct pbuf *rt_macb_rx(rt_device_t dev)
 				{
 					/* read data from device */
 					memcpy((void *)q->payload, buffer, q->len);
-					buffer += q->len;
+					buffer = (void *)((unsigned int)buffer + q->len);
 				}
 			
 			}
@@ -643,7 +642,7 @@ void macb_initialize()
 	macb->rx_ring_dma = (unsigned long)macb->rx_ring;
 	macb->tx_ring_dma = (unsigned long)macb->tx_ring;
 
-	macb->regs = (void *)AT91SAM9260_BASE_EMAC;
+	macb->regs = AT91SAM9260_BASE_EMAC;
 	macb->phy_addr = 0x00;
 	
 	/*

+ 1 - 0
bsp/at91sam9260/macb.h

@@ -330,6 +330,7 @@ struct dma_desc {
 #define MACB_TX_USED_OFFSET			31
 #define MACB_TX_USED_SIZE			1
 
+void rt_hw_macb_init();
 
 #endif /* _MACB_H */
 

+ 1 - 1
bsp/at91sam9260/mii.h

@@ -158,7 +158,7 @@
  * 100T4 this is fine.  If your phy places 100T4 elsewhere in the
  * priority order, you will need to roll your own function.
  */
-static inline unsigned int mii_nway_result (unsigned int negotiated)
+rt_inline unsigned int mii_nway_result (unsigned int negotiated)
 {
         unsigned int ret;
 

+ 13 - 0
bsp/at91sam9260/startup.c

@@ -20,12 +20,17 @@
 #include <finsh.h>
 #endif
 
+#ifdef RT_USING_DEVICE
+#include <serial.h>
+#endif
+
 extern void rt_hw_interrupt_init(void);
 extern void rt_hw_board_init(void);
 extern void rt_serial_init(void);
 extern void rt_system_timer_init(void);
 extern void rt_system_scheduler_init(void);
 extern void rt_thread_idle_init(void);
+extern void mmu_invalidate_icache();
 extern void rt_hw_cpu_icache_enable(void);
 extern void rt_show_version(void);
 extern void rt_system_heap_init(void*, void*);
@@ -174,4 +179,12 @@ void rtthread_startup(void)
 	return ;
 }
 
+int main(void)
+{
+	/* startup RT-Thread RTOS */
+	rtthread_startup();
+
+	return 0;
+}
+
 /*@}*/

+ 4 - 0
libcpu/arm/at91sam926x/at91sam926x.h

@@ -203,6 +203,10 @@ struct rt_hw_register
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
+extern struct clk *clk_get(const char *id);
+extern rt_uint32_t clk_get_rate(struct clk *clk);
+extern void rt_hw_clock_init(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 107 - 0
libcpu/arm/at91sam926x/context_rvds.S

@@ -0,0 +1,107 @@
+;/*
+; * File      : context_rvds.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006, RT-Thread Development Team
+; *
+; * The license and distribution terms for this file may be
+; * found in the file LICENSE in this distribution or at
+; * http://www.rt-thread.org/license/LICENSE
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; * 2011-08-14     weety    copy from mini2440
+; */
+
+NOINT	EQU		0xc0	; disable interrupt in psr
+
+	AREA |.text|, CODE, READONLY, ALIGN=2
+	ARM
+	REQUIRE8
+	PRESERVE8
+
+;/*
+; * rt_base_t rt_hw_interrupt_disable();
+; */
+rt_hw_interrupt_disable	PROC
+	EXPORT rt_hw_interrupt_disable
+	MRS r0, cpsr
+	ORR r1, r0, #NOINT
+	MSR cpsr_c, r1
+	BX	lr
+	ENDP
+
+;/*
+; * void rt_hw_interrupt_enable(rt_base_t level);
+; */
+rt_hw_interrupt_enable	PROC
+	EXPORT rt_hw_interrupt_enable
+	MSR cpsr_c, r0
+	BX	lr
+	ENDP
+
+;/*
+; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+; * r0 --> from
+; * r1 --> to
+; */
+rt_hw_context_switch	PROC
+	EXPORT rt_hw_context_switch
+	STMFD	sp!, {lr}			; push pc (lr should be pushed in place of PC)
+	STMFD	sp!, {r0-r12, lr}	; push lr & register file
+
+	MRS		r4, cpsr
+	STMFD	sp!, {r4}			; push cpsr
+	MRS		r4, spsr
+	STMFD	sp!, {r4}			; push spsr
+
+	STR	sp, [r0]				; store sp in preempted tasks TCB
+	LDR	sp, [r1]				; get new task stack pointer
+
+	LDMFD	sp!, {r4}			; pop new task spsr
+	MSR	spsr_cxsf, r4
+	LDMFD	sp!, {r4}			; pop new task cpsr
+	MSR	cpsr_cxsf, r4
+
+	LDMFD	sp!, {r0-r12, lr, pc}	; pop new task r0-r12, lr & pc
+	ENDP
+
+;/*
+; * void rt_hw_context_switch_to(rt_uint32 to);
+; * r0 --> to
+; */
+rt_hw_context_switch_to	PROC
+	EXPORT rt_hw_context_switch_to
+	LDR	sp, [r0]				; get new task stack pointer
+
+	LDMFD	sp!, {r4}			; pop new task spsr
+	MSR	spsr_cxsf, r4
+	LDMFD	sp!, {r4}			; pop new task cpsr
+	MSR	cpsr_cxsf, r4
+
+	LDMFD	sp!, {r0-r12, lr, pc}	; pop new task r0-r12, lr & pc
+	ENDP
+
+;/*
+; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
+; */
+	IMPORT rt_thread_switch_interrput_flag
+	IMPORT rt_interrupt_from_thread
+	IMPORT rt_interrupt_to_thread
+
+rt_hw_context_switch_interrupt	PROC
+	EXPORT rt_hw_context_switch_interrupt
+	LDR r2, =rt_thread_switch_interrput_flag
+	LDR r3, [r2]
+	CMP r3, #1
+	BEQ _reswitch
+	MOV r3, #1							; set rt_thread_switch_interrput_flag to 1
+	STR r3, [r2]
+	LDR r2, =rt_interrupt_from_thread	; set rt_interrupt_from_thread
+	STR r0, [r2]
+_reswitch
+	LDR r2, =rt_interrupt_to_thread		; set rt_interrupt_to_thread
+	STR r1, [r2]
+	BX	lr
+	ENDP
+
+	END

+ 2 - 1
libcpu/arm/at91sam926x/gpio.h

@@ -1,6 +1,7 @@
 #ifndef __GPIO_H__
 #define __GPIO_H__
 
+#include <rtthread.h>
 #include <at91_aic.h>
 
 #define PIN_BASE		AIC_IRQS
@@ -111,7 +112,7 @@
 #define	AT91_PIN_PC31	(PIN_BASE + 0x40 + 31)
 
 
-static inline rt_uint32_t gpio_to_irq(rt_uint32_t gpio)
+rt_inline rt_uint32_t gpio_to_irq(rt_uint32_t gpio)
 {
 	return gpio;
 }

+ 6 - 1
libcpu/arm/at91sam926x/interrupt.c

@@ -76,6 +76,9 @@ static rt_uint32_t at91sam9260_default_irq_priority[MAX_HANDLERS] = {
  */
 /*@{*/
 
+void rt_hw_interrupt_mask(int irq);
+void rt_hw_interrupt_umask(int irq);
+
 rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector)
 {
 	rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
@@ -102,7 +105,7 @@ rt_isr_handler_t at91_gpio_irq_handle(rt_uint32_t vector)
 		irq_n = AIC_IRQS + 32*2;
 	}
 	else
-		return;
+		return RT_NULL;
 	isr = at91_sys_read(pio+PIO_ISR) & at91_sys_read(pio+PIO_IMR);
 	while (isr) 
 	{
@@ -113,6 +116,8 @@ rt_isr_handler_t at91_gpio_irq_handle(rt_uint32_t vector)
 		isr >>= 1;
 		irq_n++;
 	}
+
+	return RT_NULL;
 }
 
 /*

+ 4 - 4
libcpu/arm/at91sam926x/io.h

@@ -28,16 +28,16 @@
 #define writel(v,a)	(*(volatile unsigned int   *)(a) = (v))
 
 
-static inline unsigned int at91_sys_read(unsigned int reg_offset)
+rt_inline unsigned int at91_sys_read(unsigned int reg_offset)
 {
-	void  *addr = (void  *)AT91_BASE_SYS;
+	unsigned int  addr = AT91_BASE_SYS;
 
 	return readl(addr + reg_offset);
 }
 
-static inline void at91_sys_write(unsigned int reg_offset, unsigned long value)
+rt_inline void at91_sys_write(unsigned int reg_offset, unsigned long value)
 {
-	void *addr = (void *)AT91_BASE_SYS;
+	unsigned int addr = AT91_BASE_SYS;
 
 	writel(value, addr + reg_offset);
 }

+ 315 - 0
libcpu/arm/at91sam926x/start_rvds.S

@@ -0,0 +1,315 @@
+;/*
+; * File      : start_rvds.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006, RT-Thread Development Team
+; *
+; * The license and distribution terms for this file may be
+; * found in the file LICENSE in this distribution or at
+; * http://www.rt-thread.org/license/LICENSE
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; * 2011-08-14     weety      first version
+; */
+
+
+; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
+
+Mode_USR        EQU     0x10
+Mode_FIQ        EQU     0x11
+Mode_IRQ        EQU     0x12
+Mode_SVC        EQU     0x13
+Mode_ABT        EQU     0x17
+Mode_UND        EQU     0x1B
+Mode_SYS        EQU     0x1F
+
+SVCMODE         EQU   		0x13
+MODEMASK        EQU   		0x1f
+
+I_Bit           EQU     0x80            ; when I bit is set, IRQ is disabled
+F_Bit           EQU     0x40            ; when F bit is set, FIQ is disabled
+
+
+;----------------------- Stack and Heap Definitions ----------------------------
+
+;// <h> Stack Configuration (Stack Sizes in Bytes)
+;//   <o0> Undefined Mode      <0x0-0xFFFFFFFF:8>
+;//   <o1> Supervisor Mode     <0x0-0xFFFFFFFF:8>
+;//   <o2> Abort Mode          <0x0-0xFFFFFFFF:8>
+;//   <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8>
+;//   <o4> Interrupt Mode      <0x0-0xFFFFFFFF:8>
+;//   <o5> User/System Mode    <0x0-0xFFFFFFFF:8>
+;// </h>
+
+UND_Stack_Size  EQU     512
+SVC_Stack_Size  EQU     4096
+ABT_Stack_Size  EQU     512
+FIQ_Stack_Size  EQU     1024
+IRQ_Stack_Size  EQU     1024
+USR_Stack_Size  EQU     512
+
+ISR_Stack_Size  EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
+                         FIQ_Stack_Size + IRQ_Stack_Size)
+
+                AREA    STACK, NOINIT, READWRITE, ALIGN=3
+
+Stack_Mem       SPACE   USR_Stack_Size
+__initial_sp    SPACE   ISR_Stack_Size
+Stack_Top
+
+
+;// <h> Heap Configuration
+;//   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF>
+;// </h>
+
+Heap_Size       EQU     0x00000000
+
+                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
+__heap_base
+Heap_Mem        SPACE   Heap_Size
+__heap_limit
+
+
+;----------------------- Memory Definitions ------------------------------------
+
+AT91_MATRIX_BASE    EQU  0xffffee00
+AT91_MATRIX_MRCR	   EQU  (AT91_MATRIX_BASE + 0x100)
+AT91_MATRIX_RCB0    EQU  0x00000001
+AT91_MATRIX_RCB1    EQU  0x00000002
+AT91_AIC_BASE       EQU  0xfffff000
+AT91_AIC_IDCR       EQU  0x124
+AT91_AIC_ICCR       EQU  0x128
+
+;----------------------- CODE --------------------------------------------------
+
+                PRESERVE8
+
+
+; Area Definition and Entry Point
+;  Startup Code must be linked first at Address at which it expects to run.
+
+                AREA    RESET, CODE, READONLY
+                ARM
+
+; Exception Vectors
+;  Mapped to Address 0.
+;  Absolute addressing mode must be used.
+;  Dummy Handlers are implemented as infinite loops which can be modified.
+
+				EXPORT Entry_Point
+Entry_Point
+Vectors         LDR     PC, Reset_Addr
+                LDR     PC, Undef_Addr
+                LDR     PC, SWI_Addr
+                LDR     PC, PAbt_Addr
+                LDR     PC, DAbt_Addr
+		NOP
+                LDR     PC, IRQ_Addr
+                LDR     PC, FIQ_Addr
+
+Reset_Addr      DCD     Reset_Handler
+Undef_Addr      DCD     Undef_Handler
+SWI_Addr        DCD     SWI_Handler
+PAbt_Addr       DCD     PAbt_Handler
+DAbt_Addr       DCD     DAbt_Handler
+                DCD     0                   ; Reserved Address
+IRQ_Addr        DCD     IRQ_Handler
+FIQ_Addr        DCD     FIQ_Handler
+
+Undef_Handler   B       Undef_Handler
+SWI_Handler     B       SWI_Handler
+PAbt_Handler    B       PAbt_Handler
+;DAbt_Handler    B       DAbt_Handler
+FIQ_Handler     B       FIQ_Handler
+
+;*
+;*************************************************************************
+;*
+;* Interrupt handling
+;*
+;*************************************************************************
+;*
+; DAbt Handler
+DAbt_Handler
+               IMPORT rt_hw_trap_dabt
+
+                	sub 	sp, sp, #72
+	                stmia 	sp, {r0 - r12}   		;/* Calling r0-r12					*/
+                    add		r8, sp, #60
+	                stmdb   r8, {sp, lr}            ;/* Calling SP, LR					*/
+	                str		lr, [r8, #0]            ;/* Save calling PC					*/
+	                mrs		r6, spsr
+	                str		r6, [r8, #4]            ;/* Save CPSR						*/
+	                str		r0, [r8, #8]            ;/* Save OLD_R0						*/
+	                mov		r0, sp
+
+	                bl 		rt_hw_trap_dabt
+
+
+;##########################################
+; Reset Handler
+
+                EXPORT  Reset_Handler
+Reset_Handler
+
+
+; set the cpu to SVC32 mode-----------------------------------------------------
+
+                MRS		R0,CPSR
+               	BIC		R0,R0,#MODEMASK
+	               ORR		R0,R0,#SVCMODE
+	               MSR		CPSR_cxsf,R0
+                LDR	R1, =AT91_AIC_BASE
+	               LDR	R0, =0xffffffff
+	               STR	R0, [R1, #AT91_AIC_IDCR]
+	               STR	R0, [R1, #AT91_AIC_ICCR]
+
+; remap internal ram to 0x00000000 address
+	               LDR	R0, =AT91_MATRIX_MRCR
+	               LDR	R1, =(AT91_MATRIX_RCB0|AT91_MATRIX_RCB1)
+	               STR	R1, [R0]
+
+
+; Copy Exception Vectors to Internal RAM ---------------------------------------
+
+                ADR     R8,  Vectors    ; Source
+                LDR     R9, =0x00  ; Destination
+                LDMIA   R8!, {R0-R7}    ; Load Vectors
+                STMIA   R9!, {R0-R7}    ; Store Vectors
+                LDMIA   R8!, {R0-R7}    ; Load Handler Addresses
+                STMIA   R9!, {R0-R7}    ; Store Handler Addresses
+
+
+; Setup Stack for each mode ----------------------------------------------------
+
+                LDR     R0, =Stack_Top
+
+;  Enter Undefined Instruction Mode and set its Stack Pointer
+                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
+                MOV     SP, R0
+                SUB     R0, R0, #UND_Stack_Size
+
+;  Enter Abort Mode and set its Stack Pointer
+                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
+                MOV     SP, R0
+                SUB     R0, R0, #ABT_Stack_Size
+
+;  Enter FIQ Mode and set its Stack Pointer
+                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
+                MOV     SP, R0
+                SUB     R0, R0, #FIQ_Stack_Size
+
+;  Enter IRQ Mode and set its Stack Pointer
+                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
+                MOV     SP, R0
+                SUB     R0, R0, #IRQ_Stack_Size
+
+;  Enter Supervisor Mode and set its Stack Pointer
+                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
+                MOV     SP, R0
+                SUB     R0, R0, #SVC_Stack_Size
+
+;  Enter User Mode and set its Stack Pointer
+                ; MSR     CPSR_c, #Mode_USR
+                MOV     SP, R0
+                SUB     SL, SP, #USR_Stack_Size
+
+; Enter the C code -------------------------------------------------------------
+
+                IMPORT  __main
+                LDR     R0, =__main
+                BX      R0
+
+                IMPORT rt_interrupt_enter
+                IMPORT rt_interrupt_leave
+                IMPORT rt_thread_switch_interrput_flag
+                IMPORT rt_interrupt_from_thread
+                IMPORT rt_interrupt_to_thread
+                IMPORT rt_hw_trap_irq
+
+IRQ_Handler     PROC
+                EXPORT IRQ_Handler
+                STMFD   sp!, {r0-r12,lr}
+                BL  rt_interrupt_enter
+                BL  rt_hw_trap_irq
+                BL  rt_interrupt_leave
+
+                ; if rt_thread_switch_interrput_flag set, jump to
+                ; rt_hw_context_switch_interrupt_do and don't return
+                LDR r0, =rt_thread_switch_interrput_flag
+                LDR r1, [r0]
+                CMP r1, #1
+                BEQ rt_hw_context_switch_interrupt_do
+
+                LDMFD   sp!, {r0-r12,lr}
+                SUBS    pc, lr, #4
+                ENDP
+
+; /*
+; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
+; */
+rt_hw_context_switch_interrupt_do   PROC
+                EXPORT rt_hw_context_switch_interrupt_do
+                MOV     r1,  #0         ; clear flag
+                STR     r1,  [r0]
+
+                LDMFD   sp!, {r0-r12,lr}; reload saved registers
+                STMFD   sp!, {r0-r3}    ; save r0-r3
+                MOV     r1,  sp
+                ADD     sp,  sp, #16    ; restore sp
+                SUB     r2,  lr, #4     ; save old task's pc to r2
+
+                MRS     r3,  spsr       ; get cpsr of interrupt thread
+
+                ; switch to SVC mode and no interrupt
+				MSR 	cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC
+
+                STMFD   sp!, {r2}       ; push old task's pc
+                STMFD   sp!, {r4-r12,lr}; push old task's lr,r12-r4
+                MOV     r4,  r1         ; Special optimised code below
+                MOV     r5,  r3
+                LDMFD   r4!, {r0-r3}
+                STMFD   sp!, {r0-r3}    ; push old task's r3-r0
+                STMFD   sp!, {r5}       ; push old task's cpsr
+                MRS     r4,  spsr
+                STMFD   sp!, {r4}       ; push old task's spsr
+
+                LDR     r4,  =rt_interrupt_from_thread
+                LDR     r5,  [r4]
+                STR     sp,  [r5]       ; store sp in preempted tasks's TCB
+
+                LDR     r6,  =rt_interrupt_to_thread
+                LDR     r6,  [r6]
+                LDR     sp,  [r6]       ; get new task's stack pointer
+
+                LDMFD   sp!, {r4}       ; pop new task's spsr
+                MSR     spsr_cxsf, r4
+                LDMFD   sp!, {r4}       ; pop new task's psr
+                MSR     cpsr_cxsf, r4
+
+                LDMFD   sp!, {r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc
+                ENDP
+
+                IF      :DEF:__MICROLIB
+
+                EXPORT  __heap_base
+                EXPORT  __heap_limit
+
+                ELSE
+; User Initial Stack & Heap
+                AREA    |.text|, CODE, READONLY
+
+                IMPORT  __use_two_region_memory
+                EXPORT  __user_initial_stackheap
+__user_initial_stackheap
+
+                LDR     R0, =  Heap_Mem
+                LDR     R1, =(Stack_Mem + USR_Stack_Size)
+                LDR     R2, = (Heap_Mem +      Heap_Size)
+                LDR     R3, = Stack_Mem
+                BX      LR
+                ENDIF
+
+
+                END
+

+ 29 - 11
libcpu/arm/at91sam926x/system_clock.c

@@ -26,34 +26,52 @@ struct clk {
 };
 
 static struct clk clk32k = {
-	.name = "clk32k",
-	.rate_hz = AT91_SLOW_CLOCK,
+	"clk32k",
+	AT91_SLOW_CLOCK,
+	RT_NULL,
+	{RT_NULL, RT_NULL},
 };
 
 static struct clk main_clk = {
-	.name = "main",
+	"main",
+	0,
+	RT_NULL,
+	{RT_NULL, RT_NULL},
 };
 
 static struct clk plla = {
-	.name = "plla",
+	"plla",
+	0,
+	RT_NULL,
+	{RT_NULL, RT_NULL},
 };
 
 static struct clk mck = {
-	.name = "mck",
+	"mck",
+	0,
+	RT_NULL,
+	{RT_NULL, RT_NULL},
 };
 
 static struct clk uhpck = {
-	.name = "uhpck",
+	"uhpck",
+	0,
+	RT_NULL,
+	{RT_NULL, RT_NULL},
 };
 
 static struct clk pllb = {
-	.name = "pllb",
-	.parent = &main_clk,
+	"pllb",
+	0,
+	&main_clk,
+	{RT_NULL, RT_NULL},
 };
 
 static struct clk udpck = {
-	.name = "udpck",
-	.parent = &pllb,
+	"udpck",
+	0,
+	&pllb,
+	{RT_NULL, RT_NULL},
 };
 
 static struct clk *const standard_pmc_clocks[] = {
@@ -75,7 +93,7 @@ struct clk *clk_get(const char *id)
 	for (list = (&clocks)->next; list != &clocks; list = list->next)
 	{
 		clk = (struct clk *)rt_list_entry(list, struct clk, node);
-		if (strcmp(id, clk->name) == 0)
+		if (rt_strcmp(id, clk->name) == 0)
 			return clk;
 	}