From 1c23d682818dfbde24a896edd741f955f6046d69 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Tue, 27 Aug 2013 14:52:39 +0300 Subject: [PATCH 01/18] Added support for LPC11U24_301/401 compilation with ARM toolchain --- .../TARGET_LPC11U24_301/LPC11U24.sct | 17 +++++++++++++++++ .../{ => TARGET_LPC11U24_401}/LPC11U24.sct | 0 2 files changed, 17 insertions(+) create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U24_301/LPC11U24.sct rename libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/{ => TARGET_LPC11U24_401}/LPC11U24.sct (100%) diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U24_301/LPC11U24.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U24_301/LPC11U24.sct new file mode 100644 index 0000000000..5a6e12b240 --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U24_301/LPC11U24.sct @@ -0,0 +1,17 @@ + +LR_IROM1 0x00000000 0x8000 { ; load region size_region (32k) + ER_IROM1 0x00000000 0x8000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + ; 8_byte_aligned(48 vect * 4 bytes) = 8_byte_aligned(0xC0) = 0xC0 + ; 6KB - 0xC0 = 0x1740 + RW_IRAM1 0x100000C0 0x1740 { + .ANY (+RW +ZI) + } + RW_IRAM2 0x20004000 0x800 { ; RW data, USB RAM + .ANY (USBRAM) + } +} + diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/LPC11U24.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U24_401/LPC11U24.sct similarity index 100% rename from libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/LPC11U24.sct rename to libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U24_401/LPC11U24.sct From 9a270999d056ff050155f839f7fa7b777948a09b Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Tue, 27 Aug 2013 15:19:01 +0300 Subject: [PATCH 02/18] Added support for LPC11U35_401 in ARM and GCC_ARM --- .../TARGET_LPC11U35_401/LPC11U35.sct | 17 ++ .../TARGET_LPC11U35_401/LPC11U35.ld | 152 ++++++++++++++++++ workspace_tools/targets.py | 12 +- 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U35_401/LPC11U35.sct create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_GCC_ARM/TARGET_LPC11U35_401/LPC11U35.ld diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U35_401/LPC11U35.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U35_401/LPC11U35.sct new file mode 100644 index 0000000000..99d9a6c20d --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_STD/TARGET_LPC11U35_401/LPC11U35.sct @@ -0,0 +1,17 @@ + +LR_IROM1 0x00000000 0x10000 { ; load region size_region (64k) + ER_IROM1 0x00000000 0x10000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + ; 8_byte_aligned(48 vect * 4 bytes) = 8_byte_aligned(0xC0) = 0xC0 + ; 8KB - 0xC0 = 0x1F40 + RW_IRAM1 0x100000C0 0x1F40 { + .ANY (+RW +ZI) + } + RW_IRAM2 0x20004000 0x800 { ; RW data, USB RAM + .ANY (USBRAM) + } +} + diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_GCC_ARM/TARGET_LPC11U35_401/LPC11U35.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_GCC_ARM/TARGET_LPC11U35_401/LPC11U35.ld new file mode 100644 index 0000000000..bcfe4dea89 --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_GCC_ARM/TARGET_LPC11U35_401/LPC11U35.ld @@ -0,0 +1,152 @@ +/* Linker script to configure memory regions. */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K + RAM (rwx) : ORIGIN = 0x100000C0, LENGTH = 0x1F40 + USB_RAM (rwx): ORIGIN = 0x20004000, LENGTH = 0x800 +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text.Reset_Handler) + *(.text.SystemInit) + + /* Only vectors and code running at reset are safe to be in first 512 + bytes since RAM can be mapped into this area for RAM based interrupt + vectors. */ + . = 0x00000200; + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE (__fini_array_end = .); + + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + __bss_start__ = .; + *(.bss*) + *(COMMON) + __bss_end__ = .; + } > RAM + + .heap : + { + __end__ = .; + end = __end__; + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy : + { + *(.stack) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index b5cf7f5f5c..e2909372e0 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -228,6 +228,15 @@ class LPC11C24(Target): self.supported_toolchains = ["ARM", "uARM", "GCC_ARM"] +class LPC11U35_401(Target): + def __init__(self): + Target.__init__(self) + + self.core = "Cortex-M0" + + self.extra_labels = ['NXP', 'LPC11UXX'] + + self.supported_toolchains = ["ARM", "uARM", "GCC_ARM"] # Get a single instance for each target TARGETS = [ @@ -244,7 +253,8 @@ TARGETS = [ MBED_MCU(), LPC1347(), LPC1114(), - LPC11C24() + LPC11C24(), + LPC11U35_401() ] # Map each target name to its unique instance From 2cdd41d9b139e4d5694e1c9e7e02a3e3ed77c003 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Tue, 27 Aug 2013 15:31:47 +0300 Subject: [PATCH 03/18] Added support for LPC11U24/_301 and LPC11U35_401 in uARM --- .../TARGET_LPC11U24_301/LPC11U24.sct | 17 +++++++++++++++++ .../{ => TARGET_LPC11U24_401}/LPC11U24.sct | 0 .../TARGET_LPC11U35_401/LPC11U35.sct | 17 +++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U24_301/LPC11U24.sct rename libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/{ => TARGET_LPC11U24_401}/LPC11U24.sct (100%) create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_401/LPC11U35.sct diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U24_301/LPC11U24.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U24_301/LPC11U24.sct new file mode 100644 index 0000000000..5a6e12b240 --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U24_301/LPC11U24.sct @@ -0,0 +1,17 @@ + +LR_IROM1 0x00000000 0x8000 { ; load region size_region (32k) + ER_IROM1 0x00000000 0x8000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + ; 8_byte_aligned(48 vect * 4 bytes) = 8_byte_aligned(0xC0) = 0xC0 + ; 6KB - 0xC0 = 0x1740 + RW_IRAM1 0x100000C0 0x1740 { + .ANY (+RW +ZI) + } + RW_IRAM2 0x20004000 0x800 { ; RW data, USB RAM + .ANY (USBRAM) + } +} + diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/LPC11U24.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U24_401/LPC11U24.sct similarity index 100% rename from libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/LPC11U24.sct rename to libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U24_401/LPC11U24.sct diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_401/LPC11U35.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_401/LPC11U35.sct new file mode 100644 index 0000000000..99d9a6c20d --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11UXX/TOOLCHAIN_ARM_MICRO/TARGET_LPC11U35_401/LPC11U35.sct @@ -0,0 +1,17 @@ + +LR_IROM1 0x00000000 0x10000 { ; load region size_region (64k) + ER_IROM1 0x00000000 0x10000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + ; 8_byte_aligned(48 vect * 4 bytes) = 8_byte_aligned(0xC0) = 0xC0 + ; 8KB - 0xC0 = 0x1F40 + RW_IRAM1 0x100000C0 0x1F40 { + .ANY (+RW +ZI) + } + RW_IRAM2 0x20004000 0x800 { ; RW data, USB RAM + .ANY (USBRAM) + } +} + From 4603d729f9aef2aad341765251a3bc7d24dde7c1 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Thu, 22 Aug 2013 18:11:51 -0700 Subject: [PATCH 04/18] net: Fully disable LWIP_ASSERTs I was doing some debugging that had me looking at the disassembly of lpc_rx_queue() from within the debugger. I was looking for the call to pbuf_alloc() that we see in the following code snippet: p = pbuf_alloc(PBUF_RAW, (u16_t) EMAC_ETH_MAX_FLEN, PBUF_RAM); if (p == NULL) { LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, ("lpc_rx_queue: could not allocate RX pbuf (free desc=%d)\n", lpc_enetif->rx_free_descs)); return queued; } /* pbufs allocated from the RAM pool should be non-chained. */ LWIP_ASSERT("lpc_rx_queue: pbuf is not contiguous (chained)", pbuf_clen(p) <= 1); When I was looking through the disassembly for this code I noticed a call to pbuf_clen() in the actual machine code. => 0x0000bab0 <+24>: bl 0x44c0 0x0000bab4 <+28>: ldr r3, [r4, #112] ; 0x70 0x0000bab6 <+30>: ldrh.w r12, [r5, #10] 0x0000baba <+34>: add.w r2, r3, #9 0x0000babe <+38>: add.w r0, r12, #4294967295 ; 0xffffffff The only call to pbuf_clean made from this function is made from within the LWIP_ASSERT. When I looked more closely at how this macro was defined, I saw that the mbed version of the stack had disabled the LWIP_PLATFORM_ASSERT macro when LWIP_DEBUG was false which means that no action will be taken if the assert is false but it still allows the LWIP_ASSERT macro to potentially evaluate the assert expression. Defining the LWIP_NOASSERT macro will fully disable the LWIP_ASSERT macro. I saw one of my TCP/IP samples shrink about 0.5K when I made this change. --- libraries/net/lwip/lwip/lwipopts.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/net/lwip/lwip/lwipopts.h b/libraries/net/lwip/lwip/lwipopts.h index 10846e2416..463e2c387b 100644 --- a/libraries/net/lwip/lwip/lwipopts.h +++ b/libraries/net/lwip/lwip/lwipopts.h @@ -99,6 +99,7 @@ #define MEMP_OVERFLOW_CHECK 1 #define MEMP_SANITY_CHECK 1 #else +#define LWIP_NOASSERT 1 #define LWIP_STATS 0 #endif From fa392423c84ac5d5acbf8fc650f8fcca1b322c52 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Fri, 23 Aug 2013 22:14:38 -0700 Subject: [PATCH 05/18] Silence GCC unused variable warning. After making my previous commit to completely disable LWIP_ASSERT macro invocations, I ended up with a warning in pbuf.c where an err variable was set but only checked for success in an assert. I added a "(void)err;" reference to silence this warning. --- libraries/net/lwip/lwip/core/pbuf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/net/lwip/lwip/core/pbuf.c b/libraries/net/lwip/lwip/core/pbuf.c index 818eb62035..cd37c79723 100644 --- a/libraries/net/lwip/lwip/core/pbuf.c +++ b/libraries/net/lwip/lwip/core/pbuf.c @@ -998,6 +998,8 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer) } err = pbuf_copy(q, p); LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); + /* next line references err variable even if LWIP_ASSERT is ignored. */ + (void)err; pbuf_free(p); return q; } From f5ec5d3ab2d2ab130dc4ba12a0742da8db4225fb Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sat, 24 Aug 2013 13:13:26 -0700 Subject: [PATCH 06/18] net: Enable SYS_LIGHTWEIGHT_PROT This option actually enables the use of the lwip_sys_mutex for protecting concurrent access to such important lwIP resources as: select_cb_list (this is the one which orig flagged problem) sockets array mem stats (if enabled) heap (if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT was non-zero) memp pool allocs/frees netif->loop_last pbuf linked list pbuf reference counts ... I first noticed this issue when I hit a crash while slamming the net stack with a large number of TCP packets (I was actually sending 1k data buffers from the TCPEchoServer mbed sample.) It crashed in the last line of this code snippet from event_callback: for (scb = select_cb_list; scb != NULL; scb = scb->next) { if (scb->sem_signalled == 0) { It was crashing because scb had an invalid address so it generated a bus fault. I figured that memory was either corrupted or there was some kind of concurrency issue. In trying to determine which, I wanted to walk through the select_cb_list linked list and see where it was corrupted: (gdb) p scb $1 = (struct lwip_select_cb *) 0x85100080 (gdb) p select_cb_list $2 = (struct lwip_select_cb *) 0x0 That was interesting, the head of the linked list was now NULL but it must have had a non-NULL value when this loop started running or we would have never gotten to the point where we hit this crash. This was starting to look like a concurrency issue since the linked list was modified out from underneath this thread. Looking through the source code for this function, I saw use of macros like SYS_ARCH_PROTECT and SYS_ARCH_UNPROTECT which looked like they should be providing the thead synchronization. I disassembled the event_callback() function in the debugger and saw no signs of the usage of synchronizition APIs that I expected. A search through the code for the definition of these SYS_ARCH_UN/PROTECT macros led me to discovering that they were actually ignored unless an implementation defined them itself (the mbed version doesn't do so) or the SYS_LIGHTWEIGHT_PROT macro is set to non-zero (the mbed version didn't do this either). Flipping the SYS_LIGHTWEIGHT_PROT macro on in lwipopts.h fixed the crash I kept hitting, increased the size of the code a bit, and unfortunately slows things down a bit since it now actually serializes access to these data structures by making calls to the RTOS sync APIs. --- libraries/net/lwip/lwip/lwipopts.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/net/lwip/lwip/lwipopts.h b/libraries/net/lwip/lwip/lwipopts.h index 463e2c387b..4d07680dbc 100644 --- a/libraries/net/lwip/lwip/lwipopts.h +++ b/libraries/net/lwip/lwip/lwipopts.h @@ -27,6 +27,8 @@ #if NO_SYS == 0 #include "cmsis_os.h" +#define SYS_LIGHTWEIGHT_PROT 1 + #define LWIP_RAW 0 #define TCPIP_MBOX_SIZE 8 From acb35785c90a721b0d815f91b38cc4fa9b8d157f Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sat, 24 Aug 2013 14:10:30 -0700 Subject: [PATCH 07/18] net: Only process 1 packet per ethernet RX interrupt Previously the packet_rx() function would wait on the RxSem and when signalled it would process all available inbound packets. This used to cause no problem but once the thread synchronization was turned on via SYS_LIGHTWEIGHT_PROT, the semaphore actually started to overflow its maximum token count of 65535. This caused the mbed_die() flashing LEDs of death. The old code was really breaking the producer/consumer pattern that I typically see with a semaphore since the consumer was written to consume more than 1 produced object per semaphore wait. Before the thread synchronization was enabled, the packet_rx() thread could use a single time slice to process all of these packets and then loop back around a few more times to decrement the semaphore count while skipping the packet processing since it had all been done. Now the packet processing code would cause the thread to give up its time slice as it hit newly enabled critical sections. In the end it was possible for the code to leak 2 semaphore signals for every 1 by which the thread was awaken. After about 10 seconds of load, this would cause a leak of 65535 signals. NOTE: Two potential issues with this change: 1) The LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex check was removed from packet_rx(). I believe that this is Ok since the same condition is later checked in lpc_low_level_input() anyway so it won't now try to process more packets than what exist. 2) What if ENET_IRQHandler(void) ends up not signalling the RxSem for every packet received? When would that happen? I could see it happening if the ethernet hardware would try to pend more than 1 interrupt when the priority was too elevated to process the pending requests. Putting the consumer loop back in packet_rx() and using a Signal instead of a Semaphore might be a better solution? --- libraries/net/eth/lwip-eth/arch/lpc17_emac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c index 243f9930a0..18d577144d 100644 --- a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c +++ b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c @@ -809,9 +809,8 @@ static void packet_rx(void* pvParameters) { /* Wait for receive task to wakeup */ sys_arch_sem_wait(&lpc_enetif->RxSem, 0); - /* Process packets until all empty */ - while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) - lpc_enetif_input(lpc_enetif->netif); + /* Process packet for this semaphore signal */ + lpc_enetif_input(lpc_enetif->netif); } } From de8161fde126ba36eaea9bd8f2f44a43d635c2c6 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sat, 24 Aug 2013 14:48:12 -0700 Subject: [PATCH 08/18] net: Reset pbuf length when re-queueing on error. I recently pulled a NXP crash fix for their ethernet driver which will requeue a pbuf to the ethernet driver rather than sending it to the lwip stack if it can't allocate a new pbuf to keep the ethernet hardware primed with available packet buffers. While recently reviewing this code I noticed that the full size of the pbuf wasn't used on this re-queueing operation but the size of the last received packet. I now reset the pbuf size back to its originally allocated size before doing this requeue operation. --- libraries/net/eth/lwip-eth/arch/lpc17_emac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c index 18d577144d..e082fd495f 100644 --- a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c +++ b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c @@ -346,6 +346,7 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) struct lpc_enetdata *lpc_enetif = netif->state; struct pbuf *p = NULL; u32_t idx, length; + u16_t origLength; #ifdef LOCK_RX_THREAD #if NO_SYS == 0 @@ -428,6 +429,7 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) /* Zero-copy */ p = lpc_enetif->rxb[idx]; + origLength = p->len; p->len = (u16_t) length; /* Free pbuf from descriptor */ @@ -440,6 +442,7 @@ static struct pbuf *lpc_low_level_input(struct netif *netif) LINK_STATS_INC(link.drop); /* Re-queue the pbuf for receive */ + p->len = origLength; lpc_rxqueue_pbuf(lpc_enetif, p); LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE, From 2bed9964627c52b4ce54159fa724ed5e61623046 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Tue, 27 Aug 2013 22:24:47 -0700 Subject: [PATCH 09/18] Revert "net: Only process 1 packet per ethernet RX interrupt" This reverts commit acb35785c90a721b0d815f91b38cc4fa9b8d157f. It turns out that this commit actually causes problems if an ethernet interrupt is dropped because a higher privilege task is running, such as LocalFileSystem accesses. If this happens, the semaphore count isn't incremented enough times and the packet_rx() thread will fall behind and end up running as though it had only one ethernet receive buffer. This causes even more lost packets. I plan to fix this by switching the semaphore to be a signal so that the syncronization object is more boolean. It simply indicates if an interrupt has arrived since the last time packet_rx() was awaken to process inbound packets. --- libraries/net/eth/lwip-eth/arch/lpc17_emac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c index e082fd495f..9bace5f80b 100644 --- a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c +++ b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c @@ -812,8 +812,9 @@ static void packet_rx(void* pvParameters) { /* Wait for receive task to wakeup */ sys_arch_sem_wait(&lpc_enetif->RxSem, 0); - /* Process packet for this semaphore signal */ - lpc_enetif_input(lpc_enetif->netif); + /* Process packets until all empty */ + while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) + lpc_enetif_input(lpc_enetif->netif); } } From 8cf3e658d178aab5f0049c634ab83e49516b3a35 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Tue, 27 Aug 2013 23:38:42 -0700 Subject: [PATCH 10/18] Don't use semaphore from ENET_IRQHandler to packet_rx I now use a signal to communicate when a packet has been received by the ethernet hardware and should be processed by the packet_rx thread. Previously the change to make the lwIP stack thread safe introduced enough delay in packet_rx that the semaphore count could lag behind the processed packets and overflow its maximum token count. Now the ISR uses the signal to indicate that >= 1 packet has been received since the last time packet_rx() was awaken. Previously the ethernet driver used generic sys_arch* APIs exposed from lwIP to manipulate the semaphores. I now call CMSIS RTOS APIs directly when using the signals. I think this is acceptable since that same driver source file already contains similar os* calls that talk directly to the RTOS. --- libraries/net/eth/lwip-eth/arch/lpc17_emac.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c index 9bace5f80b..093f8a6ca3 100644 --- a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c +++ b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c @@ -88,6 +88,10 @@ */ #define TXINTGROUP (EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE) +/** \brief Signal used for ethernet ISR to signal packet_rx() thread. + */ +#define RX_SIGNAL 1 + #else #define RXINTGROUP 0 #define TXINTGROUP 0 @@ -123,7 +127,7 @@ struct lpc_enetdata { struct pbuf *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */ u32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */ #if NO_SYS == 0 - sys_sem_t RxSem; /**< RX receive thread wakeup semaphore */ + sys_thread_t RxThread; /**< RX receive thread data object pointer */ sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ sys_mutex_t TXLockMutex; /**< TX critical section mutex */ sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */ @@ -783,8 +787,8 @@ void ENET_IRQHandler(void) ints = LPC_EMAC->IntStatus; if (ints & RXINTGROUP) { - /* RX group interrupt(s): Give semaphore to wakeup RX receive task.*/ - sys_sem_signal(&lpc_enetdata.RxSem); + /* RX group interrupt(s): Give signal to wakeup RX receive task.*/ + osSignalSet(lpc_enetdata.RxThread->id, RX_SIGNAL); } if (ints & TXINTGROUP) { @@ -810,7 +814,7 @@ static void packet_rx(void* pvParameters) { while (1) { /* Wait for receive task to wakeup */ - sys_arch_sem_wait(&lpc_enetif->RxSem, 0); + osSignalWait(RX_SIGNAL, osWaitForever); /* Process packets until all empty */ while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) @@ -1096,9 +1100,8 @@ err_t lpc_enetif_init(struct netif *netif) LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK)); /* Packet receive task */ - err = sys_sem_new(&lpc_enetdata.RxSem, 0); - LWIP_ASSERT("RxSem creation error", (err == ERR_OK)); - sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY); + lpc_enetdata.RxThread = sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY); + LWIP_ASSERT("RxThread creation error", (lpc_enetdata.RxThread)); /* Transmit cleanup task */ err = sys_sem_new(&lpc_enetdata.TxCleanSem, 0); From b0c0f47c7d3bb4965e0c3e631e37a416723c2310 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Tue, 27 Aug 2013 23:57:24 -0700 Subject: [PATCH 11/18] Changed leading whitespace back to tab. The leading whitespace preceeding the fields in the lpc_enetdata structure definition were originally a tab and I used 4 spaces when I added RxThread. --- libraries/net/eth/lwip-eth/arch/lpc17_emac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c index 093f8a6ca3..729840f636 100644 --- a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c +++ b/libraries/net/eth/lwip-eth/arch/lpc17_emac.c @@ -127,7 +127,7 @@ struct lpc_enetdata { struct pbuf *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */ u32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */ #if NO_SYS == 0 - sys_thread_t RxThread; /**< RX receive thread data object pointer */ + sys_thread_t RxThread; /**< RX receive thread data object pointer */ sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */ sys_mutex_t TXLockMutex; /**< TX critical section mutex */ sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */ From 97d92789ec335374f2b57293df44a01604e3afbc Mon Sep 17 00:00:00 2001 From: dinau Date: Wed, 28 Aug 2013 23:29:16 +0900 Subject: [PATCH 12/18] Fixed: The issue of interrupt vector remapping for GCC_ARM LPC1114 --- .../TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld index 3f3cd51167..6c1f51722b 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld @@ -4,7 +4,7 @@ MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 32K - RAM (rwx) : ORIGIN = 0x10000000, LENGTH = 2K + RAM (rwx) : ORIGIN = 0x100000C0, LENGTH = 0x0F40 } /* Linker script to place sections and symbol values. Should be used together @@ -40,6 +40,7 @@ SECTIONS .text : { KEEP(*(.isr_vector)) + . = 0x200; *(.text*) KEEP(*(.init)) From 841ce1d719766ef17814cf9b7ede8e146b5e11cf Mon Sep 17 00:00:00 2001 From: dinau Date: Thu, 29 Aug 2013 21:40:57 +0900 Subject: [PATCH 13/18] Fixed: The issue of interrupt vector remapping for GCC_ARM LPC1114 --- .../TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld index 6c1f51722b..dd2e65da50 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC11XX/TOOLCHAIN_GCC_ARM/LPC1114.ld @@ -40,6 +40,8 @@ SECTIONS .text : { KEEP(*(.isr_vector)) + *(.text.Reset_Handler) + *(.text.SystemInit) . = 0x200; *(.text*) From e870a90ff2af3c12ddda144698b20ab68b05fefd Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Fri, 30 Aug 2013 12:19:08 +0300 Subject: [PATCH 14/18] Added toolchain hooks and support for LPC4088_EA binary generation A new hooks mechanism (hooks.py) allows various targets to customize part(s) of the build process. This was implemented to allow generation of custom binary images for the EA LPC4088 target, but it should be generic enough to allow other such customizations in the future. For now, only the 'binary' step is hooked in toolchains/arm.py. --- .../{ => TARGET_LPC4088}/LPC407X_8X.sct | 0 .../TARGET_LPC4088_EA/LPC407X_8X.sct | 24 ++++++ workspace_tools/hooks.py | 77 +++++++++++++++++++ workspace_tools/targets.py | 43 ++++++++++- workspace_tools/toolchains/__init__.py | 2 + workspace_tools/toolchains/arm.py | 5 +- 6 files changed, 148 insertions(+), 3 deletions(-) rename libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/{ => TARGET_LPC4088}/LPC407X_8X.sct (100%) create mode 100644 libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/TARGET_LPC4088_EA/LPC407X_8X.sct create mode 100644 workspace_tools/hooks.py diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/LPC407X_8X.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/TARGET_LPC4088/LPC407X_8X.sct similarity index 100% rename from libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/LPC407X_8X.sct rename to libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/TARGET_LPC4088/LPC407X_8X.sct diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/TARGET_LPC4088_EA/LPC407X_8X.sct b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/TARGET_LPC4088_EA/LPC407X_8X.sct new file mode 100644 index 0000000000..61319733bc --- /dev/null +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC408X/TOOLCHAIN_ARM_STD/TARGET_LPC4088_EA/LPC407X_8X.sct @@ -0,0 +1,24 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x00000000 0x00080000 { ; load region size_region + ER_IROM1 0x00000000 0x00080000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x100000E8 0x0000FF18 { ; RW data + .ANY (+RW +ZI) + } + RW_IRAM2 0x20000000 0x00008000 { + .ANY (AHBSRAM1) + } +} + +LR_IROM2 0x28000000 0x01000000 { + ER_IROM2 0x28000000 0x01000000 { ; load address = execution address + .ANY (+RO) + } +} + diff --git a/workspace_tools/hooks.py b/workspace_tools/hooks.py new file mode 100644 index 0000000000..b171de3fff --- /dev/null +++ b/workspace_tools/hooks.py @@ -0,0 +1,77 @@ +# Configurable hooks in the build system. Can be used by various platforms +# to customize the build process. + +################################################################################ +# Hooks for the various parts of the build process + +# Internal mapping of hooks per tool +_hooks = {} + +# Internal mapping of running hooks +_running_hooks = {} + +# Available hook types +_hook_types = ["binary"] + +# Available hook steps +_hook_steps = ["pre", "replace", "post"] + +# Hook the given function. Use this function as a decorator +def hook_tool(function): + tool = function.__name__ + tool_flag = "_" + tool + "_done" + def wrapper(t_self, *args, **kwargs): + # if a hook for this tool is already running, it's most likely + # coming from a derived class, so don't hook the super class version + if _running_hooks.get(tool, False): + return function(t_self, *args, **kwargs) + _running_hooks[tool] = True + # If this tool isn't hooked, return original function + if not _hooks.has_key(tool): + res = function(t_self, *args, **kwargs) + _running_hooks[tool] = False + return res + tooldesc = _hooks[tool] + setattr(t_self, tool_flag, False) + # If there is a replace hook, execute the replacement instead + if tooldesc.has_key("replace"): + res = tooldesc["replace"](t_self, *args, **kwargs) + # If the replacement has set the "done" flag, exit now + # Otherwise continue as usual + if getattr(t_self, tool_flag, False): + _running_hooks[tool] = False + return res + # Execute pre-function before main function if specified + if tooldesc.has_key("pre"): + tooldesc["pre"](t_self, *args, **kwargs) + # Execute the main function now + res = function(t_self, *args, **kwargs) + # Execute post-function after main function if specified + if tooldesc.has_key("post"): + post_res = tooldesc["post"](t_self, *args, **kwargs) + _running_hooks[tool] = False + return post_res or res + else: + _running_hooks[tool] = False + return res + return wrapper + +class Hook: + def __init__(self, target, toolchain): + _hooks.clear() + self.toolchain = toolchain + target.init_hooks(self, toolchain.__class__.__name__) + + def hook_add(self, hook_type, hook_step, function): + if not hook_type in _hook_types or not hook_step in _hook_steps: + return False + if not hook_type in _hooks: + _hooks[hook_type] = {} + _hooks[hook_type][hook_step] = function + return True + + def hook_add_binary(self, hook_step, function): + return self.hook_add("binary", hook_step, function) + +################################################################################ + diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index e2909372e0..0134c734b2 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -23,6 +23,8 @@ CORE_LABELS = { "Cortex-M4" : "M4" } +import os +import shutil class Target: def __init__(self): @@ -46,6 +48,8 @@ class Target: def get_labels(self): return [self.name, CORE_LABELS[self.core]] + self.extra_labels + def init_hooks(self, hook, toolchain_name): + pass class LPC2368(Target): def __init__(self): @@ -140,6 +144,42 @@ class LPC4088(Target): self.supported_toolchains = ["ARM", "GCC_CR"] +# Use this target to generate the custom binary image for LPC4088 EA boards +class LPC4088_EA(LPC4088): + def __init__(self): + LPC4088.__init__(self) + + def init_hooks(self, hook, toolchain_name): + if toolchain_name in ['ARM_STD', 'ARM_MICRO']: + hook.hook_add_binary("post", self.binary_hook) + + @staticmethod + def binary_hook(t_self, elf, binf): + if not os.path.isdir(binf): + # Regular binary file, nothing to do + return + outbin = open(binf + ".temp", "wb") + partf = open(os.path.join(binf, "ER_IROM1"), "rb") + # Pad the fist part (internal flash) with 0xFF to 512k + data = partf.read() + outbin.write(data) + outbin.write('\xFF' * (512*1024 - len(data))) + partf.close() + # Read and append the second part (external flash) in chunks of fixed size + chunksize = 128 * 1024 + partf = open(os.path.join(binf, "ER_IROM2"), "rb") + while True: + data = partf.read(chunksize) + outbin.write(data) + if len(data) < chunksize: + break + partf.close() + outbin.close() + # Remove the directory with the binary parts and rename the temporary + # file to 'binf' + shutil.rmtree(binf, True) + os.rename(binf + '.temp', binf) + t_self.debug("Generated custom binary file (internal flash + SPIFI)") class LPC4330_M4(Target): def __init__(self): @@ -254,7 +294,8 @@ TARGETS = [ LPC1347(), LPC1114(), LPC11C24(), - LPC11U35_401() + LPC11U35_401(), + LPC4088_EA() ] # Map each target name to its unique instance diff --git a/workspace_tools/toolchains/__init__.py b/workspace_tools/toolchains/__init__.py index 3003478c06..352aa1f048 100644 --- a/workspace_tools/toolchains/__init__.py +++ b/workspace_tools/toolchains/__init__.py @@ -25,6 +25,7 @@ from workspace_tools.utils import run_cmd, mkdir, rel_path, ToolException, split from workspace_tools.patch import patch from workspace_tools.settings import BUILD_OPTIONS +import workspace_tools.hooks as hooks def print_notify(event): # Default command line notification @@ -144,6 +145,7 @@ class mbedToolchain: def __init__(self, target, options=None, notify=None): self.target = target self.name = self.__class__.__name__ + self.hook = hooks.Hook(target, self) self.legacy_ignore_dirs = LEGACY_IGNORE_DIRS - set([target.name, LEGACY_TOOLCHAIN_NAMES[self.name]]) diff --git a/workspace_tools/toolchains/arm.py b/workspace_tools/toolchains/arm.py index a6601b0ec6..df265d0f76 100644 --- a/workspace_tools/toolchains/arm.py +++ b/workspace_tools/toolchains/arm.py @@ -19,7 +19,7 @@ from os.path import join from workspace_tools.toolchains import mbedToolchain from workspace_tools.settings import ARM_BIN, ARM_INC, ARM_LIB, MY_ARM_CLIB, ARM_CPPLIB - +from workspace_tools.hooks import hook_tool class ARM(mbedToolchain): LINKER_EXT = '.sct' @@ -97,12 +97,13 @@ class ARM(mbedToolchain): self.default_cmd([self.ar, '-r', lib_path] + objects) def link(self, output, objects, libraries, lib_dirs, mem_map): - args = ["-o", output, "--userlibpath", ",".join(lib_dirs), "--info=totals", "--list=.link_totals.txt"] + args = ["-o", output, "--userlibpath", ",".join(lib_dirs), "--info=totals", "--list=.link_totals.txt", "--any_placement=first_fit"] if mem_map: args.extend(["--scatter", mem_map]) self.default_cmd(self.ld + args + objects + libraries + self.sys_libs) + @hook_tool def binary(self, elf, bin): self.default_cmd([self.elf2bin, '--bin', '-o', bin, elf]) From 7dddd9e578fb0bd553f8ec9d615fdff109d06c5a Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sun, 25 Aug 2013 00:43:15 -0700 Subject: [PATCH 15/18] Asm versions of netstack memcpy() and lwip_standard_chksum() For tests such as TCPEchoServer (http://mbed.org/users/emilmont/notebook/networking-libraries-benchmark/) this change showed a 28% improvement (14Mbps to 18Mbps) when the echo test was modified to instead use 1K data buffers. I targetted these two functions based on manual profiling samples which showed that a great deal of time was being spent in these two functions when the network stack was being slammed with UDP packets. --- libraries/net/lwip/lwip-sys/arch/cc.h | 17 ++- libraries/net/lwip/lwip-sys/arch/checksum.c | 126 ++++++++++++++++++++ libraries/net/lwip/lwip-sys/arch/memcpy.c | 59 +++++++++ 3 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 libraries/net/lwip/lwip-sys/arch/checksum.c create mode 100644 libraries/net/lwip/lwip-sys/arch/memcpy.c diff --git a/libraries/net/lwip/lwip-sys/arch/cc.h b/libraries/net/lwip/lwip-sys/arch/cc.h index 394635a612..a17082e2ba 100644 --- a/libraries/net/lwip/lwip-sys/arch/cc.h +++ b/libraries/net/lwip/lwip-sys/arch/cc.h @@ -82,8 +82,21 @@ typedef uintptr_t mem_ptr_t; #define ALIGNED(n) __attribute__((aligned (n))) #endif -/* Used with IP headers only */ -#define LWIP_CHKSUM_ALGORITHM 1 +/* Provide Thumb-2 routines for GCC to improve performance */ +#if defined(TOOLCHAIN_GCC) && defined(__thumb2__) + #define MEMCPY(dst,src,len) thumb2_memcpy(dst,src,len) + #define LWIP_CHKSUM thumb2_checksum + /* Set algorithm to 0 so that unused lwip_standard_chksum function + doesn't generate compiler warning */ + #define LWIP_CHKSUM_ALGORITHM 0 + + void* thumb2_memcpy(void* pDest, const void* pSource, size_t length); + u16_t thumb2_checksum(void* pData, int length); +#else + /* Used with IP headers only */ + #define LWIP_CHKSUM_ALGORITHM 1 +#endif + #ifdef LWIP_DEBUG diff --git a/libraries/net/lwip/lwip-sys/arch/checksum.c b/libraries/net/lwip/lwip-sys/arch/checksum.c new file mode 100644 index 0000000000..e97aef39d0 --- /dev/null +++ b/libraries/net/lwip/lwip-sys/arch/checksum.c @@ -0,0 +1,126 @@ +/* Copyright (C) 2013 - Adam Green (https://github.com/adamgreen) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +#if defined(TOOLCHAIN_GCC) && defined(__thumb2__) + + +/* This is a hand written Thumb-2 assembly language version of the + algorithm 3 version of lwip_standard_chksum in lwIP's inet_chksum.c. It + performs the checksumming 32-bits at a time and even unrolls the loop to + perform two of these 32-bit adds per loop iteration. + + Returns: + 16-bit 1's complement summation (not inversed). + + NOTE: This function does return a uint16_t from the assembly language code + but is marked as void so that GCC doesn't issue warning because it + doesn't know about this low level return. +*/ +__attribute__((naked)) void /*uint16_t*/ thumb2_checksum(const void* pData, int length) +{ + __asm ( + ".syntax unified\n" + ".thumb\n" + + // Push non-volatile registers we use on stack. Push link register too to + // keep stack 8-byte aligned and allow single pop to restore and return. + " push {r4, lr}\n" + // Initialize sum, r2, to 0. + " movs r2, #0\n" + // Remember whether pData was at odd address in r3. This is used later to + // know if it needs to swap the result since the summation will be done at + // an offset of 1, rather than 0. + " ands r3, r0, #1\n" + // Need to 2-byte align? If not skip ahead. + " beq 1$\n" + // We can return if there are no bytes to sum. + " cbz r1, 9$\n" + + // 2-byte align. + // Place the first data byte in odd summation location since it needs to be + // swapped later. It's ok to overwrite r2 here as it only had a value of 0 + // up until now. Advance r0 pointer and decrement r1 length as we go. + " ldrb r2, [r0], #1\n" + " lsls r2, r2, #8\n" + " subs r1, r1, #1\n" + + // Need to 4-byte align? If not skip ahead. + "1$:\n" + " ands r4, r0, #3\n" + " beq 2$\n" + // Have more than 1 byte left to align? If not skip ahead to take care of + // trailing byte. + " cmp r1, #2\n" + " blt 7$\n" + + // 4-byte align. + " ldrh r4, [r0], #2\n" + " adds r2, r2, r4\n" + " subs r1, r1, #2\n" + + // Main summing loop which sums up data 2 words at a time. + // Make sure that we have more than 7 bytes left to sum. + "2$:\n" + " cmp r1, #8\n" + " blt 3$\n" + // Sum next two words. Applying previous upper 16-bit carry to + // lower 16-bits. + " ldr r4, [r0], #4\n" + " adds r2, r4\n" + " adc r2, r2, #0\n" + " ldr r4, [r0], #4\n" + " adds r2, r4\n" + " adc r2, r2, #0\n" + " subs r1, r1, #8\n" + " b 2$\n" + + // Sum up any remaining half-words. + "3$:\n" + // Make sure that we have more than 1 byte left to sum. + " cmp r1, #2\n" + " blt 7$\n" + // Sum up next half word, continue to apply carry. + " ldrh r4, [r0], #2\n" + " adds r2, r4\n" + " adc r2, r2, #0\n" + " subs r1, r1, #2\n" + " b 3$\n" + + // Handle trailing byte, if it exists + "7$:\n" + " cbz r1, 8$\n" + " ldrb r4, [r0]\n" + " adds r2, r4\n" + " adc r2, r2, #0\n" + + // Fold 32-bit checksum into 16-bit checksum. + "8$:\n" + " ubfx r4, r2, #16, #16\n" + " ubfx r2, r2, #0, #16\n" + " adds r2, r4\n" + " ubfx r4, r2, #16, #16\n" + " ubfx r2, r2, #0, #16\n" + " adds r2, r4\n" + + // Swap bytes if started at odd address + " cbz r3, 9$\n" + " rev16 r2, r2\n" + + // Return final sum. + "9$: mov r0, r2\n" + " pop {r4, pc}\n" + ); +} + +#endif diff --git a/libraries/net/lwip/lwip-sys/arch/memcpy.c b/libraries/net/lwip/lwip-sys/arch/memcpy.c new file mode 100644 index 0000000000..fefbcda3c2 --- /dev/null +++ b/libraries/net/lwip/lwip-sys/arch/memcpy.c @@ -0,0 +1,59 @@ +/* Copyright (C) 2013 - Adam Green (https://github.com/adamgreen) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +#if defined(TOOLCHAIN_GCC) && defined(__thumb2__) + +#include + + +/* This is a hand written Thumb-2 assembly language version of the + standard C memcpy() function that can be used by the lwIP networking + stack to improve its performance. It copies 4 bytes at a time and + unrolls the loop to perform 4 of these copies per loop iteration. +*/ +__attribute__((naked)) void thumb2_memcpy(void* pDest, const void* pSource, size_t length) +{ + __asm ( + ".syntax unified\n" + ".thumb\n" + + // Copy 16 bytes at a time first. + " lsrs r3, r2, #4\n" + " beq.n 2$\n" + "1$: ldr r12, [r1], #4\n" + " str r12, [r0], #4\n" + " ldr r12, [r1], #4\n" + " str r12, [r0], #4\n" + " ldr r12, [r1], #4\n" + " str r12, [r0], #4\n" + " ldr r12, [r1], #4\n" + " str r12, [r0], #4\n" + " subs r3, #1\n" + " bne 1$\n" + + // Copy byte by byte for what is left. + "2$:\n" + " ands r3, r2, #0xf\n" + " beq.n 4$\n" + "3$: ldrb r12, [r1], #1\n" + " strb r12, [r0], #1\n" + " subs r3, #1\n" + " bne 3$\n" + + // Return to caller. + "4$: bx lr\n" + ); +} + +#endif From 2b57e648a45c2dd860db6f2f0eb96180699eb3e6 Mon Sep 17 00:00:00 2001 From: dinau Date: Sat, 31 Aug 2013 11:34:53 +0900 Subject: [PATCH 16/18] Fixed: [GCC_ARM : LPC1768] Issue ignored the linker option for _print_float and _scanf_float. --- workspace_tools/toolchains/gcc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace_tools/toolchains/gcc.py b/workspace_tools/toolchains/gcc.py index e864c7a7a3..79add1463f 100644 --- a/workspace_tools/toolchains/gcc.py +++ b/workspace_tools/toolchains/gcc.py @@ -140,7 +140,7 @@ class GCC_ARM(GCC): # Use latest gcc nanolib self.ld.append("--specs=nano.specs") - if target in ["LPC1768"]: + if target.name in ["LPC1768"]: self.ld.extend(["-u", "_printf_float", "-u", "_scanf_float"]) self.sys_libs.append("nosys") From 7bcdf0b98030edbbeb8d867e07c99860426573c8 Mon Sep 17 00:00:00 2001 From: dinau Date: Sat, 31 Aug 2013 13:33:34 +0900 Subject: [PATCH 17/18] LPC2368 [GCC_ARM, GCC_CR]: 1. Added: GCC_CR toolchain ID for LPC2368. (targets.py) 2. Modified: Startup codes for GCC_ARM and GCC_CR toolchain. 3. Verified: "ticker" and "basic" test program works well, so far. --- .../TOOLCHAIN_GCC_ARM/LPC2368.ld | 3 +- .../TOOLCHAIN_GCC_ARM/vector_functions.s | 211 ++++++++---------- .../TOOLCHAIN_GCC_ARM/vector_table.s | 4 +- .../TOOLCHAIN_GCC_CR/LPC2368.ld | 6 +- .../TOOLCHAIN_GCC_CR/vector_functions.s | 211 ++++++++---------- .../TOOLCHAIN_GCC_CR/vector_table.s | 4 +- libraries/tests/mbed/ticker/main.cpp | 2 +- workspace_tools/targets.py | 2 +- 8 files changed, 192 insertions(+), 251 deletions(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld index 8d93d6e9d3..d632d65b40 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld @@ -48,7 +48,7 @@ SECTIONS .text : { __privileged_code_start__ = . ; KEEP( *( .vectors ) ) - *( .privileged_code ) + KEEP( *( .privileged_code ) ) __privileged_code_end__ = .; @@ -142,6 +142,7 @@ SECTIONS /* Heap starts here and grows up in memory */ . = ALIGN( 8 ) ; __heap_start__ = . ; + end = . ; .stab 0 (NOLOAD) : { *(.stab) } .stabstr 0 (NOLOAD) : { *(.stabstr) } diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s index 0751c50591..8b4eba394d 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s @@ -1,180 +1,149 @@ -# 1 "vector_functions.s" -# 1 "" -# 1 "" -# 1 "vector_functions.s" -; -; -; +/* .include "vector_defns.h" */ -# 1 "vector_defns.h" 1 -# 6 "vector_functions.s" 2 + + +.section .plivileged_code, "ax" +.arm + + +.weak __mbed_fiq +.weak __mbed_undef +.weak __mbed_prefetch_abort +.weak __mbed_data_abort +.weak __mbed_irq +.weak __mbed_swi +.weak __mbed_dcc_irq +.weak __mbed_reset +.global __mbed_init_realmonitor +/* .global __mbed_init */ - - - .section VECFUNCS, "ax" - .arm - - - .weak __mbed_fiq - .weak __mbed_undef - .weak __mbed_prefetch_abort - .weak __mbed_data_abort - .weak __mbed_irq - .weak __mbed_swi - .weak __mbed_dcc_irq - .weak __mbed_reset - .global __mbed_init_realmonitor - .global __mbed_init - -; -; __mbed_fiq: B __mbed_fiq - -; -; __mbed_undef: LDR PC, =0x7fffffa0 - -; -; __mbed_prefetch_abort: LDR PC, =0x7fffffb0 - -; -; __mbed_data_abort: LDR PC, =0x7fffffc0 - -; -; -; -; -; -; -; -; -; __mbed_irq: - ; MSR CPSR_c, #0x1F|0x80|0x40 - - ; + STMDB sp!, {r0-r3,r12,lr} - - ; + MOV r0, #0xFFFFFF00 LDR r0, [r0] - - ; + MOV lr, pc BX r0 - - ; + MOV r0, #0xFFFFFF00 - STR r0, [r0] ; - - ; + STR r0, [r0] + LDMFD sp!,{r0-r3,r12,lr} - - ; + MSR CPSR_c, #0x12|0x80|0x40 - - ; + SUBS pc, lr, #4 - -; -; -; -; __mbed_swi: - ; - ; STMFD sp!, {a4, r4, ip, lr} - - ; + LDR r4, =0x40000040 - - ; - ; + LDR a4, =0x00940000 LDR PC, =0x7ffff820 - -; -; -; -; __mbed_dcc_irq: - - ; - - ; LDMFD sp!,{r0-r3,r12,lr} - - ; + MSR CPSR_c, #0x12|0x80|0x40 - - ; - - ; - SUB lr, lr, #4 ; - STMFD sp!, {ip,lr} ; - - ; + + SUB lr, lr, #4 + STMFD sp!, {ip,lr} + LDR LR, =0xfffff000 STR LR, [LR, #0xf00] - - ; - ; - ; - ; + LDR PC, =0x7fffffe0 +/* + __mbed_reset is called after reset + we setup the stacks and realmonitor, then call Reset_Handler like on M3 +*/ + +.section .text, "ax" +.arm +.global Reset_handler +Reset_Handler: + .extern __libc_init_array + .extern SystemInit + .extern __wrap_main + LDR R0, =SystemInit + MOV LR, PC + BX R0 + + LDR R0, =__libc_init_array + MOV LR, PC + BX R0 + + LDR R0, =__wrap_main + BX R0 -; -; __mbed_reset: - - ; - - LDR R0, =(0x40000000 + 0x8000) - - ; + LDR R0, =( __SRAM_segment_end__ ) + MSR CPSR_c, #0x1B|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x17|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x11|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000000 - - ; + MSR CPSR_c, #0x12|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x13|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x10 MOV SP, R0 + +/* Relocate .data section (Copy from ROM to RAM) */ + LDR R1, =__text_end__ /* _etext */ + LDR R2, =__data_start__ /* _data */ + LDR R3, =__data_end__ /* _edata */ + CMP R2, R3 + BEQ DataIsEmpty +LoopRel: CMP R2, R3 + LDRLO R0, [R1], #4 + STRLO R0, [R2], #4 + BLO LoopRel +DataIsEmpty: - ; +/* Clear .bss section (Zero init) */ + MOV R0, #0 + LDR R1, =__bss_start__ + LDR R2, =__bss_end__ + CMP R1,R2 + BEQ BSSIsEmpty +LoopZI: CMP R1, R2 + STRLO R0, [R1], #4 + BLO LoopZI +BSSIsEmpty: + + +/* Init realmonitor */ LDR R0, =__mbed_init_realmonitor MOV LR, PC BX R0 - - ; - LDR R0, =__mbed_init + +/* Go to Reset_Handler */ + LDR R0, =Reset_Handler BX R0 diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_table.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_table.s index 281e7a9bd4..d797c3794d 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_table.s +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_table.s @@ -18,7 +18,7 @@ - .section VECTOR_TABLE, "ax" + .section .vectors, "ax" .arm @@ -34,7 +34,7 @@ ; -__main: +_start: LDR PC, =__mbed_reset LDR PC, =__mbed_undef LDR PC, =__mbed_swi diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld index a30d07bbb6..007b1d6a1d 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld @@ -2,7 +2,7 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(vectors) -GROUP(-lsupc++ -lm -lc -lgcc) +GROUP( libgcc.a libc.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o ) /* Memory Definitions: */ MEMORY @@ -50,7 +50,7 @@ SECTIONS .text : { __privileged_code_start__ = . ; KEEP( *( .vectors ) ) - *( .privileged_code ) + KEEP( *( .privileged_code ) ) __privileged_code_end__ = .; @@ -144,6 +144,8 @@ SECTIONS /* Heap starts here and grows up in memory */ . = ALIGN( 8 ) ; __heap_start__ = . ; + _pvHeapStart = . ; + end = . ; .stab 0 (NOLOAD) : { *(.stab) } .stabstr 0 (NOLOAD) : { *(.stabstr) } diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s index 0751c50591..8b4eba394d 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s @@ -1,180 +1,149 @@ -# 1 "vector_functions.s" -# 1 "" -# 1 "" -# 1 "vector_functions.s" -; -; -; +/* .include "vector_defns.h" */ -# 1 "vector_defns.h" 1 -# 6 "vector_functions.s" 2 + + +.section .plivileged_code, "ax" +.arm + + +.weak __mbed_fiq +.weak __mbed_undef +.weak __mbed_prefetch_abort +.weak __mbed_data_abort +.weak __mbed_irq +.weak __mbed_swi +.weak __mbed_dcc_irq +.weak __mbed_reset +.global __mbed_init_realmonitor +/* .global __mbed_init */ - - - .section VECFUNCS, "ax" - .arm - - - .weak __mbed_fiq - .weak __mbed_undef - .weak __mbed_prefetch_abort - .weak __mbed_data_abort - .weak __mbed_irq - .weak __mbed_swi - .weak __mbed_dcc_irq - .weak __mbed_reset - .global __mbed_init_realmonitor - .global __mbed_init - -; -; __mbed_fiq: B __mbed_fiq - -; -; __mbed_undef: LDR PC, =0x7fffffa0 - -; -; __mbed_prefetch_abort: LDR PC, =0x7fffffb0 - -; -; __mbed_data_abort: LDR PC, =0x7fffffc0 - -; -; -; -; -; -; -; -; -; __mbed_irq: - ; MSR CPSR_c, #0x1F|0x80|0x40 - - ; + STMDB sp!, {r0-r3,r12,lr} - - ; + MOV r0, #0xFFFFFF00 LDR r0, [r0] - - ; + MOV lr, pc BX r0 - - ; + MOV r0, #0xFFFFFF00 - STR r0, [r0] ; - - ; + STR r0, [r0] + LDMFD sp!,{r0-r3,r12,lr} - - ; + MSR CPSR_c, #0x12|0x80|0x40 - - ; + SUBS pc, lr, #4 - -; -; -; -; __mbed_swi: - ; - ; STMFD sp!, {a4, r4, ip, lr} - - ; + LDR r4, =0x40000040 - - ; - ; + LDR a4, =0x00940000 LDR PC, =0x7ffff820 - -; -; -; -; __mbed_dcc_irq: - - ; - - ; LDMFD sp!,{r0-r3,r12,lr} - - ; + MSR CPSR_c, #0x12|0x80|0x40 - - ; - - ; - SUB lr, lr, #4 ; - STMFD sp!, {ip,lr} ; - - ; + + SUB lr, lr, #4 + STMFD sp!, {ip,lr} + LDR LR, =0xfffff000 STR LR, [LR, #0xf00] - - ; - ; - ; - ; + LDR PC, =0x7fffffe0 +/* + __mbed_reset is called after reset + we setup the stacks and realmonitor, then call Reset_Handler like on M3 +*/ + +.section .text, "ax" +.arm +.global Reset_handler +Reset_Handler: + .extern __libc_init_array + .extern SystemInit + .extern __wrap_main + LDR R0, =SystemInit + MOV LR, PC + BX R0 + + LDR R0, =__libc_init_array + MOV LR, PC + BX R0 + + LDR R0, =__wrap_main + BX R0 -; -; __mbed_reset: - - ; - - LDR R0, =(0x40000000 + 0x8000) - - ; + LDR R0, =( __SRAM_segment_end__ ) + MSR CPSR_c, #0x1B|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x17|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x11|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000000 - - ; + MSR CPSR_c, #0x12|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x13|0x80|0x40 MOV SP, R0 SUB R0, R0, #0x00000040 - - ; + MSR CPSR_c, #0x10 MOV SP, R0 + +/* Relocate .data section (Copy from ROM to RAM) */ + LDR R1, =__text_end__ /* _etext */ + LDR R2, =__data_start__ /* _data */ + LDR R3, =__data_end__ /* _edata */ + CMP R2, R3 + BEQ DataIsEmpty +LoopRel: CMP R2, R3 + LDRLO R0, [R1], #4 + STRLO R0, [R2], #4 + BLO LoopRel +DataIsEmpty: - ; +/* Clear .bss section (Zero init) */ + MOV R0, #0 + LDR R1, =__bss_start__ + LDR R2, =__bss_end__ + CMP R1,R2 + BEQ BSSIsEmpty +LoopZI: CMP R1, R2 + STRLO R0, [R1], #4 + BLO LoopZI +BSSIsEmpty: + + +/* Init realmonitor */ LDR R0, =__mbed_init_realmonitor MOV LR, PC BX R0 - - ; - LDR R0, =__mbed_init + +/* Go to Reset_Handler */ + LDR R0, =Reset_Handler BX R0 diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_table.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_table.s index 281e7a9bd4..d797c3794d 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_table.s +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_table.s @@ -18,7 +18,7 @@ - .section VECTOR_TABLE, "ax" + .section .vectors, "ax" .arm @@ -34,7 +34,7 @@ ; -__main: +_start: LDR PC, =__mbed_reset LDR PC, =__mbed_undef LDR PC, =__mbed_swi diff --git a/libraries/tests/mbed/ticker/main.cpp b/libraries/tests/mbed/ticker/main.cpp index 5c7082ddfb..09eb230d12 100644 --- a/libraries/tests/mbed/ticker/main.cpp +++ b/libraries/tests/mbed/ticker/main.cpp @@ -13,7 +13,7 @@ void flip_1() { Ticker flipper_2; -#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC4088) || defined(TARGET_LPC1114) +#if defined(TARGET_LPC1768) || defined(TARGET_LPC11U24) || defined(TARGET_LPC4088) || defined(TARGET_LPC1114) || defined(TARGET_LPC2368) # define LED_NAME LED2 #elif defined(TARGET_KL05Z) # define LED_NAME LED2 diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index 0134c734b2..4bc73becdc 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -59,7 +59,7 @@ class LPC2368(Target): self.extra_labels = ['NXP', 'LPC23XX'] - self.supported_toolchains = ["ARM"] + self.supported_toolchains = ["ARM","GCC_ARM","GCC_CR"] class LPC1768(Target): From 8503ccb7a34d79d28247277dbccf5a77acbe25ae Mon Sep 17 00:00:00 2001 From: dinau Date: Sat, 31 Aug 2013 16:00:40 +0900 Subject: [PATCH 18/18] LPC2368 [GCC_ARM, GCC_CR]: 1. Added: GCC_CR toolchain ID for LPC2368. (targets.py) 2. Modified: Startup codes for GCC_ARM and GCC_CR toolchain. 3. Verified: "ticker" and "basic" test program work well, so far. (Fixed typo.) --- .../TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld | 4 ++-- .../TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s | 2 +- .../TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld | 6 +++--- .../TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld index d632d65b40..9267d0ef86 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/LPC2368.ld @@ -48,7 +48,7 @@ SECTIONS .text : { __privileged_code_start__ = . ; KEEP( *( .vectors ) ) - KEEP( *( .privileged_code ) ) + *( .privileged_code ) __privileged_code_end__ = .; @@ -142,7 +142,7 @@ SECTIONS /* Heap starts here and grows up in memory */ . = ALIGN( 8 ) ; __heap_start__ = . ; - end = . ; + end = . ; .stab 0 (NOLOAD) : { *(.stab) } .stabstr 0 (NOLOAD) : { *(.stabstr) } diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s index 8b4eba394d..6e99ec8e08 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_ARM/vector_functions.s @@ -2,7 +2,7 @@ -.section .plivileged_code, "ax" +.section .privileged_code, "ax" .arm diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld index 007b1d6a1d..29c738fbf5 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/LPC2368.ld @@ -50,7 +50,7 @@ SECTIONS .text : { __privileged_code_start__ = . ; KEEP( *( .vectors ) ) - KEEP( *( .privileged_code ) ) + *( .privileged_code ) __privileged_code_end__ = .; @@ -144,8 +144,8 @@ SECTIONS /* Heap starts here and grows up in memory */ . = ALIGN( 8 ) ; __heap_start__ = . ; - _pvHeapStart = . ; - end = . ; + _pvHeapStart = . ; + end = . ; .stab 0 (NOLOAD) : { *(.stab) } .stabstr 0 (NOLOAD) : { *(.stabstr) } diff --git a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s index 8b4eba394d..6e99ec8e08 100644 --- a/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s +++ b/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC23XX/TOOLCHAIN_GCC_CR/vector_functions.s @@ -2,7 +2,7 @@ -.section .plivileged_code, "ax" +.section .privileged_code, "ax" .arm