diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 00b3d3c551d..1803713c068 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -116,6 +116,7 @@ config SIM_NETDEV depends on NET_ETHERNET select ARCH_HAVE_NETDEV_STATISTICS select SCHED_LPWORK + select SIM_WALLTIME ---help--- Build in support for a simulated network device using a TAP device on Linux or WPCAP on Windows. diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index b82d5316383..96a7078ab8a 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -167,7 +167,7 @@ ifeq ($(CONFIG_SIM_NETDEV),y) CSRCS += up_netdriver.c HOSTCFLAGS += -DNETDEV_BUFSIZE=$(CONFIG_NET_ETH_PKTSIZE) ifneq ($(HOSTOS),Cygwin) - HOSTSRCS += up_tapdev.c up_netdev.c + HOSTSRCS += up_tapdev.c ifeq ($(CONFIG_SIM_NET_BRIDGE),y) HOSTCFLAGS += -DCONFIG_SIM_NET_BRIDGE HOSTCFLAGS += -DCONFIG_SIM_NET_BRIDGE_DEVICE=\"$(CONFIG_SIM_NET_BRIDGE_DEVICE)\" @@ -176,7 +176,7 @@ ifeq ($(CONFIG_SIM_NET_HOST_ROUTE),y) HOSTCFLAGS += -DCONFIG_SIM_NET_HOST_ROUTE endif else # HOSTOS != Cygwin - HOSTSRCS += up_wpcap.c up_netdev.c + HOSTSRCS += up_wpcap.c DRVLIB = /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a endif # HOSTOS != Cygwin endif # CONFIG_SIM_NETDEV diff --git a/arch/sim/src/sim/up_internal.h b/arch/sim/src/sim/up_internal.h index f87e709598d..a7fd5897883 100644 --- a/arch/sim/src/sim/up_internal.h +++ b/arch/sim/src/sim/up_internal.h @@ -272,12 +272,6 @@ bool simuart_checkc(void); char *up_deviceimage(void); void up_registerblockdevice(void); -/* up_netdev.c **************************************************************/ - -#ifdef CONFIG_NET -unsigned long up_getwalltime(void); -#endif - /* up_x11framebuffer.c ******************************************************/ #ifdef CONFIG_SIM_X11FB @@ -324,12 +318,14 @@ FAR struct ioexpander_dev_s *sim_ioexpander_initialize(void); #if defined(CONFIG_SIM_NETDEV) && !defined(__CYGWIN__) void tapdev_init(void); +int tapdev_avail(void); unsigned int tapdev_read(unsigned char *buf, unsigned int buflen); void tapdev_send(unsigned char *buf, unsigned int buflen); void tapdev_ifup(in_addr_t ifaddr); void tapdev_ifdown(void); # define netdev_init() tapdev_init() +# define netdev_avail() tapdev_avail() # define netdev_read(buf,buflen) tapdev_read(buf,buflen) # define netdev_send(buf,buflen) tapdev_send(buf,buflen) # define netdev_ifup(ifaddr) tapdev_ifup(ifaddr) @@ -344,6 +340,7 @@ unsigned int wpcap_read(unsigned char *buf, unsigned int buflen); void wpcap_send(unsigned char *buf, unsigned int buflen); # define netdev_init() wpcap_init() +# define netdev_avail() 1 # define netdev_read(buf,buflen) wpcap_read(buf,buflen) # define netdev_send(buf,buflen) wpcap_send(buf,buflen) # define netdev_ifup(ifaddr) {} diff --git a/arch/sim/src/sim/up_netdev.c b/arch/sim/src/sim/up_netdev.c deleted file mode 100644 index 2df0d9abae7..00000000000 --- a/arch/sim/src/sim/up_netdev.c +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** - * arch/sim/src/sim/up_tapdev.c - * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#ifndef NULL -# define NULL (void*)0 -#endif - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -unsigned long up_getwalltime(void) -{ - struct timeval tm; - gettimeofday(&tm, NULL); - return tm.tv_sec*1000 + tm.tv_usec/1000; -} diff --git a/arch/sim/src/sim/up_netdriver.c b/arch/sim/src/sim/up_netdriver.c index d816b96b292..fff5e0c9074 100644 --- a/arch/sim/src/sim/up_netdriver.c +++ b/arch/sim/src/sim/up_netdriver.c @@ -44,14 +44,11 @@ #include -#include -#include +#include #include -#include + #include #include - -#include #include #include @@ -61,31 +58,15 @@ #include "up_internal.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define BUF ((struct eth_hdr_s *)g_sim_dev.d_buf) - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct timer -{ - uint32_t interval; - uint32_t start; -}; - /**************************************************************************** * Private Data ****************************************************************************/ -static struct timer g_periodic_timer; - /* Net driver worker */ -static struct work_s g_network; +static struct work_s g_timer_work; +static struct work_s g_avail_work; +static struct work_s g_recv_work; /* A single packet buffer is used */ @@ -99,29 +80,13 @@ static struct net_driver_s g_sim_dev; * Private Functions ****************************************************************************/ -static void timer_set(struct timer *t, unsigned int interval) +static void netdriver_reply(FAR struct net_driver_s *dev) { - t->interval = interval; - t->start = up_getwalltime(); -} - -static bool timer_expired(struct timer *t) -{ - return (up_getwalltime() - t->start) >= t->interval; -} - -void timer_reset(struct timer *t) -{ - t->start += t->interval; -} - -static int sim_txpoll(struct net_driver_s *dev) -{ - /* If the polling resulted in data that should be sent out on the network, + /* If the receiving resulted in data that should be sent out on the network, * the field d_len is set to a value > 0. */ - if (g_sim_dev.d_len > 0) + if (dev->d_len > 0) { /* Look up the destination MAC address and add it to the Ethernet * header. @@ -129,10 +94,10 @@ static int sim_txpoll(struct net_driver_s *dev) #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 - if (IFF_IS_IPv4(g_sim_dev.d_flags)) + if (IFF_IS_IPv4(dev->d_flags)) #endif { - arp_out(&g_sim_dev); + arp_out(dev); } #endif /* CONFIG_NET_IPv4 */ @@ -141,16 +106,155 @@ static int sim_txpoll(struct net_driver_s *dev) else #endif { - neighbor_out(&g_sim_dev); + neighbor_out(dev); } #endif /* CONFIG_NET_IPv6 */ - if (!devif_loopback(&g_sim_dev)) + /* Send the packet */ + + NETDEV_TXPACKETS(dev); + netdev_send(dev->d_buf, dev->d_len); + NETDEV_TXDONE(dev); + } +} + +static void netdriver_recv_work(FAR void *arg) +{ + FAR struct net_driver_s *dev = arg; + FAR struct eth_hdr_s *eth; + + net_lock(); + + /* netdev_read will return 0 on a timeout event and >0 on a data received event */ + + dev->d_len = netdev_read((FAR unsigned char *)dev->d_buf, + CONFIG_NET_ETH_PKTSIZE); + if (dev->d_len > 0) + { + NETDEV_RXPACKETS(dev); + + /* Data received event. Check for valid Ethernet header with + * destination == our MAC address + */ + + eth = (FAR struct eth_hdr_s *)dev->d_buf; + if (dev->d_len > ETH_HDRLEN) + { +#ifdef CONFIG_NET_PKT + /* When packet sockets are enabled, feed the frame into the packet + * tap. + */ + + pkt_input(dev); +#endif /* CONFIG_NET_PKT */ + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv4 + if (eth->type == HTONS(ETHTYPE_IP)) + { + ninfo("IPv4 frame\n"); + NETDEV_RXIPV4(dev); + + /* Handle ARP on input then give the IPv4 packet to the network + * layer + */ + + arp_ipin(dev); + ipv4_input(dev); + + /* Check for a reply to the IPv4 packet */ + + netdriver_reply(dev); + } + else +#endif /* CONFIG_NET_IPv4 */ +#ifdef CONFIG_NET_IPv6 + if (eth->type == HTONS(ETHTYPE_IP6)) + { + ninfo("Iv6 frame\n"); + NETDEV_RXIPV6(dev); + + /* Give the IPv6 packet to the network layer */ + + ipv6_input(dev); + + /* Check for a reply to the IPv6 packet */ + + netdriver_reply(dev); + } + else +#endif/* CONFIG_NET_IPv6 */ +#ifdef CONFIG_NET_ARP + if (eth->type == htons(ETHTYPE_ARP)) + { + ninfo("ARP frame\n"); + NETDEV_RXARP(dev); + + arp_arpin(dev); + + /* If the above function invocation resulted in data that + * should be sent out on the network, the global variable + * d_len is set to a value > 0. + */ + + if (dev->d_len > 0) + { + netdev_send(dev->d_buf, dev->d_len); + } + } + else +#endif + { + NETDEV_RXDROPPED(dev); + nwarn("WARNING: Unsupported Ethernet type %u\n", eth->type); + } + } + else + { + NETDEV_RXERRORS(dev); + } + } + + net_unlock(); +} + +static int netdriver_txpoll(FAR struct net_driver_s *dev) +{ + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (dev->d_len > 0) + { + /* Look up the destination MAC address and add it to the Ethernet + * header. + */ + +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv4(dev->d_flags)) +#endif + { + arp_out(dev); + } +#endif /* CONFIG_NET_IPv4 */ + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + else +#endif + { + neighbor_out(dev); + } +#endif /* CONFIG_NET_IPv6 */ + + if (!devif_loopback(dev)) { /* Send the packet */ NETDEV_TXPACKETS(dev); - netdev_send(g_sim_dev.d_buf, g_sim_dev.d_len); + netdev_send(dev->d_buf, dev->d_len); NETDEV_TXDONE(dev); } } @@ -162,215 +266,87 @@ static int sim_txpoll(struct net_driver_s *dev) return 0; } -static void netdriver_work(FAR void *arg) +static void netdriver_timer_work(FAR void *arg) { - FAR struct eth_hdr_s *eth; - - /* Check for new frames. If so, then poll the network for new XMIT data */ + FAR struct net_driver_s *dev = arg; net_lock(); - devif_poll(&g_sim_dev, sim_txpoll); + if (IFF_IS_UP(dev->d_flags)) + { + work_queue(LPWORK, &g_timer_work, netdriver_timer_work, dev, CLK_TCK); + devif_timer(dev, CLK_TCK, netdriver_txpoll); + } net_unlock(); +} - /* netdev_read will return 0 on a timeout event and >0 on a data received event */ +static int netdriver_ifup(FAR struct net_driver_s *dev) +{ + netdev_ifup(dev->d_ipaddr); + work_queue(LPWORK, &g_timer_work, netdriver_timer_work, dev, CLK_TCK); + return OK; +} - g_sim_dev.d_len = netdev_read((FAR unsigned char *)g_sim_dev.d_buf, - CONFIG_NET_ETH_PKTSIZE); +static int netdriver_ifdown(FAR struct net_driver_s *dev) +{ + work_cancel(LPWORK, &g_timer_work); + netdev_ifdown(); + return OK; +} - /* Disable preemption through to the following so that it behaves a little more - * like an interrupt (otherwise, the following logic gets pre-empted an behaves - * oddly. - */ +static void netdriver_txavail_work(FAR void *arg) +{ + FAR struct net_driver_s *dev = arg; - sched_lock(); - if (g_sim_dev.d_len > 0) + net_lock(); + if (IFF_IS_UP(dev->d_flags)) { - NETDEV_RXPACKETS(&g_sim_dev); - - /* Data received event. Check for valid Ethernet header with - * destination == our MAC address - */ - - eth = BUF; - if (g_sim_dev.d_len > ETH_HDRLEN) - { -#ifdef CONFIG_NET_PKT - /* When packet sockets are enabled, feed the frame into the packet - * tap. - */ - - pkt_input(&g_sim_dev); -#endif /* CONFIG_NET_PKT */ - - /* We only accept IP packets of the configured type and ARP packets */ - -#ifdef CONFIG_NET_IPv4 - if (eth->type == HTONS(ETHTYPE_IP)) - { - ninfo("IPv4 frame\n"); - NETDEV_RXIPV4(&g_sim_dev); - - /* Handle ARP on input then give the IPv4 packet to the network - * layer - */ - - arp_ipin(&g_sim_dev); - ipv4_input(&g_sim_dev); - - /* If the above function invocation resulted in data that - * should be sent out on the network, the global variable - * d_len is set to a value > 0. - */ - - if (g_sim_dev.d_len > 0) - { - /* Update the Ethernet header with the correct MAC address */ - -#ifdef CONFIG_NET_IPv6 - if (IFF_IS_IPv4(g_sim_dev.d_flags)) -#endif - { - arp_out(&g_sim_dev); - } -#ifdef CONFIG_NET_IPv6 - else - { - neighbor_out(&g_sim_dev); - } -#endif - - /* And send the packet */ - - netdev_send(g_sim_dev.d_buf, g_sim_dev.d_len); - } - } - else -#endif /* CONFIG_NET_IPv4 */ -#ifdef CONFIG_NET_IPv6 - if (eth->type == HTONS(ETHTYPE_IP6)) - { - ninfo("Iv6 frame\n"); - NETDEV_RXIPV6(&g_sim_dev); - - /* Give the IPv6 packet to the network layer */ - - ipv6_input(&g_sim_dev); - - /* If the above function invocation resulted in data that - * should be sent out on the network, the global variable - * d_len is set to a value > 0. - */ - - if (g_sim_dev.d_len > 0) - { - /* Update the Ethernet header with the correct MAC address */ - -#ifdef CONFIG_NET_IPv4 - if (IFF_IS_IPv4(g_sim_dev.d_flags)) - { - arp_out(&g_sim_dev); - } - else -#endif -#ifdef CONFIG_NET_IPv6 - { - neighbor_out(&g_sim_dev); - } -#endif /* CONFIG_NET_IPv6 */ - - /* And send the packet */ - - netdev_send(g_sim_dev.d_buf, g_sim_dev.d_len); - } - } - else -#endif/* CONFIG_NET_IPv6 */ -#ifdef CONFIG_NET_ARP - if (eth->type == htons(ETHTYPE_ARP)) - { - ninfo("ARP frame\n"); - NETDEV_RXARP(&g_sim_dev); - - arp_arpin(&g_sim_dev); - - /* If the above function invocation resulted in data that - * should be sent out on the network, the global variable - * d_len is set to a value > 0. - */ - - if (g_sim_dev.d_len > 0) - { - netdev_send(g_sim_dev.d_buf, g_sim_dev.d_len); - } - } - else -#endif - { - NETDEV_RXDROPPED(&g_sim_dev); - nwarn("WARNING: Unsupported Ethernet type %u\n", eth->type); - } - } - else - { - NETDEV_RXERRORS(&g_sim_dev); - } + devif_poll(dev, netdriver_txpoll); } + net_unlock(); +} - /* Otherwise, it must be a timeout event */ - - else if (timer_expired(&g_periodic_timer)) +static int netdriver_txavail(FAR struct net_driver_s *dev) +{ + if (work_available(&g_avail_work)) { - timer_reset(&g_periodic_timer); - devif_timer(&g_sim_dev, MSEC2TICK(g_periodic_timer.interval), sim_txpoll); + work_queue(LPWORK, &g_avail_work, netdriver_txavail_work, dev, 0); } - - sched_unlock(); + return OK; } /**************************************************************************** * Public Functions ****************************************************************************/ -void netdriver_loop(void) -{ - if (work_available(&g_network)) - { - work_queue(LPWORK, &g_network, netdriver_work, NULL, 0); - } -} - -int netdriver_ifup(struct net_driver_s *dev) -{ - netdev_ifup(dev->d_ipaddr); - return OK; -} - -int netdriver_ifdown(struct net_driver_s *dev) -{ - netdev_ifdown(); - return OK; -} - int netdriver_init(void) { + FAR struct net_driver_s *dev = &g_sim_dev; + /* Internal initialization */ - timer_set(&g_periodic_timer, 500); netdev_init(); /* Set callbacks */ - g_sim_dev.d_buf = g_pktbuf; /* Single packet buffer */ - g_sim_dev.d_ifup = netdriver_ifup; - g_sim_dev.d_ifdown = netdriver_ifdown; + dev->d_buf = g_pktbuf; /* Single packet buffer */ + dev->d_ifup = netdriver_ifup; + dev->d_ifdown = netdriver_ifdown; + dev->d_txavail = netdriver_txavail; /* Register the device with the OS so that socket IOCTLs can be performed */ - netdev_register(&g_sim_dev, NET_LL_ETHERNET); - return OK; + return netdev_register(dev, NET_LL_ETHERNET); } void netdriver_setmacaddr(unsigned char *macaddr) { memcpy(g_sim_dev.d_mac.ether.ether_addr_octet, macaddr, IFHWADDRLEN); } + +void netdriver_loop(void) +{ + if (work_available(&g_recv_work) && netdev_avail()) + { + work_queue(LPWORK, &g_recv_work, netdriver_recv_work, &g_sim_dev, 0); + } +} diff --git a/arch/sim/src/sim/up_tapdev.c b/arch/sim/src/sim/up_tapdev.c index 463e4531cb0..7d2eef9f297 100644 --- a/arch/sim/src/sim/up_tapdev.c +++ b/arch/sim/src/sim/up_tapdev.c @@ -231,11 +231,10 @@ void tapdev_init(void) set_macaddr(); } -unsigned int tapdev_read(unsigned char *buf, unsigned int buflen) +int tapdev_avail(void) { - fd_set fdset; - struct timeval tv; - int ret; + struct timeval tv; + fd_set fdset; /* We can't do anything if we failed to open the tap device */ @@ -247,13 +246,19 @@ unsigned int tapdev_read(unsigned char *buf, unsigned int buflen) /* Wait for data on the tap device (or a timeout) */ tv.tv_sec = 0; - tv.tv_usec = 1000; + tv.tv_usec = 0; FD_ZERO(&fdset); FD_SET(gtapdevfd, &fdset); - ret = select(gtapdevfd + 1, &fdset, NULL, NULL, &tv); - if (ret == 0) + return select(gtapdevfd + 1, &fdset, NULL, NULL, &tv) > 0; +} + +unsigned int tapdev_read(unsigned char *buf, unsigned int buflen) +{ + int ret; + + if (!tapdev_avail()) { return 0; } diff --git a/boards/sim/sim/sim/configs/bluetooth/defconfig b/boards/sim/sim/sim/configs/bluetooth/defconfig index 54e5c9b10ea..2dca3519fbf 100644 --- a/boards/sim/sim/sim/configs/bluetooth/defconfig +++ b/boards/sim/sim/sim/configs/bluetooth/defconfig @@ -66,7 +66,6 @@ CONFIG_SCHED_HAVE_PARENT=y CONFIG_SCHED_ONEXIT=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y -CONFIG_SIM_WALLTIME=y CONFIG_START_DAY=3 CONFIG_START_MONTH=4 CONFIG_SYSTEM_NSH=y diff --git a/boards/sim/sim/sim/configs/rpserver/defconfig b/boards/sim/sim/sim/configs/rpserver/defconfig index 59e6aa20e43..f355d8df5a8 100644 --- a/boards/sim/sim/sim/configs/rpserver/defconfig +++ b/boards/sim/sim/sim/configs/rpserver/defconfig @@ -57,7 +57,6 @@ CONFIG_SCHED_WAITPID=y CONFIG_SIM_M32=y CONFIG_SIM_NET_BRIDGE=y CONFIG_SIM_RPTUN_MASTER=y -CONFIG_SIM_WALLTIME=y CONFIG_SYSLOG_PREFIX=y CONFIG_SYSLOG_PREFIX_STRING="server: " CONFIG_SYSLOG_RPMSG_SERVER=y diff --git a/boards/sim/sim/sim/configs/udgram/defconfig b/boards/sim/sim/sim/configs/udgram/defconfig index cc54d7c1036..20f7986c583 100644 --- a/boards/sim/sim/sim/configs/udgram/defconfig +++ b/boards/sim/sim/sim/configs/udgram/defconfig @@ -48,7 +48,6 @@ CONFIG_SCHED_HAVE_PARENT=y CONFIG_SCHED_ONEXIT=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y -CONFIG_SIM_WALLTIME=y CONFIG_START_MONTH=6 CONFIG_START_YEAR=2008 CONFIG_SYSTEM_NSH=y diff --git a/boards/sim/sim/sim/configs/userfs/defconfig b/boards/sim/sim/sim/configs/userfs/defconfig index 41fc7523501..86a1214d351 100644 --- a/boards/sim/sim/sim/configs/userfs/defconfig +++ b/boards/sim/sim/sim/configs/userfs/defconfig @@ -57,7 +57,6 @@ CONFIG_SCHED_HAVE_PARENT=y CONFIG_SCHED_ONEXIT=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y -CONFIG_SIM_WALLTIME=y CONFIG_START_MONTH=6 CONFIG_START_YEAR=2008 CONFIG_SYSTEM_NSH=y diff --git a/boards/sim/sim/sim/configs/ustream/defconfig b/boards/sim/sim/sim/configs/ustream/defconfig index 208f2f9a318..109351a513a 100644 --- a/boards/sim/sim/sim/configs/ustream/defconfig +++ b/boards/sim/sim/sim/configs/ustream/defconfig @@ -48,7 +48,6 @@ CONFIG_SCHED_HAVE_PARENT=y CONFIG_SCHED_ONEXIT=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y -CONFIG_SIM_WALLTIME=y CONFIG_START_MONTH=6 CONFIG_START_YEAR=2008 CONFIG_SYSTEM_NSH=y