Przeglądaj źródła

ci: update bl & hpm demo

Signed-off-by: sakumisu <1203593632@qq.com>
sakumisu 2 miesięcy temu
rodzic
commit
a2352bffdb

+ 27 - 1
.github/workflows/build_tests.yml

@@ -37,7 +37,33 @@ jobs:
           export HPM_SDK_BASE=~/hpm_sdk
           export GNURISCV_TOOLCHAIN_PATH=~/rv32imac_zicsr_zifencei_multilib_b_ext-linux
           export HPM_SDK_TOOLCHAIN_VARIANT=
-          cmake -S . -B build -GNinja -DBOARD=hpm6750evk2 -DCMAKE_BUILD_TYPE=flash_sdram_xip -DEXTRA_C_FLAGS="-Werror";cmake --build build
+          cmake -S . -B build -GNinja -DBOARD=hpm6800evk -DHPM_BUILD_TYPE=flash_sdram_xip -DCMAKE_BUILD_TYPE=debug -DEXTRA_C_FLAGS="-Werror";cmake --build build
+
+  build_bouffalolab:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v3
+
+      - name: Install dependencies
+        run: sudo apt-get update && sudo apt-get install -y cmake make
+
+      - name: Download bouffalo_sdk
+        run: |
+          cd ~
+          git clone https://github.com/bouffalolab/bouffalo_sdk.git
+
+      - name: Download RISC-V toolchain
+        run: |
+          cd ~
+          git clone https://github.com/bouffalolab/toolchain_gcc_t-head_linux.git
+
+      - name: Build bouffalo demo
+        run: |
+          cd tests/bouffalolab
+          export BL_SDK_BASE=~/bouffalo_sdk
+          export PATH=~/toolchain_gcc_t-head_linux/bin:$PATH
+          make CHIP=bl616 BOARD=bl616dk -j12
 
   build_espressif:
     strategy:

+ 46 - 0
tests/bouffalolab/CMakeLists.txt

@@ -0,0 +1,46 @@
+cmake_minimum_required(VERSION 3.15)
+
+include(proj.conf)
+
+find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
+
+sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_ECM)
+sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_NCM)
+sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_RNDIS)
+sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_ASIX)
+sdk_add_compile_definitions(-DCONFIG_USBHOST_PLATFORM_RTL8152)
+sdk_add_include_directories(inc)
+
+target_sources(app PRIVATE ../../demo/usb_host.c)
+
+set(CONFIG_CHERRYMP 1)
+set(CONFIG_CHERRYUSB 1)
+set(CONFIG_CHERRYUSB_DEVICE 1)
+set(CONFIG_CHERRYUSB_HOST 1)
+
+set(CONFIG_CHERRYUSB_DEVICE_CDC_RNDIS 1)
+set(CONFIG_CHERRYUSB_DEVICE_CDC_ECM 1)
+
+# add_subdirectory(src/cherryusb_hostuvcuac)
+add_subdirectory(../.. cherryusb)
+
+# sdk_add_link_options(-uusbd_cdc_acm_init_intf)
+# sdk_add_link_options(-uusbd_hid_init_intf)
+# sdk_add_link_options(-uusbd_msc_init_intf)
+# sdk_add_link_options(-uusbd_video_init_intf)
+# sdk_add_link_options(-uusbd_audio_init_intf)
+# sdk_add_link_options(-uusbd_cdc_ecm_init_intf)
+# sdk_add_link_options(-uusbd_rndis_init_intf)
+# sdk_add_link_options(-uusbd_initialize)
+# sdk_add_link_options(-uusbd_desc_register)
+# sdk_add_link_options(-uusbd_add_interface)
+# sdk_add_link_options(-uusbd_add_endpoint)
+# sdk_add_link_options(-uusbd_rndis_start_write)
+# sdk_add_link_options(-uusbd_rndis_start_read)
+# sdk_add_link_options(-uusbd_cdc_ecm_start_write)
+# sdk_add_link_options(-uusbd_cdc_ecm_start_read)
+# sdk_add_link_options(-uusbd_video_stream_start_write)
+# sdk_add_link_options(-uusbd_video_stream_split_transfer)
+
+sdk_set_main_file(src/main.c)
+project(cherryusb)

+ 13 - 0
tests/bouffalolab/Makefile

@@ -0,0 +1,13 @@
+SDK_DEMO_PATH ?= .
+BL_SDK_BASE ?= /home/sakumisu/repo/bouffalolab/bouffalo_sdk_github
+
+export BL_SDK_BASE
+
+CHIP ?= bl616
+BOARD ?= bl616dk
+CROSS_COMPILE = riscv64-unknown-elf-
+
+# add custom cmake definition
+#cmake_definition+=-Dxxx=sss
+
+include $(BL_SDK_BASE)/project.build

+ 14 - 0
tests/bouffalolab/flash_prog_cfg.ini

@@ -0,0 +1,14 @@
+[cfg]
+# 0: no erase, 1:programmed section erase, 2: chip erase
+erase = 1
+# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
+skip_mode = 0x0, 0x0
+# 0: not use isp mode, #1: isp mode
+boot2_isp_mode = 0
+pre_program = 
+pre_program_args = 
+
+[FW]
+filedir = ./build/build_out/cherryusb*_$(CHIPNAME).bin
+address = 0x000000
+

+ 128 - 0
tests/bouffalolab/inc/FreeRTOSConfig.h

@@ -0,0 +1,128 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+#if defined(BL602) || defined(BL702) || defined(BL702L)
+#define configMTIME_BASE_ADDRESS    (0x02000000UL + 0xBFF8UL)
+#define configMTIMECMP_BASE_ADDRESS (0x02000000UL + 0x4000UL)
+#else
+#if __riscv_xlen == 64
+#define configMTIME_BASE_ADDRESS    (0)
+#define configMTIMECMP_BASE_ADDRESS ((0xE4000000UL) + 0x4000UL)
+#else
+#define configMTIME_BASE_ADDRESS    ((0xE0000000UL) + 0xBFF8UL)
+#define configMTIMECMP_BASE_ADDRESS ((0xE0000000UL) + 0x4000UL)
+#endif
+#endif
+
+#define configSUPPORT_STATIC_ALLOCATION         1
+#define configUSE_PREEMPTION                    1
+#define configUSE_IDLE_HOOK                     0
+#define configUSE_TICK_HOOK                     0
+#define configCPU_CLOCK_HZ                      ((uint32_t)(1 * 1000 * 1000))
+#define configTICK_RATE_HZ                      ((TickType_t)1000)
+#define configMAX_PRIORITIES                    (32)
+#define configMINIMAL_STACK_SIZE                ((unsigned short)128) /* Only needs to be this high as some demo tasks also use this constant.  In production only the idle task would use this. */
+#define configTOTAL_HEAP_SIZE                   ((size_t)24 * 1024)
+#define configMAX_TASK_NAME_LEN                 (16)
+#define configUSE_TRACE_FACILITY                1
+#define configUSE_STATS_FORMATTING_FUNCTIONS    1
+#define configUSE_16_BIT_TICKS                  0
+#define configIDLE_SHOULD_YIELD                 0
+#define configUSE_MUTEXES                       1
+#define configQUEUE_REGISTRY_SIZE               8
+#define configCHECK_FOR_STACK_OVERFLOW          2
+#define configUSE_RECURSIVE_MUTEXES             1
+#define configUSE_MALLOC_FAILED_HOOK            1
+#define configUSE_APPLICATION_TASK_TAG          1
+#define configUSE_COUNTING_SEMAPHORES           1
+#define configGENERATE_RUN_TIME_STATS           0
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+#define configUSE_TICKLESS_IDLE                 0
+#define configUSE_POSIX_ERRNO                   1
+
+#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 0
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES                   0
+#define configMAX_CO_ROUTINE_PRIORITIES         (2)
+
+/* Software timer definitions. */
+#define configUSE_TIMERS                        1
+#define configTIMER_TASK_PRIORITY               (configMAX_PRIORITIES - 1)
+#define configTIMER_QUEUE_LENGTH                4
+#define configTIMER_TASK_STACK_DEPTH            (512)
+/* Task priorities.  Allow these to be overridden. */
+#ifndef uartPRIMARY_PRIORITY
+#define uartPRIMARY_PRIORITY (configMAX_PRIORITIES - 3)
+#endif
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+#define INCLUDE_vTaskPrioritySet         1
+#define INCLUDE_uxTaskPriorityGet        1
+#define INCLUDE_vTaskDelete              1
+#define INCLUDE_vTaskCleanUpResources    1
+#define INCLUDE_vTaskSuspend             1
+#define INCLUDE_vTaskDelayUntil          1
+#define INCLUDE_vTaskDelay               1
+#define INCLUDE_eTaskGetState            1
+#define INCLUDE_xTimerPendFunctionCall   1
+#define INCLUDE_xTaskAbortDelay          1
+#define INCLUDE_xTaskGetHandle           1
+#define INCLUDE_xSemaphoreGetMutexHolder 1
+/* Normal assert() semantics without relying on the provision of an assert.h
+header file. */
+void vApplicationMallocFailedHook(void);
+void vAssertCalled(void);
+
+#include <stdio.h>
+
+#define configASSERT(x)                        \
+    if ((x) == 0) {                            \
+        printf("file [%s]\r\n", __FILE__);     \
+        printf("func [%s]\r\n", __FUNCTION__); \
+        printf("line [%d]\r\n", __LINE__);     \
+        printf("%s\r\n", (const char *)(#x));  \
+        vAssertCalled();                       \
+    }
+#if (configUSE_TICKLESS_IDLE != 0)
+void vApplicationSleep(uint32_t xExpectedIdleTime);
+#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vApplicationSleep(xExpectedIdleTime)
+#endif
+// #define portUSING_MPU_WRAPPERS
+#endif /* FREERTOS_CONFIG_H */

+ 270 - 0
tests/bouffalolab/inc/fatfs_conf_user.h

@@ -0,0 +1,270 @@
+/*---------------------------------------------------------------------------/
+/  Configurations of FatFs Module
+/---------------------------------------------------------------------------*/
+
+/* User external configuration, User need to use this file as a template.
+All configuration items must be included in the file */
+
+/*---------------------------------------------------------------------------/
+/ Function Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_CONTINUOUS 1
+/* Read and write as much data as possible at one time, regardless of the cluster size */
+
+#define FF_FS_READONLY 0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/  Read-only configuration removes writing API functions, f_write(), f_sync(),
+/  f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/  and optional writing functions as well. */
+
+#define FF_FS_MINIMIZE 0
+/* This option defines minimization level to remove some basic API functions.
+/
+/   0: Basic functions are fully enabled.
+/   1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/      are removed.
+/   2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
+/   3: f_lseek() function is removed in addition to 2. */
+
+#define FF_USE_FIND 1
+/* This option switches filtered directory read functions, f_findfirst() and
+/  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
+
+#define FF_USE_MKFS 1
+/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
+
+#define FF_USE_FASTSEEK 1
+/* This option switches fast seek function. (0:Disable or 1:Enable) */
+
+#define FF_USE_EXPAND 0
+/* This option switches f_expand function. (0:Disable or 1:Enable) */
+
+#define FF_USE_CHMOD 0
+/* This option switches attribute manipulation functions, f_chmod() and f_utime().
+/  (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
+
+#define FF_USE_LABEL 0
+/* This option switches volume label functions, f_getlabel() and f_setlabel().
+/  (0:Disable or 1:Enable) */
+
+#define FF_USE_FORWARD 0
+/* This option switches f_forward() function. (0:Disable or 1:Enable) */
+
+#define FF_USE_STRFUNC 0
+#define FF_PRINT_LLI   1
+#define FF_PRINT_FLOAT 1
+#define FF_STRF_ENCODE 3
+/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
+/  f_printf().
+/
+/   0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
+/   1: Enable without LF-CRLF conversion.
+/   2: Enable with LF-CRLF conversion.
+/
+/  FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
+/  makes f_printf() support floating point argument. These features want C99 or later.
+/  When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
+/  encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
+/  to be read/written via those functions.
+/
+/   0: ANSI/OEM in current CP
+/   1: Unicode in UTF-16LE
+/   2: Unicode in UTF-16BE
+/   3: Unicode in UTF-8
+*/
+
+/*---------------------------------------------------------------------------/
+/ Locale and Namespace Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_CODE_PAGE 437
+/* This option specifies the OEM code page to be used on the target system.
+/  Incorrect code page setting can cause a file open failure.
+/
+/   437 - U.S.
+/   720 - Arabic
+/   737 - Greek
+/   771 - KBL
+/   775 - Baltic
+/   850 - Latin 1
+/   852 - Latin 2
+/   855 - Cyrillic
+/   857 - Turkish
+/   860 - Portuguese
+/   861 - Icelandic
+/   862 - Hebrew
+/   863 - Canadian French
+/   864 - Arabic
+/   865 - Nordic
+/   866 - Russian
+/   869 - Greek 2
+/   932 - Japanese (DBCS)
+/   936 - Simplified Chinese (DBCS)
+/   949 - Korean (DBCS)
+/   950 - Traditional Chinese (DBCS)
+/     0 - Include all code pages above and configured by f_setcp()
+*/
+
+#define FF_USE_LFN 2
+#define FF_MAX_LFN 255
+/* The FF_USE_LFN switches the support for LFN (long file name).
+/
+/   0: Disable LFN. FF_MAX_LFN has no effect.
+/   1: Enable LFN with static  working buffer on the BSS. Always NOT thread-safe.
+/   2: Enable LFN with dynamic working buffer on the STACK.
+/   3: Enable LFN with dynamic working buffer on the HEAP.
+/
+/  To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
+/  requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
+/  additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
+/  The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
+/  be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN
+/  specification.
+/  When use stack for the working buffer, take care on stack overflow. When use heap
+/  memory for the working buffer, memory management functions, ff_memalloc() and
+/  ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
+
+#define FF_LFN_UNICODE 0
+/* This option switches the character encoding on the API when LFN is enabled.
+/
+/   0: ANSI/OEM in current CP (TCHAR = char)
+/   1: Unicode in UTF-16 (TCHAR = WCHAR)
+/   2: Unicode in UTF-8 (TCHAR = char)
+/   3: Unicode in UTF-32 (TCHAR = DWORD)
+/
+/  Also behavior of string I/O functions will be affected by this option.
+/  When LFN is not enabled, this option has no effect. */
+
+#define FF_LFN_BUF 255
+#define FF_SFN_BUF 12
+/* This set of options defines size of file name members in the FILINFO structure
+/  which is used to read out directory items. These values should be suffcient for
+/  the file names to read. The maximum possible length of the read file name depends
+/  on character encoding. When LFN is not enabled, these options have no effect. */
+
+#define FF_FS_RPATH 0
+/* This option configures support for relative path.
+/
+/   0: Disable relative path and remove related functions.
+/   1: Enable relative path. f_chdir() and f_chdrive() are available.
+/   2: f_getcwd() function is available in addition to 1.
+*/
+
+/*---------------------------------------------------------------------------/
+/ Drive/Volume Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_VOLUMES 5
+/* Number of volumes (logical drives) to be used. (1-10) */
+
+#define FF_STR_VOLUME_ID 2
+#define FF_VOLUME_STRS   "ram", "flash", "sd", "sd2", "usb"
+/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
+/  When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
+/  number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
+/  logical drives. Number of items must not be less than FF_VOLUMES. Valid
+/  characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
+/  compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
+/  not defined, a user defined volume string table is needed as:
+/
+/  const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
+*/
+
+#define FF_MULTI_PARTITION 0
+/* This option switches support for multiple volumes on the physical drive.
+/  By default (0), each logical drive number is bound to the same physical drive
+/  number and only an FAT volume found on the physical drive will be mounted.
+/  When this function is enabled (1), each logical drive number can be bound to
+/  arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/  function will be available. */
+
+#define FF_MIN_SS 512
+#define FF_MAX_SS 512
+/* This set of options configures the range of sector size to be supported. (512,
+/  1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
+/  harddisk, but a larger value may be required for on-board flash memory and some
+/  type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
+/  for variable sector size mode and disk_ioctl() function needs to implement
+/  GET_SECTOR_SIZE command. */
+
+#define FF_LBA64 0
+/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
+/  To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
+
+#define FF_MIN_GPT 0x10000000
+/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
+/  f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
+
+#define FF_USE_TRIM 0
+/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
+/  To enable Trim function, also CTRL_TRIM command should be implemented to the
+/  disk_ioctl() function. */
+
+/*---------------------------------------------------------------------------/
+/ System Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_TINY 0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/  At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
+/  Instead of private sector buffer eliminated from the file object, common sector
+/  buffer in the filesystem object (FATFS) is used for the file data transfer. */
+
+#define FF_FS_EXFAT 0
+/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
+/  To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
+/  Note that enabling exFAT discards ANSI C (C89) compatibility. */
+
+#define FF_FS_NORTC   1
+#define FF_NORTC_MON  1
+#define FF_NORTC_MDAY 1
+#define FF_NORTC_YEAR 2022
+/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
+/  an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
+/  timestamp feature. Every object modified by FatFs will have a fixed timestamp
+/  defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
+/  To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
+/  added to the project to read current time form real-time clock. FF_NORTC_MON,
+/  FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
+/  These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
+
+#define FF_FS_NOFSINFO 0
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/  option, and f_getfree() function at the first time after volume mount will force
+/  a full FAT scan. Bit 1 controls the use of last allocated cluster number.
+/
+/  bit0=0: Use free cluster count in the FSINFO if available.
+/  bit0=1: Do not trust free cluster count in the FSINFO.
+/  bit1=0: Use last allocated cluster number in the FSINFO if available.
+/  bit1=1: Do not trust last allocated cluster number in the FSINFO.
+*/
+
+#define FF_FS_LOCK 0
+/* The option FF_FS_LOCK switches file lock function to control duplicated file open
+/  and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
+/  is 1.
+/
+/  0:  Disable file lock function. To avoid volume corruption, application program
+/      should avoid illegal open, remove and rename to the open objects.
+/  >0: Enable file lock function. The value defines how many files/sub-directories
+/      can be opened simultaneously under file lock control. Note that the file
+/      lock control is independent of re-entrancy. */
+
+#define FF_FS_REENTRANT 0
+#define FF_FS_TIMEOUT   1000
+/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/  module itself. Note that regardless of this option, file access to different
+/  volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/  and f_fdisk() function, are always not re-entrant. Only file/directory access
+/  to the same volume is under control of this featuer.
+/
+/   0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
+/   1: Enable re-entrancy. Also user provided synchronization handlers,
+/      ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
+/      function, must be added to the project. Samples are available in ffsystem.c.
+/
+/  The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
+*/
+
+/*--- End of configuration options ---*/

+ 442 - 0
tests/bouffalolab/inc/lwipopts_user.h

@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2025, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef LWIPOPTS_H
+#define LWIPOPTS_H
+
+#ifdef USE_LWIPOPTS_APP_H
+#include "lwipopts_app.h"
+#endif
+
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT 1
+#define IP_REASSEMBLY        0
+#define IP_FRAG              0
+#define ARP_QUEUEING         0
+#define NO_SYS               0
+#define LWIP_RAND            rand
+
+#define LWIP_NETIF_HOSTNAME  0
+#define LWIP_TIMEVAL_PRIVATE 0
+#define LWIP_TIMERS          1
+#define LWIP_RAW             1
+#define LWIP_IPV4            1
+#define LWIP_IGMP            1
+#define LWIP_ICMP            1
+#define ICMP_TTL             64
+#define LWIP_TCP             1
+#define TCP_TTL              255
+#define LWIP_UDP             1
+#define UDP_TTL              255
+#define LWIP_DNS             1
+
+/**
+ * LWIP_NETIF_API==1: Support netif api (in netifapi.c)
+ */
+#define LWIP_NETIF_API 1
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN 1
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET 1
+
+/* ---------- Memory options ---------- */
+#define MEMP_MEM_MALLOC 0
+
+/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
+   lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
+   byte alignment -> define MEM_ALIGNMENT to 2. */
+#ifndef MEM_ALIGNMENT
+#define MEM_ALIGNMENT 64
+#endif
+
+/* MEM_SIZE: the size of the heap memory. If the application will send
+a lot of data that needs to be copied, this should be set high. */
+#ifndef MEM_SIZE
+#define MEM_SIZE (32 * 1024)
+#endif
+
+/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
+   sends a lot of data out of ROM (or other static memory), this
+   should be set high. */
+#ifndef MEMP_NUM_PBUF
+#define MEMP_NUM_PBUF 100
+#endif
+
+/**
+ * MEMP_NUM_RAW_PCB: Number of raw connection PCBs
+ * (requires the LWIP_RAW option)
+ */
+#ifndef MEMP_NUM_RAW_PCB
+#define MEMP_NUM_RAW_PCB 4
+#endif
+
+/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+   per active UDP "connection". */
+#ifndef MEMP_NUM_UDP_PCB
+#define MEMP_NUM_UDP_PCB 4
+#endif
+
+/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
+   connections. */
+#ifndef MEMP_NUM_TCP_PCB
+#define MEMP_NUM_TCP_PCB 4
+#endif
+
+/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
+   connections. */
+#ifndef MEMP_NUM_TCP_PCB_LISTEN
+#define MEMP_NUM_TCP_PCB_LISTEN 5
+#endif
+
+/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
+   segments. */
+#ifndef MEMP_NUM_TCP_SEG
+#define MEMP_NUM_TCP_SEG 40
+#endif
+
+/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
+   timeouts. */
+#ifndef MEMP_NUM_SYS_TIMEOUT
+#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL)
+#endif
+
+/**
+ * MEMP_NUM_NETCONN: the number of struct netconns.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#ifndef MEMP_NUM_NETCONN
+#define MEMP_NUM_NETCONN 4
+#endif
+
+/* ---------- Pbuf options ---------- */
+/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
+#ifndef PBUF_POOL_SIZE
+#define PBUF_POOL_SIZE 20
+#endif
+
+/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
+#ifndef PBUF_POOL_BUFSIZE
+#define PBUF_POOL_BUFSIZE 1600
+#endif
+
+/* ---------- TCP options ---------- */
+/* Controls if TCP should queue segments that arrive out of
+   order. Define to 0 if your device is low on memory. */
+#ifndef TCP_QUEUE_OOSEQ
+#define TCP_QUEUE_OOSEQ 0
+#endif
+
+/* TCP Maximum segment size. */
+#ifndef TCP_MSS
+#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
+#endif
+
+/* TCP sender buffer space (bytes). */
+#ifndef TCP_SND_BUF
+#define TCP_SND_BUF (8 * TCP_MSS)
+#endif
+
+/*  TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
+  as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
+#ifndef TCP_SND_QUEUELEN
+#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF / TCP_MSS)
+#endif
+
+/* TCP receive window. */
+#ifndef TCP_WND
+#define TCP_WND (16 * TCP_MSS)
+#endif
+
+/* ---------- DHCP options ---------- */
+/* Define LWIP_DHCP to 1 if you want DHCP configuration of
+   interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
+   turning this on does currently not work. */
+#ifndef LWIP_DHCP
+#define LWIP_DHCP 1
+#endif
+
+/* ---------- Statistics options ---------- */
+#ifndef LWIP_STATS
+#define LWIP_STATS 0
+#endif
+
+#ifndef LWIP_PROVIDE_ERRNO
+#define LWIP_PROVIDE_ERRNO 1
+#endif
+
+/*
+   ------------------------------------------------
+   ---------- Network Interfaces options ----------
+   ------------------------------------------------
+*/
+/**
+ * LWIP_SINGLE_NETIF==1: use a single netif only. This is the common case for
+ * small real-life targets. Some code like routing etc. can be left out.
+ */
+#ifndef LWIP_SINGLE_NETIF
+#define LWIP_SINGLE_NETIF 1
+#endif
+
+/* ---------- link callback options ---------- */
+/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
+ * whenever the link changes (i.e., link down)
+ */
+#ifndef LWIP_NETIF_LINK_CALLBACK
+#define LWIP_NETIF_LINK_CALLBACK 1
+#endif
+
+/**
+ * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP *tries* to put all data
+ * to be sent into one single pbuf. This is for compatibility with DMA-enabled
+ * MACs that do not support scatter-gather.
+ * Beware that this might involve CPU-memcpy before transmitting that would not
+ * be needed without this flag! Use this only if you need to!
+ *
+ * ATTENTION: a driver should *NOT* rely on getting single pbufs but check TX
+ * pbufs for being in one piece. If not, @ref pbuf_clone can be used to get
+ * a single pbuf:
+ *   if (p->next != NULL) {
+ *     struct pbuf *q = pbuf_clone(PBUF_RAW, PBUF_RAM, p);
+ *     if (q == NULL) {
+ *       return ERR_MEM;
+ *     }
+ *     p = q; ATTENTION: do NOT free the old 'p' as the ref belongs to the caller!
+ *   }
+ */
+#ifndef LWIP_NETIF_TX_SINGLE_PBUF
+#define LWIP_NETIF_TX_SINGLE_PBUF 0
+#endif
+
+/*
+   --------------------------------------
+   ---------- Checksum options ----------
+   --------------------------------------
+*/
+
+/*
+ * Some MCUs allow computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
+ * To use this feature let the following define uncommented.
+ * To disable it and process by CPU comment the  the checksum.
+*/
+#ifdef CHECKSUM_BY_HARDWARE
+/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
+#define CHECKSUM_GEN_IP 0
+/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
+#define CHECKSUM_GEN_UDP 0
+/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
+#define CHECKSUM_GEN_TCP 0
+/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
+#define CHECKSUM_CHECK_IP 0
+/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
+#define CHECKSUM_CHECK_UDP 0
+/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
+#define CHECKSUM_CHECK_TCP 0
+/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
+#define CHECKSUM_GEN_ICMP 0
+#else
+/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
+#define CHECKSUM_GEN_IP    1
+/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
+#define CHECKSUM_GEN_UDP   1
+/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
+#define CHECKSUM_GEN_TCP   1
+/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
+#define CHECKSUM_CHECK_IP  1
+/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
+#define CHECKSUM_CHECK_UDP 1
+/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
+#define CHECKSUM_CHECK_TCP 1
+/* CHECKSUM_CHECK_ICMP==1: Check checksums by software for incoming ICMP packets.*/
+#define CHECKSUM_GEN_ICMP  1
+#endif
+
+/*
+   -----------------------------------
+   ---------- DEBUG options ----------
+   -----------------------------------
+*/
+#ifdef LWIP_DEBUG
+
+#ifndef LWIP_DBG_MIN_LEVEL
+#define LWIP_DBG_MIN_LEVEL 0
+#endif
+
+#ifndef PPP_DEBUG
+#define PPP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef MEM_DEBUG
+#define MEM_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef MEMP_DEBUG
+#define MEMP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef PBUF_DEBUG
+#define PBUF_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef API_LIB_DEBUG
+#define API_LIB_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef API_MSG_DEBUG
+#define API_MSG_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCPIP_DEBUG
+#define TCPIP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef NETIF_DEBUG
+#define NETIF_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef SOCKETS_DEBUG
+#define SOCKETS_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef DNS_DEBUG
+#define DNS_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef AUTOIP_DEBUG
+#define AUTOIP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef DHCP_DEBUG
+#define DHCP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef IP_DEBUG
+#define IP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef IP_REASS_DEBUG
+#define IP_REASS_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef ICMP_DEBUG
+#define ICMP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef IGMP_DEBUG
+#define IGMP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef UDP_DEBUG
+#define UDP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_DEBUG
+#define TCP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_INPUT_DEBUG
+#define TCP_INPUT_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_OUTPUT_DEBUG
+#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_RTO_DEBUG
+#define TCP_RTO_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_CWND_DEBUG
+#define TCP_CWND_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_WND_DEBUG
+#define TCP_WND_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_FR_DEBUG
+#define TCP_FR_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_QLEN_DEBUG
+#define TCP_QLEN_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_RST_DEBUG
+#define TCP_RST_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef ETHARP_DEBUG
+#define ETHARP_DEBUG LWIP_DBG_OFF
+#endif
+
+#endif
+
+/*
+   ---------------------------------
+   ---------- OS options ----------
+   ---------------------------------
+*/
+#ifndef TCPIP_THREAD_NAME
+#define TCPIP_THREAD_NAME "tcpip"
+#endif
+
+#ifndef TCPIP_THREAD_STACKSIZE
+#define TCPIP_THREAD_STACKSIZE 2048
+#endif
+
+#ifndef TCPIP_MBOX_SIZE
+#define TCPIP_MBOX_SIZE 8
+#endif
+
+#ifndef DEFAULT_RAW_RECVMBOX_SIZE
+#define DEFAULT_RAW_RECVMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_UDP_RECVMBOX_SIZE
+#define DEFAULT_UDP_RECVMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_TCP_RECVMBOX_SIZE
+#define DEFAULT_TCP_RECVMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_ACCEPTMBOX_SIZE
+#define DEFAULT_ACCEPTMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_THREAD_STACKSIZE
+#define DEFAULT_THREAD_STACKSIZE 500
+#endif
+
+#ifndef TCPIP_THREAD_PRIO
+#define TCPIP_THREAD_PRIO 10
+#endif
+
+#define LWIP_COMPAT_MUTEX       0
+#define LWIP_TCPIP_CORE_LOCKING 1
+
+#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT
+#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
+#endif
+
+#ifndef LWIP_MEM_SECTION
+#define LWIP_MEM_SECTION ".bss"
+#endif
+
+// bouffalo patch
+#define LWIP_DNS_SERVER          0
+#define LWIP_SUPPORT_CUSTOM_PBUF 1
+
+#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] __attribute__((section(LWIP_MEM_SECTION)))
+
+#endif /* __LWIPOPTS_H__ */

+ 325 - 0
tests/bouffalolab/inc/usb_config.h

@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef CHERRYUSB_CONFIG_H
+#define CHERRYUSB_CONFIG_H
+
+/* ================ USB common Configuration ================ */
+#include "bflb_core.h"
+
+#ifdef __RTTHREAD__
+#include <rtthread.h>
+
+#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
+#else
+#define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__)
+#endif
+
+#ifndef CONFIG_USB_DBG_LEVEL
+#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
+#endif
+
+/* Enable print with color */
+#define CONFIG_USB_PRINTF_COLOR_ENABLE
+
+// #define CONFIG_USB_DCACHE_ENABLE
+
+/* data align size when use dma or use dcache */
+#ifdef CONFIG_USB_DCACHE_ENABLE
+#define CONFIG_USB_ALIGN_SIZE 32 // 32 or 64
+#else
+#define CONFIG_USB_ALIGN_SIZE 4
+#endif
+
+/* attribute data into no cache ram */
+#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
+
+/* use usb_memcpy default for high performance but cost more flash memory.
+ * And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
+*/
+// #define CONFIG_USB_MEMCPY_DISABLE
+
+/* ================= USB Device Stack Configuration ================ */
+
+/* Ep0 in and out transfer buffer */
+#ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN
+#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
+#endif
+
+/* Send ep0 in data from user buffer instead of copying into ep0 reqdata
+ * Please note that user buffer must be aligned with CONFIG_USB_ALIGN_SIZE
+*/
+// #define CONFIG_USBDEV_EP0_INDATA_NO_COPY
+
+/* Check if the input descriptor is correct */
+// #define CONFIG_USBDEV_DESC_CHECK
+
+/* Enable test mode */
+// #define CONFIG_USBDEV_TEST_MODE
+
+/* enable advance desc register api */
+#define CONFIG_USBDEV_ADVANCE_DESC
+
+/* move ep0 setup handler from isr to thread */
+// #define CONFIG_USBDEV_EP0_THREAD
+
+#ifndef CONFIG_USBDEV_EP0_PRIO
+#define CONFIG_USBDEV_EP0_PRIO 4
+#endif
+
+#ifndef CONFIG_USBDEV_EP0_STACKSIZE
+#define CONFIG_USBDEV_EP0_STACKSIZE 2048
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MAX_LUN
+#define CONFIG_USBDEV_MSC_MAX_LUN 1
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MAX_BUFSIZE
+#define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
+#define CONFIG_USBDEV_MSC_MANUFACTURER_STRING ""
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING
+#define CONFIG_USBDEV_MSC_PRODUCT_STRING ""
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_VERSION_STRING
+#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
+#endif
+
+/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */
+// #define CONFIG_USBDEV_MSC_POLLING
+
+/* move msc read & write from isr to thread */
+// #define CONFIG_USBDEV_MSC_THREAD
+
+#ifndef CONFIG_USBDEV_MSC_PRIO
+#define CONFIG_USBDEV_MSC_PRIO 4
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_STACKSIZE
+#define CONFIG_USBDEV_MSC_STACKSIZE 2048
+#endif
+
+#ifndef CONFIG_USBDEV_MTP_MAX_BUFSIZE
+#define CONFIG_USBDEV_MTP_MAX_BUFSIZE 2048
+#endif
+
+#ifndef CONFIG_USBDEV_MTP_MAX_OBJECTS
+#define CONFIG_USBDEV_MTP_MAX_OBJECTS 256
+#endif
+
+#ifndef CONFIG_USBDEV_MTP_MAX_PATHNAME
+#define CONFIG_USBDEV_MTP_MAX_PATHNAME 256
+#endif
+
+#define CONFIG_USBDEV_MTP_THREAD
+
+#ifndef CONFIG_USBDEV_MTP_PRIO
+#define CONFIG_USBDEV_MTP_PRIO 4
+#endif
+
+#ifndef CONFIG_USBDEV_MTP_STACKSIZE
+#define CONFIG_USBDEV_MTP_STACKSIZE 4096
+#endif
+
+#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
+#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
+#endif
+
+/* rndis transfer buffer size, must be a multiple of (1536 + 44)*/
+#ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
+#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
+#endif
+
+#ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID
+#define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff
+#endif
+
+#ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC
+#define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB"
+#endif
+
+#define CONFIG_USBDEV_RNDIS_USING_LWIP
+#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
+
+/* ================ USB HOST Stack Configuration ================== */
+
+#define CONFIG_USBHOST_MAX_RHPORTS          1
+#define CONFIG_USBHOST_MAX_EXTHUBS          1
+#define CONFIG_USBHOST_MAX_EHPORTS          4
+#define CONFIG_USBHOST_MAX_INTERFACES       8
+#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 2
+#define CONFIG_USBHOST_MAX_ENDPOINTS        4
+
+#define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
+#define CONFIG_USBHOST_MAX_HID_CLASS     4
+#define CONFIG_USBHOST_MAX_MSC_CLASS     2
+#define CONFIG_USBHOST_MAX_AUDIO_CLASS   1
+#define CONFIG_USBHOST_MAX_VIDEO_CLASS   1
+
+#define CONFIG_USBHOST_DEV_NAMELEN 16
+
+#ifndef CONFIG_USBHOST_PSC_PRIO
+#define CONFIG_USBHOST_PSC_PRIO 0
+#endif
+#ifndef CONFIG_USBHOST_PSC_STACKSIZE
+#define CONFIG_USBHOST_PSC_STACKSIZE 2048
+#endif
+
+//#define CONFIG_USBHOST_GET_STRING_DESC
+
+// #define CONFIG_USBHOST_MSOS_ENABLE
+#ifndef CONFIG_USBHOST_MSOS_VENDOR_CODE
+#define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00
+#endif
+
+/* Ep0 max transfer buffer */
+#ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN
+#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 4096
+#endif
+
+#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
+#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
+#endif
+
+#ifndef CONFIG_USBHOST_MSC_TIMEOUT
+#define CONFIG_USBHOST_MSC_TIMEOUT 5000
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
+#endif
+
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE (2048)
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE (2048)
+#endif
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_CDC_NCM_ETH_MAX_TX_SIZE (2048)
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_ASIX_ETH_MAX_RX_SIZE (2048)
+#endif
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_ASIX_ETH_MAX_TX_SIZE (2048)
+#endif
+
+/* This parameter affects usb performance, and depends on (TCP_WND)tcp eceive windows size,
+ * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
+ */
+#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE
+#define CONFIG_USBHOST_RTL8152_ETH_MAX_RX_SIZE (2048)
+#endif
+/* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
+#ifndef CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE
+#define CONFIG_USBHOST_RTL8152_ETH_MAX_TX_SIZE (2048)
+#endif
+
+#define CONFIG_USBHOST_BLUETOOTH_HCI_H4
+// #define CONFIG_USBHOST_BLUETOOTH_HCI_LOG
+
+#ifndef CONFIG_USBHOST_BLUETOOTH_TX_SIZE
+#define CONFIG_USBHOST_BLUETOOTH_TX_SIZE 2048
+#endif
+#ifndef CONFIG_USBHOST_BLUETOOTH_RX_SIZE
+#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
+#endif
+
+/* ================ USB Device Port Configuration ================*/
+
+#ifndef CONFIG_USBDEV_MAX_BUS
+#define CONFIG_USBDEV_MAX_BUS 1
+#endif
+
+// #define CONFIG_USBDEV_SOF_ENABLE
+
+/* ---------------- FSDEV Configuration ---------------- */
+//#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
+
+/* ---------------- DWC2 Configuration ---------------- */
+/* enable dwc2 buffer dma mode for device
+ * in xxx32 chips, only pb14/pb15 can support dma mode, pa11/pa12 is not supported(only a few supports, but we ignore them)
+*/
+// #define CONFIG_USB_DWC2_DMA_ENABLE
+
+/* ---------------- MUSB Configuration ---------------- */
+#define CONFIG_USB_MUSB_EP_NUM 8
+// #define CONFIG_USB_MUSB_SUNXI
+
+/* ================ USB Host Port Configuration ==================*/
+#ifndef CONFIG_USBHOST_MAX_BUS
+#define CONFIG_USBHOST_MAX_BUS 1
+#endif
+
+/* ---------------- EHCI Configuration ---------------- */
+
+#define CONFIG_USB_EHCI_HCCR_OFFSET     (0x0)
+#define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024
+#define CONFIG_USB_EHCI_QH_NUM          10
+#define CONFIG_USB_EHCI_QTD_NUM         (CONFIG_USB_EHCI_QH_NUM * 3)
+#define CONFIG_USB_EHCI_ITD_NUM         4
+#define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE
+// #define CONFIG_USB_EHCI_CONFIGFLAG
+// #define CONFIG_USB_EHCI_ISO
+// #define CONFIG_USB_EHCI_WITH_OHCI
+// #define CONFIG_USB_EHCI_DESC_DCACHE_ENABLE
+
+/* ---------------- OHCI Configuration ---------------- */
+#define CONFIG_USB_OHCI_HCOR_OFFSET (0x0)
+#define CONFIG_USB_OHCI_ED_NUM 10
+#define CONFIG_USB_OHCI_TD_NUM 3
+// #define CONFIG_USB_OHCI_DESC_DCACHE_ENABLE
+
+/* ---------------- XHCI Configuration ---------------- */
+#define CONFIG_USB_XHCI_HCCR_OFFSET (0x0)
+
+/* ---------------- DWC2 Configuration ---------------- */
+// nothing to define
+
+/* ---------------- MUSB Configuration ---------------- */
+#define CONFIG_USB_MUSB_PIPE_NUM 8
+// #define CONFIG_USB_MUSB_SUNXI
+// #define CONFIG_USB_MUSB_WITHOUT_MULTIPOINT
+
+/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode,
+ * the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS.
+ *
+ * in xxx32 chips, only pb14/pb15 can support hs mode, pa11/pa12 is not supported(only a few supports, but we ignore them).
+*/
+// #define CONFIG_USB_HS
+
+#ifndef usb_phyaddr2ramaddr
+#define usb_phyaddr2ramaddr(addr) (addr)
+#endif
+
+#ifndef usb_ramaddr2phyaddr
+#define usb_ramaddr2phyaddr(addr) (addr)
+#endif
+
+#define ATTR_FAST_RAM_SECTION ATTR_TCM_SECTION
+#define CONFIG_USB_HS
+
+#endif

+ 16 - 0
tests/bouffalolab/proj.conf

@@ -0,0 +1,16 @@
+set(CONFIG_FREERTOS 1)
+
+# do not use sdk cherryusb because its version is lower than master.
+
+#set(CONFIG_CHERRYUSB 1)
+#set(CONFIG_CHERRYUSB_HOST 1)
+#set(CONFIG_CHERRYUSB_HOST_ECM 1)
+
+set(CONFIG_PSRAM 1)
+set(CONFIG_FATFS          1)
+set(CONFIG_FATFS_USBH     1)
+
+set(CONFIG_LWIP 1)
+set(CONFIG_PING 1)
+set(CONFIG_IPERF 1)
+set(CONFIG_SHELL 1)

+ 158 - 0
tests/bouffalolab/src/main.c

@@ -0,0 +1,158 @@
+#include <FreeRTOS.h>
+#include "semphr.h"
+#include "usbh_core.h"
+#include "bflb_uart.h"
+#include "board.h"
+#include "shell.h"
+#ifdef CONFIG_USB_EHCI_ISO
+#include "usbh_uvc_stream.h"
+#include "usbh_uac_stream.h"
+#endif
+#include "lwip/tcpip.h"
+
+static struct bflb_device_s *uart0;
+
+extern void shell_init_with_task(struct bflb_device_s *shell);
+
+#ifdef CONFIG_USB_EHCI_ISO
+static ATTR_NOINIT_PSRAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer1[640 * 480 * 2];
+static ATTR_NOINIT_PSRAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer2[640 * 480 * 2];
+static struct usbh_videoframe frame_pool[2];
+
+static ATTR_NOINIT_PSRAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer[AUDIO_MIC_EP_MPS * 8];
+static struct usbh_audioframe frame_pool2[8];
+
+void usbh_video_run(struct usbh_video *video_class)
+{
+    usbh_video_stream_start(640, 480, USBH_VIDEO_FORMAT_MJPEG);
+}
+
+void usbh_video_stop(struct usbh_video *video_class)
+{
+    usbh_video_stream_stop();
+}
+
+void usbh_video_frame_callback(struct usbh_videoframe *frame)
+{
+    USB_LOG_RAW("frame buf:%p,frame len:%d\r\n", frame->frame_buf, frame->frame_size);
+}
+#endif
+
+int main(void)
+{
+    board_init();
+
+    uart0 = bflb_device_get_by_name("uart0");
+    shell_init_with_task(uart0);
+
+    /* Initialize the LwIP stack */
+    tcpip_init(NULL, NULL);
+
+    printf("Starting usb host task...\r\n");
+#ifdef CONFIG_USB_EHCI_ISO
+    extern void usbh_video_fps_init(void);
+    usbh_video_fps_init();
+    frame_pool[0].frame_buf = frame_buffer1;
+    frame_pool[0].frame_bufsize = 640 * 480 * 2;
+    frame_pool[1].frame_buf = frame_buffer2;
+    frame_pool[1].frame_bufsize = 640 * 480 * 2;
+
+    usbh_video_stream_init(5, frame_pool, 2);
+
+    for (uint8_t i = 0; i < 8; i++) {
+        frame_pool2[i].frame_buf = frame_buffer + i * AUDIO_MIC_EP_MPS;
+        frame_pool2[i].frame_bufsize = AUDIO_MIC_EP_MPS;
+    }
+
+    usbh_audio_mic_stream_init(5, frame_pool2, 8);
+#endif
+    vTaskStartScheduler();
+
+    while (1) {
+    }
+}
+
+int usbh_deinit(int argc, char **argv)
+{
+    printf("usbh_deinit\r\n");
+    usbh_deinitialize(0);
+    return 0;
+}
+SHELL_CMD_EXPORT_ALIAS(usbh_deinit, usbh_deinit, usbh deinit);
+
+int usbh_init(int argc, char **argv)
+{
+    printf("usbh_init\r\n");
+    usbh_initialize(0, 0x20072000, NULL);
+    return 0;
+}
+
+SHELL_CMD_EXPORT_ALIAS(usbh_init, usbh_init, usbh init);
+
+SHELL_CMD_EXPORT_ALIAS(lsusb, lsusb, ls usb);
+
+// int uvcinit(int argc, char **argv)
+// {
+//     video_init(0, 0x20072000);
+//     return 0;
+// }
+// SHELL_CMD_EXPORT_ALIAS(uvcinit, uvcinit, usbh init);
+
+// int uvcsend(int argc, char **argv)
+// {
+//     extern void video_test(uint8_t busid);
+//     video_test(0);
+//     return 0;
+// }
+// SHELL_CMD_EXPORT_ALIAS(uvcsend, uvcsend, usbh init);
+
+#ifdef CONFIG_USB_EHCI_ISO
+int usbh_uvc_start(int argc, char **argv)
+{
+    uint8_t type;
+
+    if (argc < 2) {
+        USB_LOG_ERR("please input correct command: usbh_uvc_start type\r\n");
+        USB_LOG_ERR("type 0:yuyv, type 1:mjpeg\r\n");
+        return -1;
+    }
+
+    type = atoi(argv[1]);
+    usbh_video_stream_start(640, 480, type);
+    return 0;
+}
+
+SHELL_CMD_EXPORT_ALIAS(usbh_uvc_start, usbh_uvc_start, usbh_uvc_start);
+
+int usbh_uvc_stop(int argc, char **argv)
+{
+    usbh_video_stream_stop();
+    return 0;
+}
+
+SHELL_CMD_EXPORT_ALIAS(usbh_uvc_stop, usbh_uvc_stop, usbh_uvc_stop);
+
+int usbh_uac_start(int argc, char **argv)
+{
+    uint32_t freq;
+
+    if (argc < 2) {
+        USB_LOG_ERR("please input correct command: usbh_uac_start freq\r\n");
+        return -1;
+    }
+
+    freq = atoi(argv[1]);
+    usbh_audio_mic_stream_start(freq);
+    return 0;
+}
+
+SHELL_CMD_EXPORT_ALIAS(usbh_uac_start, usbh_uac_start, usbh_uac_start);
+
+int usbh_uac_stop(int argc, char **argv)
+{
+    usbh_audio_mic_stream_stop();
+    return 0;
+}
+
+SHELL_CMD_EXPORT_ALIAS(usbh_uac_stop, usbh_uac_stop, usbh_uac_stop);
+#endif

+ 7 - 6
tests/hpmicro/CMakeLists.txt

@@ -23,6 +23,7 @@ sdk_compile_definitions(-D__freertos_irq_stack_top=_stack)
 sdk_compile_definitions(-DCONFIG_FREERTOS=1)
 sdk_compile_definitions(-DUSE_NONVECTOR_MODE=1)
 sdk_compile_definitions(-DDISABLE_IRQ_PREEMPTIVE=1)
+sdk_compile_definitions(-DLWIP_TIMEVAL_PRIVATE=0)
 
 sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_ECM)
 sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_NCM)
@@ -30,23 +31,23 @@ sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_CDC_RNDIS)
 sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_ASIX)
 sdk_compile_definitions(-DCONFIG_USBHOST_PLATFORM_RTL8152)
 
+sdk_compile_options("-O2")
+
 sdk_inc(inc)
 sdk_app_src(inc/arch/sys_arch.c)
 sdk_app_src(src/main.c)
 sdk_app_src(../../demo/usb_host.c)
-# sdk_app_src(src/uvc2lcd.c)
-# sdk_app_src(src/font24x48.c)
 
-# sdk_inc(src/iperf)
-# sdk_app_src(src/iperf/iperf.c src/iperf/iperf_cli.c src/iperf/utils_getopt.c src/ping.c)
-
-# sdk_app_src(src/usbh_uvc_port.c)
+sdk_inc(src/iperf)
+sdk_app_src(src/iperf/iperf.c src/iperf/iperf_cli.c src/iperf/utils_getopt.c src/ping.c)
 
 set(CONFIG_CHERRYMP 1)
 set(CONFIG_CHERRYUSB 1)
 set(CONFIG_CHERRYUSB_DEVICE 1)
 set(CONFIG_CHERRYUSB_HOST 1)
 
+# sdk_app_src(src/uvc2lcd.c)
+# sdk_app_src(src/font24x48.c)
 # add_subdirectory(src/cherryusb_hostuvcuac)
 add_subdirectory(../.. cherryusb)
 

+ 9 - 1
tests/hpmicro/inc/FreeRTOSConfig.h

@@ -29,6 +29,14 @@
 #define configMTIMECMP_BASE_ADDRESS             (HPM_MCHTMR_BASE + 8UL)
 #endif
 
+/* When USE_SYSCALL_INTERRUPT_PRIORITY is set, interrupts whose priority is higher than configMAX_SYSCALL_INTERRUPT_PRIORITY
+   will not be delayed by anything FreeRTOS do. */
+#if defined (USE_SYSCALL_INTERRUPT_PRIORITY) && USE_SYSCALL_INTERRUPT_PRIORITY
+#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY  4
+#endif
+#endif
+
 #define configUSE_PREEMPTION                    1
 #define configCPU_CLOCK_HZ                      ((uint32_t) 24000000)
 #define configTICK_RATE_HZ                      ((TickType_t) 1000)
@@ -47,7 +55,7 @@
 #define configSUPPORT_STATIC_ALLOCATION         1
 #define configSUPPORT_DYNAMIC_ALLOCATION        1
 #ifndef configTOTAL_HEAP_SIZE
-#define configTOTAL_HEAP_SIZE                   ((size_t) (120 * 1024))
+#define configTOTAL_HEAP_SIZE                   ((size_t) (64 * 1024))
 #endif
 
 /* Hook function definitions. */

+ 13 - 5
tests/hpmicro/inc/arch/cc.h

@@ -31,7 +31,7 @@
  */
 
 /*
- * Copyright (c) 2021-2022 HPMicro
+ * Copyright (c) 2021-2024 HPMicro
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -68,11 +68,23 @@
 
 #elif defined (__GNUC__)
 
+#include <sys/time.h>
+#include <time.h>
+
 #define PACK_STRUCT_BEGIN
 #define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
 #define PACK_STRUCT_END
 #define PACK_STRUCT_FIELD(x) x
 
+#elif defined(__ICCRISCV__)
+
+#include <time.h>
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+typedef unsigned long clockid_t;
+
 #elif defined (__TASKING__)
 
 #define PACK_STRUCT_BEGIN
@@ -84,8 +96,4 @@
 
 #define LWIP_PLATFORM_ASSERT(x) printf(x)
 
-#ifndef LWIP_MEM_SECTION
-#define LWIP_MEM_SECTION ".framebuffer"
-#endif
-
 #endif /* __CC_H__ */

+ 288 - 316
tests/hpmicro/inc/arch/sys_arch.c

@@ -124,9 +124,9 @@ void
 sys_init(void)
 {
 #if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
-  /* initialize sys_arch_protect global mutex */
-  sys_arch_protect_mutex = xSemaphoreCreateRecursiveMutex();
-  LWIP_ASSERT("failed to create sys_arch_protect mutex",
+    /* initialize sys_arch_protect global mutex */
+    sys_arch_protect_mutex = xSemaphoreCreateRecursiveMutex();
+    LWIP_ASSERT("failed to create sys_arch_protect mutex",
     sys_arch_protect_mutex != NULL);
 #endif /* SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
 }
@@ -136,424 +136,400 @@ sys_init(void)
 #endif
 
 #if LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS
-u32_t
-sys_now(void)
+u32_t sys_now(void)
 {
-  return xTaskGetTickCount() * portTICK_PERIOD_MS;
+    return xTaskGetTickCount() * portTICK_PERIOD_MS;
 }
 #else
-u32_t
-sys_now(void)
+u32_t sys_now(void)
 {
-  return 0;
+    return 0;
 }
 #endif
 
-u32_t
-sys_jiffies(void)
+u32_t sys_jiffies(void)
 {
-  return xTaskGetTickCount();
+    return xTaskGetTickCount();
 }
 
 #if SYS_LIGHTWEIGHT_PROT
 
-sys_prot_t
-sys_arch_protect(void)
+sys_prot_t sys_arch_protect(void)
 {
 #if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
-  BaseType_t ret;
-  LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
-
-  ret = xSemaphoreTakeRecursive(sys_arch_protect_mutex, portMAX_DELAY);
-  LWIP_ASSERT("sys_arch_protect failed to take the mutex", ret == pdTRUE);
-#else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
-  taskENTER_CRITICAL();
-#endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
-#if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
-  {
-    /* every nested call to sys_arch_protect() returns an increased number */
-    sys_prot_t ret = sys_arch_protect_nesting;
-    sys_arch_protect_nesting++;
-    LWIP_ASSERT("sys_arch_protect overflow", sys_arch_protect_nesting > ret);
-    return ret;
-  }
+    BaseType_t ret;
+    LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
+
+    ret = xSemaphoreTakeRecursive(sys_arch_protect_mutex, portMAX_DELAY);
+    LWIP_ASSERT("sys_arch_protect failed to take the mutex", ret == pdTRUE);
+    #else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
+    taskENTER_CRITICAL();
+    #endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
+    #if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
+    {
+        /* every nested call to sys_arch_protect() returns an increased number */
+        sys_prot_t ret = sys_arch_protect_nesting;
+        sys_arch_protect_nesting++;
+        LWIP_ASSERT("sys_arch_protect overflow", sys_arch_protect_nesting > ret);
+        return ret;
+    }
 #else
-  return 1;
+    return 1;
 #endif
 }
 
-void
-sys_arch_unprotect(sys_prot_t pval)
+void sys_arch_unprotect(sys_prot_t pval)
 {
 #if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
-  BaseType_t ret;
+    BaseType_t ret;
 #endif
 #if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK
-  LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting > 0);
-  sys_arch_protect_nesting--;
-  LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting == pval);
+    LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting > 0);
+    sys_arch_protect_nesting--;
+    LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting == pval);
 #endif
 
 #if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX
-  LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
+    LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL);
 
-  ret = xSemaphoreGiveRecursive(sys_arch_protect_mutex);
-  LWIP_ASSERT("sys_arch_unprotect failed to give the mutex", ret == pdTRUE);
+    ret = xSemaphoreGiveRecursive(sys_arch_protect_mutex);
+    LWIP_ASSERT("sys_arch_unprotect failed to give the mutex", ret == pdTRUE);
 #else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
-  taskEXIT_CRITICAL();
+    taskEXIT_CRITICAL();
 #endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */
-  LWIP_UNUSED_ARG(pval);
+    LWIP_UNUSED_ARG(pval);
 }
 
 #endif /* SYS_LIGHTWEIGHT_PROT */
 
-void
-sys_arch_msleep(u32_t delay_ms)
+void sys_arch_msleep(u32_t delay_ms)
 {
-  TickType_t delay_ticks = delay_ms / portTICK_RATE_MS;
-  vTaskDelay(delay_ticks);
+    TickType_t delay_ticks = delay_ms / portTICK_RATE_MS;
+    vTaskDelay(delay_ticks);
 }
 
 #if !LWIP_COMPAT_MUTEX
 
 /* Create a new mutex*/
-err_t
-sys_mutex_new(sys_mutex_t *mutex)
+err_t sys_mutex_new(sys_mutex_t *mutex)
 {
-  LWIP_ASSERT("mutex != NULL", mutex != NULL);
+    LWIP_ASSERT("mutex != NULL", mutex != NULL);
 
-  mutex->mut = xSemaphoreCreateRecursiveMutex();
-  if (mutex->mut == NULL) {
-    SYS_STATS_INC(mutex.err);
-    return ERR_MEM;
-  }
-  SYS_STATS_INC_USED(mutex);
-  return ERR_OK;
+    mutex->mut = xSemaphoreCreateRecursiveMutex();
+    if (mutex->mut == NULL) {
+        SYS_STATS_INC(mutex.err);
+        return ERR_MEM;
+    }
+    SYS_STATS_INC_USED(mutex);
+    return ERR_OK;
 }
 
-void
-sys_mutex_lock(sys_mutex_t *mutex)
+void sys_mutex_lock(sys_mutex_t *mutex)
 {
-  BaseType_t ret;
-  LWIP_ASSERT("mutex != NULL", mutex != NULL);
-  LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL);
+    BaseType_t ret;
+    LWIP_ASSERT("mutex != NULL", mutex != NULL);
+    LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
 
-  ret = xSemaphoreTakeRecursive(mutex->mut, portMAX_DELAY);
-  LWIP_ASSERT("failed to take the mutex", ret == pdTRUE);
+    ret = xSemaphoreTakeRecursive(mutex->mut, portMAX_DELAY);
+    LWIP_ASSERT("failed to take the mutex", ret == pdTRUE);
 }
 
-void
-sys_mutex_unlock(sys_mutex_t *mutex)
+void sys_mutex_unlock(sys_mutex_t *mutex)
 {
-  BaseType_t ret;
-  LWIP_ASSERT("mutex != NULL", mutex != NULL);
-  LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL);
+    BaseType_t ret;
+    LWIP_ASSERT("mutex != NULL", mutex != NULL);
+    LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
 
-  ret = xSemaphoreGiveRecursive(mutex->mut);
-  LWIP_ASSERT("failed to give the mutex", ret == pdTRUE);
+    ret = xSemaphoreGiveRecursive(mutex->mut);
+    LWIP_ASSERT("failed to give the mutex", ret == pdTRUE);
 }
 
-void
-sys_mutex_free(sys_mutex_t *mutex)
+void sys_mutex_free(sys_mutex_t *mutex)
 {
-  LWIP_ASSERT("mutex != NULL", mutex != NULL);
-  LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL);
+    LWIP_ASSERT("mutex != NULL", mutex != NULL);
+    LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); /* NOLINT */
 
-  SYS_STATS_DEC(mutex.used);
-  vSemaphoreDelete(mutex->mut);
-  mutex->mut = NULL;
+    SYS_STATS_DEC(mutex.used);
+    vSemaphoreDelete(mutex->mut);
+    mutex->mut = NULL;
 }
 
 #endif /* !LWIP_COMPAT_MUTEX */
 
-err_t
-sys_sem_new(sys_sem_t *sem, u8_t initial_count)
+err_t sys_sem_new(sys_sem_t *sem, u8_t initial_count)
 {
-  LWIP_ASSERT("sem != NULL", sem != NULL);
-  LWIP_ASSERT("initial_count invalid (not 0 or 1)",
-    (initial_count == 0) || (initial_count == 1));
+    LWIP_ASSERT("sem != NULL", sem != NULL);
+    LWIP_ASSERT("initial_count invalid (not 0 or 1)",
+        (initial_count == 0) || (initial_count == 1));
 
-  sem->sem = xSemaphoreCreateBinary();
-  if (sem->sem == NULL) {
-    SYS_STATS_INC(sem.err);
-    return ERR_MEM;
-  }
-  SYS_STATS_INC_USED(sem);
+    sem->sem = xSemaphoreCreateBinary();
+    if (sem->sem == NULL) {
+        SYS_STATS_INC(sem.err);
+        return ERR_MEM;
+    }
+    SYS_STATS_INC_USED(sem);
 
-  if (initial_count == 1) {
-    BaseType_t ret = xSemaphoreGive(sem->sem);
-    LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE);
-  }
-  return ERR_OK;
+    if (initial_count == 1) {
+        BaseType_t ret = xSemaphoreGive(sem->sem);
+        LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE);
+    }
+    return ERR_OK;
 }
 
-void
-sys_sem_signal(sys_sem_t *sem)
+void sys_sem_signal(sys_sem_t *sem)
 {
-  BaseType_t ret;
-  LWIP_ASSERT("sem != NULL", sem != NULL);
-  LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL);
+    BaseType_t ret;
+    LWIP_ASSERT("sem != NULL", sem != NULL);
+    LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
 
-  ret = xSemaphoreGive(sem->sem);
-  /* queue full is OK, this is a signal only... */
-  LWIP_ASSERT("sys_sem_signal: sane return value",
-    (ret == pdTRUE) || (ret == errQUEUE_FULL));
+    ret = xSemaphoreGive(sem->sem);
+    /* queue full is OK, this is a signal only... */
+    LWIP_ASSERT("sys_sem_signal: sane return value",
+        (ret == pdTRUE) || (ret == errQUEUE_FULL));
 }
 
-u32_t
-sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout_ms)
+u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout_ms)
 {
-  BaseType_t ret;
-  LWIP_ASSERT("sem != NULL", sem != NULL);
-  LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL);
-
-  if (!timeout_ms) {
-    /* wait infinite */
-    ret = xSemaphoreTake(sem->sem, portMAX_DELAY);
-    LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
-  } else {
-    TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
-    ret = xSemaphoreTake(sem->sem, timeout_ticks);
-    if (ret == errQUEUE_EMPTY) {
-      /* timed out */
-      return SYS_ARCH_TIMEOUT;
+    BaseType_t ret;
+    LWIP_ASSERT("sem != NULL", sem != NULL);
+    LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */
+
+    if (!timeout_ms) {
+        /* wait infinite */
+        ret = xSemaphoreTake(sem->sem, portMAX_DELAY);
+        LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
+    } else {
+        TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
+        ret = xSemaphoreTake(sem->sem, timeout_ticks);
+        if (ret == errQUEUE_EMPTY) {
+        /* timed out */
+        return SYS_ARCH_TIMEOUT;
+        }
+        LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
     }
-    LWIP_ASSERT("taking semaphore failed", ret == pdTRUE);
-  }
 
-  /* Old versions of lwIP required us to return the time waited.
-     This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
-     here is enough. */
+    /* Old versions of lwIP required us to return the time waited.
+        This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
+        here is enough. */
   return 1;
 }
 
-void
-sys_sem_free(sys_sem_t *sem)
+void sys_sem_free(sys_sem_t *sem)
 {
-  LWIP_ASSERT("sem != NULL", sem != NULL);
-  LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL);
+    LWIP_ASSERT("sem != NULL", sem != NULL);
+    LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL);  /* NOLINT */
 
-  SYS_STATS_DEC(sem.used);
-  vSemaphoreDelete(sem->sem);
-  sem->sem = NULL;
+    SYS_STATS_DEC(sem.used);
+    vSemaphoreDelete(sem->sem);
+    sem->sem = NULL;
 }
 
-err_t
-sys_mbox_new(sys_mbox_t *mbox, int size)
+err_t sys_mbox_new(sys_mbox_t *mbox, int size)
 {
-  LWIP_ASSERT("mbox != NULL", mbox != NULL);
-  LWIP_ASSERT("size > 0", size > 0);
+    LWIP_ASSERT("mbox != NULL", mbox != NULL); /* NOLINT */
+    LWIP_ASSERT("size > 0", size > 0);
 
-  mbox->mbx = xQueueCreate((UBaseType_t)size, sizeof(void *));
-  if (mbox->mbx == NULL) {
-    SYS_STATS_INC(mbox.err);
-    return ERR_MEM;
-  }
-  SYS_STATS_INC_USED(mbox);
-  return ERR_OK;
+    mbox->mbx = xQueueCreate((UBaseType_t)size, sizeof(void *));
+    if (mbox->mbx == NULL) {
+        SYS_STATS_INC(mbox.err);
+        return ERR_MEM;
+    }
+    SYS_STATS_INC_USED(mbox);
+    return ERR_OK;
 }
 
-void
-sys_mbox_post(sys_mbox_t *mbox, void *msg)
+void sys_mbox_post(sys_mbox_t *mbox, void *msg)
 {
-  BaseType_t ret;
-  LWIP_ASSERT("mbox != NULL", mbox != NULL);
-  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);
+    BaseType_t ret;
+    LWIP_ASSERT("mbox != NULL", mbox != NULL);
+    LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);  /* NOLINT */
 
-  ret = xQueueSendToBack(mbox->mbx, &msg, portMAX_DELAY);
-  LWIP_ASSERT("mbox post failed", ret == pdTRUE);
+    ret = xQueueSendToBack(mbox->mbx, &msg, portMAX_DELAY);
+    LWIP_ASSERT("mbox post failed", ret == pdTRUE);
 }
 
-err_t
-sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
+err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
 {
-  BaseType_t ret;
-  LWIP_ASSERT("mbox != NULL", mbox != NULL);
-  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);
+    BaseType_t ret;
+    LWIP_ASSERT("mbox != NULL", mbox != NULL);
+    LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
 
-  ret = xQueueSendToBack(mbox->mbx, &msg, 0);
-  if (ret == pdTRUE) {
-    return ERR_OK;
-  } else {
-    LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
-    SYS_STATS_INC(mbox.err);
-    return ERR_MEM;
-  }
+    ret = xQueueSendToBack(mbox->mbx, &msg, 0);
+    if (ret == pdTRUE) {
+        return ERR_OK;
+    } else {
+        LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
+        SYS_STATS_INC(mbox.err);
+        return ERR_MEM;
+    }
 }
 
-err_t
-sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
+err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
 {
-  BaseType_t ret;
-  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-  LWIP_ASSERT("mbox != NULL", mbox != NULL);
-  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);
+    BaseType_t ret;
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+    LWIP_ASSERT("mbox != NULL", mbox != NULL);
+    LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
 
-  ret = xQueueSendToBackFromISR(mbox->mbx, &msg, &xHigherPriorityTaskWoken);
-  if (ret == pdTRUE) {
-    if (xHigherPriorityTaskWoken == pdTRUE) {
-      return ERR_NEED_SCHED;
+    ret = xQueueSendToBackFromISR(mbox->mbx, &msg, &xHigherPriorityTaskWoken);
+    if (ret == pdTRUE) {
+        if (xHigherPriorityTaskWoken == pdTRUE) {
+        return ERR_NEED_SCHED;
+        }
+        return ERR_OK;
+    } else {
+        LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
+        SYS_STATS_INC(mbox.err);
+        return ERR_MEM;
     }
-    return ERR_OK;
-  } else {
-    LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL);
-    SYS_STATS_INC(mbox.err);
-    return ERR_MEM;
-  }
 }
 
-u32_t
-sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms)
+u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms)
 {
-  BaseType_t ret;
-  void *msg_dummy;
-  LWIP_ASSERT("mbox != NULL", mbox != NULL);
-  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);
+    BaseType_t ret;
+    void *msg_dummy;
+    LWIP_ASSERT("mbox != NULL", mbox != NULL);
+    LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
 
-  if (!msg) {
-    msg = &msg_dummy;
-  }
+    if (!msg) {
+        msg = &msg_dummy;
+    }
 
-  if (!timeout_ms) {
-    /* wait infinite */
-    ret = xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY);
-    LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
-  } else {
-    TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
-    ret = xQueueReceive(mbox->mbx, &(*msg), timeout_ticks);
-    if (ret == errQUEUE_EMPTY) {
-      /* timed out */
-      *msg = NULL;
-      return SYS_ARCH_TIMEOUT;
+    if (!timeout_ms) {
+        /* wait infinite */
+        ret = xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY);
+        LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
+    } else {
+        TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS;
+        ret = xQueueReceive(mbox->mbx, &(*msg), timeout_ticks);
+        if (ret == errQUEUE_EMPTY) {
+        /* timed out */
+        *msg = NULL;
+        return SYS_ARCH_TIMEOUT;
+        }
+        LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
     }
-    LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
-  }
 
-  /* Old versions of lwIP required us to return the time waited.
-     This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
-     here is enough. */
-  return 1;
+    /* Old versions of lwIP required us to return the time waited.
+        This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
+        here is enough. */
+    return 1;
 }
 
-u32_t
-sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
+u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
 {
-  BaseType_t ret;
-  void *msg_dummy;
-  LWIP_ASSERT("mbox != NULL", mbox != NULL);
-  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);
+    BaseType_t ret;
+    void *msg_dummy;
+    LWIP_ASSERT("mbox != NULL", mbox != NULL);
+    LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
 
-  if (!msg) {
-    msg = &msg_dummy;
-  }
+    if (!msg) {
+        msg = &msg_dummy;
+    }
 
-  ret = xQueueReceive(mbox->mbx, &(*msg), 0);
-  if (ret == errQUEUE_EMPTY) {
-    *msg = NULL;
-    return SYS_MBOX_EMPTY;
-  }
-  LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
+    ret = xQueueReceive(mbox->mbx, &(*msg), 0);
+    if (ret == errQUEUE_EMPTY) {
+        *msg = NULL;
+        return SYS_MBOX_EMPTY;
+    }
+    LWIP_ASSERT("mbox fetch failed", ret == pdTRUE);
 
-  /* Old versions of lwIP required us to return the time waited.
-     This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
-     here is enough. */
-  return 1;
+    /* Old versions of lwIP required us to return the time waited.
+        This is not the case any more. Just returning != SYS_ARCH_TIMEOUT
+        here is enough. */
+    return 1;
 }
 
-void
-sys_mbox_free(sys_mbox_t *mbox)
+void sys_mbox_free(sys_mbox_t *mbox)
 {
-  LWIP_ASSERT("mbox != NULL", mbox != NULL);
-  LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL);
+    LWIP_ASSERT("mbox != NULL", mbox != NULL);
+    LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); /* NOLINT */
 
 #if LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE
-  {
-    UBaseType_t msgs_waiting = uxQueueMessagesWaiting(mbox->mbx);
-    LWIP_ASSERT("mbox quence not empty", msgs_waiting == 0);
+    {
+        UBaseType_t msgs_waiting = uxQueueMessagesWaiting(mbox->mbx);
+        LWIP_ASSERT("mbox quence not empty", msgs_waiting == 0);
 
-    if (msgs_waiting != 0) {
-      SYS_STATS_INC(mbox.err);
+        if (msgs_waiting != 0) {
+        SYS_STATS_INC(mbox.err);
+        }
     }
-  }
 #endif
 
-  vQueueDelete(mbox->mbx);
+    vQueueDelete(mbox->mbx);
 
-  SYS_STATS_DEC(mbox.used);
+    SYS_STATS_DEC(mbox.used);
 }
 
-sys_thread_t
-sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
+sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
 {
-  TaskHandle_t rtos_task;
-  BaseType_t ret;
-  sys_thread_t lwip_thread;
-  size_t rtos_stacksize;
+    TaskHandle_t rtos_task;
+    BaseType_t ret;
+    sys_thread_t lwip_thread;
+    size_t rtos_stacksize;
 
-  LWIP_ASSERT("invalid stacksize", stacksize > 0);
+    LWIP_ASSERT("invalid stacksize", stacksize > 0);
 #if LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS
-  rtos_stacksize = (size_t)stacksize;
+    rtos_stacksize = (size_t)stacksize;
 #else
-  rtos_stacksize = (size_t)stacksize / sizeof(StackType_t);
+    rtos_stacksize = (size_t)stacksize / sizeof(StackType_t);
 #endif
 
-  /* lwIP's lwip_thread_fn matches FreeRTOS' TaskFunction_t, so we can pass the
-     thread function without adaption here. */
-  ret = xTaskCreate(thread, name, (configSTACK_DEPTH_TYPE)rtos_stacksize, arg, prio, &rtos_task);
-  LWIP_ASSERT("task creation failed", ret == pdTRUE);
+    /* lwIP's lwip_thread_fn matches FreeRTOS' TaskFunction_t, so we can pass the
+        thread function without adaption here. */
+    ret = xTaskCreate(thread, name, (configSTACK_DEPTH_TYPE)rtos_stacksize, arg, prio, &rtos_task);
+    LWIP_ASSERT("task creation failed", ret == pdTRUE);
 
-  lwip_thread.thread_handle = rtos_task;
-  return lwip_thread;
+    lwip_thread.thread_handle = rtos_task;
+    return lwip_thread;
 }
 
 #if LWIP_NETCONN_SEM_PER_THREAD
 #if configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0
 
-sys_sem_t *
-sys_arch_netconn_sem_get(void)
+sys_sem_t *sys_arch_netconn_sem_get(void)
 {
-  void *ret;
-  TaskHandle_t task = xTaskGetCurrentTaskHandle();
-  LWIP_ASSERT("task != NULL", task != NULL);
+    void *ret;
+    TaskHandle_t task = xTaskGetCurrentTaskHandle();
+    LWIP_ASSERT("task != NULL", task != NULL);
 
-  ret = pvTaskGetThreadLocalStoragePointer(task, 0);
-  return ret;
+    ret = pvTaskGetThreadLocalStoragePointer(task, 0);
+    return ret;
 }
 
-void
-sys_arch_netconn_sem_alloc(void)
-{
-  void *ret;
-  TaskHandle_t task = xTaskGetCurrentTaskHandle();
-  LWIP_ASSERT("task != NULL", task != NULL);
-
-  ret = pvTaskGetThreadLocalStoragePointer(task, 0);
-  if (ret == NULL) {
-    sys_sem_t *sem;
-    err_t err;
-    /* need to allocate the memory for this semaphore */
-    sem = mem_malloc(sizeof(sys_sem_t));
-    LWIP_ASSERT("sem != NULL", sem != NULL);
-    err = sys_sem_new(sem, 0);
-    LWIP_ASSERT("err == ERR_OK", err == ERR_OK);
-    LWIP_ASSERT("sem invalid", sys_sem_valid(sem));
-    vTaskSetThreadLocalStoragePointer(task, 0, sem);
-  }
+void sys_arch_netconn_sem_alloc(void)
+{
+    void *ret;
+    TaskHandle_t task = xTaskGetCurrentTaskHandle();
+    LWIP_ASSERT("task != NULL", task != NULL);
+
+    ret = pvTaskGetThreadLocalStoragePointer(task, 0);
+    if (ret == NULL) {
+        sys_sem_t *sem;
+        err_t err;
+        /* need to allocate the memory for this semaphore */
+        sem = mem_malloc(sizeof(sys_sem_t));
+        LWIP_ASSERT("sem != NULL", sem != NULL);
+        err = sys_sem_new(sem, 0);
+        LWIP_ASSERT("err == ERR_OK", err == ERR_OK);
+        LWIP_ASSERT("sem invalid", sys_sem_valid(sem));
+        vTaskSetThreadLocalStoragePointer(task, 0, sem);
+    }
 }
 
 void sys_arch_netconn_sem_free(void)
 {
-  void *ret;
-  TaskHandle_t task = xTaskGetCurrentTaskHandle();
-  LWIP_ASSERT("task != NULL", task != NULL);
+    void *ret;
+    TaskHandle_t task = xTaskGetCurrentTaskHandle();
+    LWIP_ASSERT("task != NULL", task != NULL);
 
-  ret = pvTaskGetThreadLocalStoragePointer(task, 0);
-  if (ret != NULL) {
-    sys_sem_t *sem = ret;
-    sys_sem_free(sem);
-    mem_free(sem);
-    vTaskSetThreadLocalStoragePointer(task, 0, NULL);
-  }
+    ret = pvTaskGetThreadLocalStoragePointer(task, 0);
+    if (ret != NULL) {
+        sys_sem_t *sem = ret;
+        sys_sem_free(sem);
+        mem_free(sem);
+        vTaskSetThreadLocalStoragePointer(task, 0, NULL);
+    }
 }
 
 #else /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */
@@ -569,24 +545,22 @@ void sys_arch_netconn_sem_free(void)
 static u8_t lwip_core_lock_count;
 static TaskHandle_t lwip_core_lock_holder_thread;
 
-void
-sys_lock_tcpip_core(void)
+void sys_lock_tcpip_core(void)
 {
-   sys_mutex_lock(&lock_tcpip_core);
-   if (lwip_core_lock_count == 0) {
-     lwip_core_lock_holder_thread = xTaskGetCurrentTaskHandle();
-   }
-   lwip_core_lock_count++;
+    sys_mutex_lock(&lock_tcpip_core);
+    if (lwip_core_lock_count == 0) {
+        lwip_core_lock_holder_thread = xTaskGetCurrentTaskHandle();
+    }
+    lwip_core_lock_count++;
 }
 
-void
-sys_unlock_tcpip_core(void)
+void sys_unlock_tcpip_core(void)
 {
-   lwip_core_lock_count--;
-   if (lwip_core_lock_count == 0) {
-       lwip_core_lock_holder_thread = 0;
-   }
-   sys_mutex_unlock(&lock_tcpip_core);
+    lwip_core_lock_count--;
+    if (lwip_core_lock_count == 0) {
+        lwip_core_lock_holder_thread = 0;
+    }
+    sys_mutex_unlock(&lock_tcpip_core);
 }
 
 #endif /* LWIP_TCPIP_CORE_LOCKING */
@@ -595,36 +569,34 @@ sys_unlock_tcpip_core(void)
 static TaskHandle_t lwip_tcpip_thread;
 #endif
 
-void
-sys_mark_tcpip_thread(void)
+void sys_mark_tcpip_thread(void)
 {
 #if !NO_SYS
-  lwip_tcpip_thread = xTaskGetCurrentTaskHandle();
+    lwip_tcpip_thread = xTaskGetCurrentTaskHandle();
 #endif
 }
 
-void
-sys_check_core_locking(void)
+void sys_check_core_locking(void)
 {
-  /* Embedded systems should check we are NOT in an interrupt context here */
-  /* E.g. core Cortex-M3/M4 ports:
-         configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
+    /* Embedded systems should check we are NOT in an interrupt context here */
+    /* E.g. core Cortex-M3/M4 ports:
+            configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
 
-     Instead, we use more generic FreeRTOS functions here, which should fail from ISR: */
-  taskENTER_CRITICAL();
-  taskEXIT_CRITICAL();
+        Instead, we use more generic FreeRTOS functions here, which should fail from ISR: */
+    taskENTER_CRITICAL();
+    taskEXIT_CRITICAL();
 
 #if !NO_SYS
-  if (lwip_tcpip_thread != 0) {
-    TaskHandle_t current_thread = xTaskGetCurrentTaskHandle();
+    if (lwip_tcpip_thread != 0) {
+        TaskHandle_t current_thread = xTaskGetCurrentTaskHandle();
 
 #if LWIP_TCPIP_CORE_LOCKING
-    LWIP_ASSERT("Function called without core lock",
-                current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0);
+        LWIP_ASSERT("Function called without core lock",
+                    current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0);
 #else /* LWIP_TCPIP_CORE_LOCKING */
-    LWIP_ASSERT("Function called from wrong thread", current_thread == lwip_tcpip_thread);
+        LWIP_ASSERT("Function called from wrong thread", current_thread == lwip_tcpip_thread);
 #endif /* LWIP_TCPIP_CORE_LOCKING */
-  }
+    }
 #endif /* !NO_SYS */
 }
 

+ 389 - 155
tests/hpmicro/inc/lwipopts.h

@@ -1,202 +1,436 @@
 /*
- * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
- * Copyright (c) 2023 HPMicro
- * All rights reserved.
- *
- * 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. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Simon Goldschmidt
+ * Copyright (c) 2025, sakumisu
  *
+ * SPDX-License-Identifier: Apache-2.0
  */
-#ifndef __LWIPOPTS_H__
-#define __LWIPOPTS_H__
+#ifndef LWIPOPTS_H
+#define LWIPOPTS_H
 
-#include <stdint.h>
+#ifdef USE_LWIPOPTS_APP_H
+#include "lwipopts_app.h"
+#endif
 
-#define SYS_LIGHTWEIGHT_PROT            0
-#define LWIP_PROVIDE_ERRNO              1
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT 1
+#define IP_REASSEMBLY        0
+#define IP_FRAG              0
+#define ARP_QUEUEING         0
+#define NO_SYS               0
+#define LWIP_RAND            rand
 
-#if defined(__SEGGER_RTL_VERSION)
-#define LWIP_TIMEVAL_PRIVATE            1
-#else
-#define LWIP_TIMEVAL_PRIVATE            0
-#endif
-
-#define LWIP_RAND                       rand
-
-#define NO_SYS                          0
-#define MEM_ALIGNMENT                   4
-#define LWIP_DNS                        1
-#define LWIP_DNS_SERVER                 0
-#define LWIP_RAW                        1
-#define LWIP_NETCONN                    1
-#define LWIP_SOCKET                     1
-#define LWIP_DHCP                       1
-#define LWIP_ICMP                       1
-#define ICMP_TTL                        64
-#define LWIP_UDP                        1
-#define LWIP_TCP                        1
-#define TCP_TTL                         255
-#define LWIP_IPV4                       1
-#define LWIP_IPV6                       0
-#define ETH_PAD_SIZE                    0
-#define LWIP_IP_ACCEPT_UDP_PORT(p)      ((p) == PP_NTOHS(67))
-#define LWIP_WND_SCALE                  1
-#define TCP_RCV_SCALE                   0
-
-#define MEM_SIZE                        (150 * 1024)
-#define TCP_MSS                         (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/)
-#define TCP_SND_BUF                     (50 * TCP_MSS)
-#define ETHARP_SUPPORT_STATIC_ENTRIES   1
-
-#define LWIP_HTTPD_CGI                  0
-#define LWIP_HTTPD_SSI                  0
-#define LWIP_HTTPD_SSI_INCLUDE_TAG      0
+#define LWIP_NETIF_HOSTNAME  0
+#define LWIP_TIMEVAL_PRIVATE 0
+#define LWIP_TIMERS          1
+#define LWIP_RAW             1
+#define LWIP_IPV4            1
+#define LWIP_IGMP            1
+#define LWIP_ICMP            1
+#define ICMP_TTL             64
+#define LWIP_TCP             1
+#define TCP_TTL              255
+#define LWIP_UDP             1
+#define UDP_TTL              255
+#define LWIP_DNS             1
 
 /**
- * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator.
+ * LWIP_NETIF_API==1: Support netif api (in netifapi.c)
  */
-#define MEMP_MEM_MALLOC         1
+#define LWIP_NETIF_API 1
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN 1
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET 1
+
+/* ---------- Memory options ---------- */
+#define MEMP_MEM_MALLOC 0
+
+/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
+   lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
+   byte alignment -> define MEM_ALIGNMENT to 2. */
+#ifndef MEM_ALIGNMENT
+#define MEM_ALIGNMENT 64
+#endif
+
+/* MEM_SIZE: the size of the heap memory. If the application will send
+a lot of data that needs to be copied, this should be set high. */
+#ifndef MEM_SIZE
+#define MEM_SIZE (32 * 1024)
+#endif
 
 /* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
- *   sends a lot of data out of ROM (or other static memory), this
- *   should be set high.
+   sends a lot of data out of ROM (or other static memory), this
+   should be set high. */
+#ifndef MEMP_NUM_PBUF
+#define MEMP_NUM_PBUF 100
+#endif
+
+/**
+ * MEMP_NUM_RAW_PCB: Number of raw connection PCBs
+ * (requires the LWIP_RAW option)
  */
-#define MEMP_NUM_PBUF           100
+#ifndef MEMP_NUM_RAW_PCB
+#define MEMP_NUM_RAW_PCB 4
+#endif
 
 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
- * per active UDP "connection".
- */
-#define MEMP_NUM_UDP_PCB        6
+   per active UDP "connection". */
+#ifndef MEMP_NUM_UDP_PCB
+#define MEMP_NUM_UDP_PCB 4
+#endif
 
 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
- *   connections.
- */
-#define MEMP_NUM_TCP_PCB        10
+   connections. */
+#ifndef MEMP_NUM_TCP_PCB
+#define MEMP_NUM_TCP_PCB 4
+#endif
 
 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
- *  connections.
- */
+   connections. */
+#ifndef MEMP_NUM_TCP_PCB_LISTEN
 #define MEMP_NUM_TCP_PCB_LISTEN 5
+#endif
 
 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
- *  segments.
- */
-#define MEMP_NUM_TCP_SEG        20
+   segments. */
+#ifndef MEMP_NUM_TCP_SEG
+#define MEMP_NUM_TCP_SEG 40
+#endif
 
 /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
- *  timeouts.
- */
-#define MEMP_NUM_SYS_TIMEOUT    10
+   timeouts. */
+#ifndef MEMP_NUM_SYS_TIMEOUT
+#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL)
+#endif
 
+/**
+ * MEMP_NUM_NETCONN: the number of struct netconns.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#ifndef MEMP_NUM_NETCONN
+#define MEMP_NUM_NETCONN 4
+#endif
 
 /* ---------- Pbuf options ---------- */
 /* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
-#define PBUF_POOL_SIZE          20
+#ifndef PBUF_POOL_SIZE
+#define PBUF_POOL_SIZE 20
+#endif
 
-/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool.*/
-#define PBUF_POOL_BUFSIZE       1600
+/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
+#ifndef PBUF_POOL_BUFSIZE
+#define PBUF_POOL_BUFSIZE 1600
+#endif
 
+/* ---------- TCP options ---------- */
 /* Controls if TCP should queue segments that arrive out of
-   order. Define to 0 if your device is low on memory
-*/
-#define TCP_QUEUE_OOSEQ         1
+   order. Define to 0 if your device is low on memory. */
+#ifndef TCP_QUEUE_OOSEQ
+#define TCP_QUEUE_OOSEQ 0
+#endif
+
+/* TCP Maximum segment size. */
+#ifndef TCP_MSS
+#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
+#endif
+
+/* TCP sender buffer space (bytes). */
+#ifndef TCP_SND_BUF
+#define TCP_SND_BUF (8 * TCP_MSS)
+#endif
 
 /*  TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
-  as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
-*/
-#define TCP_SND_QUEUELEN        (4* TCP_SND_BUF/TCP_MSS)
+  as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
+#ifndef TCP_SND_QUEUELEN
+#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF / TCP_MSS)
+#endif
 
 /* TCP receive window. */
-#define TCP_WND                 (16*TCP_MSS)
+#ifndef TCP_WND
+#define TCP_WND (16 * TCP_MSS)
+#endif
+
+/* ---------- DHCP options ---------- */
+/* Define LWIP_DHCP to 1 if you want DHCP configuration of
+   interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
+   turning this on does currently not work. */
+#ifndef LWIP_DHCP
+#define LWIP_DHCP 1
+#endif
+
+/* ---------- Statistics options ---------- */
+#ifndef LWIP_STATS
+#define LWIP_STATS 0
+#endif
+
+#ifndef LWIP_PROVIDE_ERRNO
+#define LWIP_PROVIDE_ERRNO 1
+#endif
 
 /*
- *  -----------------------------------
- *  ---------- DEBUG options ----------
- *  -----------------------------------
+   ------------------------------------------------
+   ---------- Network Interfaces options ----------
+   ------------------------------------------------
+*/
+/**
+ * LWIP_SINGLE_NETIF==1: use a single netif only. This is the common case for
+ * small real-life targets. Some code like routing etc. can be left out.
+ */
+#ifndef LWIP_SINGLE_NETIF
+#define LWIP_SINGLE_NETIF 1
+#endif
+
+/* ---------- link callback options ---------- */
+/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
+ * whenever the link changes (i.e., link down)
  */
+#ifndef LWIP_NETIF_LINK_CALLBACK
+#define LWIP_NETIF_LINK_CALLBACK 1
+#endif
+
+/**
+ * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP *tries* to put all data
+ * to be sent into one single pbuf. This is for compatibility with DMA-enabled
+ * MACs that do not support scatter-gather.
+ * Beware that this might involve CPU-memcpy before transmitting that would not
+ * be needed without this flag! Use this only if you need to!
+ *
+ * ATTENTION: a driver should *NOT* rely on getting single pbufs but check TX
+ * pbufs for being in one piece. If not, @ref pbuf_clone can be used to get
+ * a single pbuf:
+ *   if (p->next != NULL) {
+ *     struct pbuf *q = pbuf_clone(PBUF_RAW, PBUF_RAM, p);
+ *     if (q == NULL) {
+ *       return ERR_MEM;
+ *     }
+ *     p = q; ATTENTION: do NOT free the old 'p' as the ref belongs to the caller!
+ *   }
+ */
+#ifndef LWIP_NETIF_TX_SINGLE_PBUF
+#define LWIP_NETIF_TX_SINGLE_PBUF 0
+#endif
 
-#define LWIP_DEBUG                      1
+/*
+   --------------------------------------
+   ---------- Checksum options ----------
+   --------------------------------------
+*/
 
+/*
+ * Some MCUs allow computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
+ * To use this feature let the following define uncommented.
+ * To disable it and process by CPU comment the  the checksum.
+*/
+#ifdef CHECKSUM_BY_HARDWARE
+/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
+#define CHECKSUM_GEN_IP 0
+/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
+#define CHECKSUM_GEN_UDP 0
+/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
+#define CHECKSUM_GEN_TCP 0
+/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
+#define CHECKSUM_CHECK_IP 0
+/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
+#define CHECKSUM_CHECK_UDP 0
+/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
+#define CHECKSUM_CHECK_TCP 0
+/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
+#define CHECKSUM_GEN_ICMP 0
+#else
+/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
+#define CHECKSUM_GEN_IP    1
+/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
+#define CHECKSUM_GEN_UDP   1
+/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
+#define CHECKSUM_GEN_TCP   1
+/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
+#define CHECKSUM_CHECK_IP  1
+/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
+#define CHECKSUM_CHECK_UDP 1
+/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
+#define CHECKSUM_CHECK_TCP 1
+/* CHECKSUM_CHECK_ICMP==1: Check checksums by software for incoming ICMP packets.*/
+#define CHECKSUM_GEN_ICMP  1
+#endif
+
+/*
+   -----------------------------------
+   ---------- DEBUG options ----------
+   -----------------------------------
+*/
 #ifdef LWIP_DEBUG
 
-#define LWIP_DBG_MIN_LEVEL         1
-
-#define PPP_DEBUG                  LWIP_DBG_OFF
-#define MEM_DEBUG                  LWIP_DBG_OFF
-#define MEMP_DEBUG                 LWIP_DBG_OFF
-#define PBUF_DEBUG                 LWIP_DBG_OFF
-#define API_LIB_DEBUG              LWIP_DBG_OFF
-#define API_MSG_DEBUG              LWIP_DBG_OFF
-#define TCPIP_DEBUG                LWIP_DBG_OFF
-#define NETIF_DEBUG                LWIP_DBG_OFF
-#define SOCKETS_DEBUG              LWIP_DBG_OFF
-#define DNS_DEBUG                  LWIP_DBG_OFF
-#define AUTOIP_DEBUG               LWIP_DBG_OFF
-#define DHCP_DEBUG                 LWIP_DBG_OFF
-#define IP_DEBUG                   LWIP_DBG_OFF
-#define IP_REASS_DEBUG             LWIP_DBG_OFF
-#define ICMP_DEBUG                 LWIP_DBG_OFF
-#define IGMP_DEBUG                 LWIP_DBG_OFF
-#define UDP_DEBUG                  LWIP_DBG_OFF
-#define TCP_DEBUG                  LWIP_DBG_OFF
-#define TCP_INPUT_DEBUG            LWIP_DBG_OFF
-#define TCP_OUTPUT_DEBUG           LWIP_DBG_OFF
-#define TCP_RTO_DEBUG              LWIP_DBG_OFF
-#define TCP_CWND_DEBUG             LWIP_DBG_OFF
-#define TCP_WND_DEBUG              LWIP_DBG_OFF
-#define TCP_FR_DEBUG               LWIP_DBG_OFF
-#define TCP_QLEN_DEBUG             LWIP_DBG_OFF
-#define TCP_RST_DEBUG              LWIP_DBG_OFF
-#define ETHARP_DEBUG               LWIP_DBG_OFF
-
-#endif
-
-#define DHCP_DOES_ARP_CHECK             0
+#ifndef LWIP_DBG_MIN_LEVEL
+#define LWIP_DBG_MIN_LEVEL 0
+#endif
+
+#ifndef PPP_DEBUG
+#define PPP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef MEM_DEBUG
+#define MEM_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef MEMP_DEBUG
+#define MEMP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef PBUF_DEBUG
+#define PBUF_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef API_LIB_DEBUG
+#define API_LIB_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef API_MSG_DEBUG
+#define API_MSG_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCPIP_DEBUG
+#define TCPIP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef NETIF_DEBUG
+#define NETIF_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef SOCKETS_DEBUG
+#define SOCKETS_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef DNS_DEBUG
+#define DNS_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef AUTOIP_DEBUG
+#define AUTOIP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef DHCP_DEBUG
+#define DHCP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef IP_DEBUG
+#define IP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef IP_REASS_DEBUG
+#define IP_REASS_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef ICMP_DEBUG
+#define ICMP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef IGMP_DEBUG
+#define IGMP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef UDP_DEBUG
+#define UDP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_DEBUG
+#define TCP_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_INPUT_DEBUG
+#define TCP_INPUT_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_OUTPUT_DEBUG
+#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_RTO_DEBUG
+#define TCP_RTO_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_CWND_DEBUG
+#define TCP_CWND_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_WND_DEBUG
+#define TCP_WND_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_FR_DEBUG
+#define TCP_FR_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_QLEN_DEBUG
+#define TCP_QLEN_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef TCP_RST_DEBUG
+#define TCP_RST_DEBUG LWIP_DBG_OFF
+#endif
+
+#ifndef ETHARP_DEBUG
+#define ETHARP_DEBUG LWIP_DBG_OFF
+#endif
+
+#endif
 
 /*
- *  ---------------------------------
- *  ---------- OS options ----------
- *  ---------------------------------
- */
+   ---------------------------------
+   ---------- OS options ----------
+   ---------------------------------
+*/
+#ifndef TCPIP_THREAD_NAME
+#define TCPIP_THREAD_NAME "tcpip"
+#endif
 
-#define TCPIP_THREAD_NAME              "tcpip"
-#define TCPIP_THREAD_STACKSIZE          1500
-#define TCPIP_MBOX_SIZE                 64
-#define DEFAULT_RAW_RECVMBOX_SIZE       1000
-#define DEFAULT_UDP_RECVMBOX_SIZE       100
-#define DEFAULT_TCP_RECVMBOX_SIZE       100
-#define DEFAULT_ACCEPTMBOX_SIZE         1500
-#define DEFAULT_THREAD_STACKSIZE        500
-#define TCPIP_THREAD_PRIO               31
-#define LWIP_SINGLE_NETIF               1
-#define LWIP_COMPAT_MUTEX               0
+#ifndef TCPIP_THREAD_STACKSIZE
+#define TCPIP_THREAD_STACKSIZE 2048
+#endif
 
+#ifndef TCPIP_MBOX_SIZE
+#define TCPIP_MBOX_SIZE 8
+#endif
+
+#ifndef DEFAULT_RAW_RECVMBOX_SIZE
+#define DEFAULT_RAW_RECVMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_UDP_RECVMBOX_SIZE
+#define DEFAULT_UDP_RECVMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_TCP_RECVMBOX_SIZE
+#define DEFAULT_TCP_RECVMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_ACCEPTMBOX_SIZE
+#define DEFAULT_ACCEPTMBOX_SIZE 50
+#endif
+
+#ifndef DEFAULT_THREAD_STACKSIZE
+#define DEFAULT_THREAD_STACKSIZE 500
+#endif
+
+#ifndef TCPIP_THREAD_PRIO
+#define TCPIP_THREAD_PRIO 10
+#endif
+
+#define LWIP_COMPAT_MUTEX       0
+#define LWIP_TCPIP_CORE_LOCKING 1
+
+#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT
 #define LWIP_TCPIP_CORE_LOCKING_INPUT 1
-#define LWIP_TCPIP_CORE_LOCKING       1
+#endif
+
+#ifndef LWIP_MEM_SECTION
+#define LWIP_MEM_SECTION ".bss"
+#endif
 
-#include <FreeRTOS.h>
-#include <task.h>
-#endif /* __LWIPOPTS_H__ */
+#endif /* __LWIPOPTS_H__ */

+ 7 - 4
tests/hpmicro/inc/usb_config.h

@@ -47,7 +47,7 @@
 #define USBD_MAX_POWER     200
 
 /* attribute data into no cache ram */
-#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable.non_init")))
+#define USB_NOCACHE_RAM_SECTION __attribute__((section(".fast_ram.non_init")))
 
 /* use usb_memcpy default for high performance but cost more flash memory.
  * And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
@@ -172,7 +172,7 @@
 #define CONFIG_USBHOST_MAX_EHPORTS          4
 #define CONFIG_USBHOST_MAX_INTERFACES       8
 #define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 2
-#define CONFIG_USBHOST_MAX_ENDPOINTS        8
+#define CONFIG_USBHOST_MAX_ENDPOINTS        4
 
 #define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4
 #define CONFIG_USBHOST_MAX_HID_CLASS     4
@@ -198,7 +198,7 @@
 
 /* Ep0 max transfer buffer */
 #ifndef CONFIG_USBHOST_REQUEST_BUFFER_LEN
-#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
+#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 4096
 #endif
 
 #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
@@ -213,7 +213,7 @@
  * you can change to 2K ~ 16K and must be larger than TCP RX windows size in order to avoid being overflow.
  */
 #ifndef CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE
-#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (2048)
+#define CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE (16 * 1024)
 #endif
 
 /* Because lwip do not support multi pbuf at a time, so increasing this variable has no performance improvement */
@@ -306,4 +306,7 @@
 #define usb_ramaddr2phyaddr(addr) sys_address_to_core_local_mem(BOARD_RUNNING_CORE, addr)
 #endif
 
+#define ATTR_FAST_RAM_SECTION __attribute__((section(".fast")))
+// #define CONFIG_USB_EHCI_ISO
+
 #endif

+ 1066 - 0
tests/hpmicro/src/font24x48.c

@@ -0,0 +1,1066 @@
+/*
+ * Copyright (c) 2022 HPMicro
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+const unsigned char nAsciiDot24x48[]=
+{
+//0x0020( )
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0021(!)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x1C,0x00,0x00,0x18,0x00,0x00,
+0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0022(")
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0x00,0x3C,0x1E,0x00,0x3C,0x1E,0x00,0x3C,0x1E,
+0x00,0x18,0x0C,0x00,0x18,0x0C,0x00,0x18,0x0C,0x00,0x18,0x0C,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0023(#)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x60,0x18,0x00,0x60,0x18,0x00,0x30,0x0C,0x00,0x30,0x0C,
+0x00,0x30,0x0C,0x00,0x30,0x0C,0x00,0xFF,0x3F,0x00,0xFF,0x3F,0x00,0x18,0x06,0x00,
+0x18,0x06,0x00,0x18,0x06,0x00,0x18,0x06,0x00,0xFF,0x3F,0x00,0xFF,0x3F,0x00,0x0C,
+0x03,0x00,0x0C,0x03,0x00,0x8C,0x03,0x00,0x86,0x01,0x00,0x86,0x01,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0024($)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x80,0x00,0x00,0xE0,0x07,0x00,0x98,0x1E,0x00,0x8C,0x18,0x00,0x8E,0x18,
+0x00,0x8E,0x10,0x00,0x9E,0x00,0x00,0xFE,0x00,0x00,0xFC,0x00,0x00,0xF8,0x03,0x00,
+0xF0,0x07,0x00,0xC0,0x1F,0x00,0x80,0x1F,0x00,0x80,0x3E,0x00,0x80,0x3C,0x00,0x82,
+0x38,0x00,0x86,0x38,0x00,0x86,0x18,0x00,0x9E,0x0C,0x00,0xF8,0x03,0x00,0x80,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0025(%)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x0C,0x98,0x01,0x06,0x9C,0x03,0x03,0x9C,0x03,
+0x03,0x9C,0x83,0x01,0x9C,0x83,0x01,0x9C,0xC3,0x00,0x9C,0x63,0x00,0x98,0x61,0x00,
+0xF0,0x30,0x3C,0x00,0x18,0x66,0x00,0x18,0xE7,0x00,0x0C,0xE7,0x00,0x0E,0xE7,0x00,
+0x06,0xE7,0x00,0x03,0xE7,0x00,0x03,0xE7,0x80,0x01,0x66,0xC0,0x00,0x3C,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0026(&)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x73,0x00,0x80,0xE1,0x00,0xC0,0xE1,
+0x00,0xC0,0xE1,0x00,0xC0,0x63,0x00,0xC0,0x3B,0x00,0xC0,0x07,0x00,0xC0,0x87,0x1F,
+0xF0,0x0F,0x0F,0x18,0x1F,0x06,0x1C,0x3F,0x03,0x1E,0x3E,0x01,0x1E,0xFC,0x01,0x3E,
+0xF8,0x00,0x7E,0xF0,0x33,0xFC,0xF8,0x1F,0xFC,0xCF,0x0F,0xF0,0x83,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0027(')
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0028(()
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xC0,0x00,0x00,0x60,0x00,0x00,0x70,0x00,
+0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,
+0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,
+0x00,0x00,0x1E,0x00,0x00,0x1C,0x00,0x00,0x1C,0x00,0x00,0x3C,0x00,0x00,0x38,0x00,
+0x00,0x38,0x00,0x00,0x70,0x00,0x00,0x60,0x00,0x00,0xC0,0x00,0x00,0x00,0x01,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0029())
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0x00,0x1C,0x00,
+0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,
+0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,
+0x00,0x00,0xF0,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x38,0x00,
+0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0C,0x00,0x00,0x06,0x00,0x00,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x002A(*)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x01,0x00,0xC0,0x01,0x00,0x98,0x0C,
+0x00,0xB8,0x0E,0x00,0xF0,0x07,0x00,0xC0,0x00,0x00,0x60,0x03,0x00,0x70,0x07,0x00,
+0x30,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x002B(+)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,
+0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x80,0x01,0x00,
+0xFE,0x7F,0x00,0xFE,0x7F,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x80,
+0x01,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x002C(,)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x1C,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x3C,0x00,0x00,0x30,0x00,
+0x00,0x30,0x00,0x00,0x18,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x002D(-)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x002E(.)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x0C,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x002F(/)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0xC0,0x00,0x00,0x60,0x00,0x00,0x60,0x00,
+0x00,0x60,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x18,0x00,0x00,
+0x18,0x00,0x00,0x18,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x06,
+0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x03,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0030(0)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0x00,0x30,0x07,0x00,0x18,0x06,0x00,0x1C,0x0E,
+0x00,0x1C,0x0E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,
+0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1C,
+0x0E,0x00,0x1C,0x0E,0x00,0x18,0x06,0x00,0x30,0x03,0x00,0xE0,0x01,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0031(1)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0xE0,0x01,0x00,0xF8,0x01,0x00,0xFC,0x01,
+0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,
+0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,
+0x01,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x03,0x00,0xFC,0x0F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0032(2)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xFC,0x03,0x00,0xFE,0x03,0x00,0xC6,0x07,
+0x00,0x83,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x03,0x00,0x80,0x03,0x00,
+0xC0,0x01,0x00,0xC0,0x00,0x00,0xE0,0x00,0x00,0x60,0x00,0x00,0x30,0x08,0x00,0x18,
+0x08,0x00,0xF8,0x0F,0x00,0xFC,0x07,0x00,0xFE,0x07,0x00,0xFF,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0033(3)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0x00,0xF8,0x03,0x00,0xC4,0x07,0x00,0x82,0x07,
+0x00,0x80,0x07,0x00,0x80,0x03,0x00,0xC0,0x01,0x00,0xE0,0x01,0x00,0xF0,0x03,0x00,
+0xE0,0x07,0x00,0x80,0x0F,0x00,0x80,0x0F,0x00,0x00,0x0F,0x00,0x00,0x0F,0x00,0x00,
+0x0F,0x00,0x07,0x07,0x00,0x8F,0x03,0x00,0xFF,0x01,0x00,0x7E,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0034(4)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x07,0x00,0x80,0x07,
+0x00,0xC0,0x07,0x00,0xA0,0x07,0x00,0xA0,0x07,0x00,0x90,0x07,0x00,0x88,0x07,0x00,
+0x88,0x07,0x00,0x84,0x07,0x00,0x82,0x07,0x00,0xFE,0x1F,0x00,0xFE,0x1F,0x00,0xFE,
+0x1F,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0035(5)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF0,0x1F,0x00,0xF0,0x1F,0x00,0xF8,0x0F,0x00,0xF8,0x0F,
+0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x7C,0x00,0x00,0xFC,0x03,0x00,0xFE,0x07,0x00,
+0xFE,0x0F,0x00,0xC0,0x1F,0x00,0x00,0x1E,0x00,0x00,0x1C,0x00,0x00,0x18,0x00,0x00,
+0x18,0x00,0x0E,0x08,0x00,0x1E,0x08,0x00,0x7E,0x04,0x00,0xF8,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0036(6)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x80,0x07,0x00,0xC0,0x01,0x00,0x70,0x00,
+0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0xFC,0x03,0x00,0x1C,0x0F,0x00,
+0x1E,0x0F,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,
+0x1E,0x00,0x1C,0x0E,0x00,0x3C,0x0E,0x00,0x38,0x07,0x00,0xE0,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0037(7)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFC,0x1F,0x00,0xFC,0x1F,0x00,0xFC,0x0F,0x00,0xFC,0x0F,
+0x00,0x06,0x0C,0x00,0x02,0x06,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x03,0x00,
+0x00,0x03,0x00,0x00,0x03,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0xC0,
+0x00,0x00,0xC0,0x00,0x00,0xC0,0x00,0x00,0x60,0x00,0x00,0x60,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0038(8)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF0,0x03,0x00,0x38,0x0E,0x00,0x1C,0x1C,0x00,0x1E,0x1C,
+0x00,0x1E,0x1C,0x00,0x3E,0x1C,0x00,0x7E,0x0E,0x00,0xFC,0x07,0x00,0xF8,0x03,0x00,
+0xF0,0x07,0x00,0xF8,0x0F,0x00,0x9C,0x1F,0x00,0x0E,0x1F,0x00,0x0E,0x1E,0x00,0x0E,
+0x1E,0x00,0x0E,0x1E,0x00,0x0C,0x0E,0x00,0x1C,0x07,0x00,0xF0,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0039(9)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0x00,0x38,0x07,0x00,0x1C,0x0F,0x00,0x1C,0x0E,
+0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,
+0x3C,0x1E,0x00,0x3C,0x1E,0x00,0xF0,0x0F,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x80,
+0x07,0x00,0x80,0x03,0x00,0xE0,0x01,0x00,0x78,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x003A(:)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,
+0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x18,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x003B(;)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,
+0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x38,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x78,0x00,0x00,0x60,0x00,
+0x00,0x60,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x003C(<)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+0x00,0x00,0xF0,0x00,0x00,0x7C,0x00,0x80,0x0F,0x00,0xE0,0x03,0x00,0x7C,0x00,0x00,
+0x1E,0x00,0x00,0x7C,0x00,0x00,0xE0,0x03,0x00,0x80,0x0F,0x00,0x00,0x7C,0x00,0x00,
+0xF0,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x003D(=)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x00,0xFE,0xFF,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x00,0xFE,0xFF,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x003E(>)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+0x00,0x0F,0x00,0x00,0x3E,0x00,0x00,0xF0,0x01,0x00,0xC0,0x07,0x00,0x00,0x3E,0x00,
+0x00,0x78,0x00,0x00,0x3E,0x00,0xC0,0x07,0x00,0xF0,0x01,0x00,0x3E,0x00,0x00,0x0F,
+0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x003F(?)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x00,0x18,0x0F,0x00,0x1C,0x1E,0x00,0x3C,0x1E,
+0x00,0x3C,0x1E,0x00,0x38,0x1E,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x00,
+0x00,0x03,0x00,0x80,0x01,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xC0,0x00,0x00,0xE0,0x01,0x00,0xE0,0x01,0x00,0xC0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0040(@)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x03,0x00,0x07,0x0E,0xC0,0x00,0x18,0x60,0x00,
+0x20,0x10,0x00,0x60,0x18,0x00,0x40,0x08,0x70,0x8F,0x04,0x98,0x87,0x04,0x8E,0x87,
+0x06,0x8F,0x87,0x02,0x87,0x87,0x82,0x87,0x83,0x82,0xC7,0x83,0xC2,0xC3,0x43,0xC2,
+0xE3,0x41,0xC2,0xF3,0x21,0xC2,0xFB,0x11,0xC4,0xEF,0x09,0x84,0xC7,0x87,0x08,0x00,
+0x80,0x18,0x00,0x40,0x30,0x00,0x20,0x60,0x00,0x18,0x80,0x01,0x06,0x00,0xFE,0x01,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0041(A)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x06,0x00,0x00,0x0E,0x00,0x00,0x0F,
+0x00,0x00,0x1F,0x00,0x80,0x1E,0x00,0x80,0x1E,0x00,0x80,0x3C,0x00,0x40,0x3C,0x00,
+0x40,0x7C,0x00,0x20,0x78,0x00,0x20,0x78,0x00,0x10,0xF0,0x00,0xF0,0xFF,0x00,0x10,
+0xF0,0x01,0x08,0xE0,0x01,0x0C,0xE0,0x03,0x0C,0xC0,0x07,0x3F,0xF8,0x0F,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0042(B)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0xF0,0xF0,0x00,0xF0,0xE0,0x01,0xF0,0xC0,
+0x03,0xF0,0xC0,0x03,0xF0,0xC0,0x03,0xF0,0xC0,0x03,0xF0,0xE0,0x01,0xF0,0xF0,0x00,
+0xF0,0x7F,0x00,0xF0,0xF0,0x01,0xF0,0xC0,0x03,0xF0,0xC0,0x07,0xF0,0xC0,0x07,0xF0,
+0xC0,0x07,0xF0,0xC0,0x07,0xF0,0xE0,0x03,0xF0,0xF0,0x01,0xFE,0x7F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0043(C)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x02,0xE0,0xC1,0x03,0xF0,0x80,0x03,0x78,0x00,
+0x03,0x78,0x00,0x02,0x3C,0x00,0x02,0x3C,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,
+0x3E,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x7C,0x00,0x00,0x7C,
+0x00,0x00,0x78,0x00,0x02,0xF0,0x00,0x03,0xE0,0xC1,0x01,0x80,0x7F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0044(D)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0x0F,0x00,0x3C,0x7C,0x00,0x3C,0xF0,0x00,0x3C,0xF0,
+0x01,0x3C,0xE0,0x03,0x3C,0xE0,0x03,0x3C,0xC0,0x07,0x3C,0xC0,0x07,0x3C,0xC0,0x07,
+0x3C,0xC0,0x07,0x3C,0xC0,0x07,0x3C,0xC0,0x07,0x3C,0xC0,0x07,0x3C,0xC0,0x03,0x3C,
+0xE0,0x03,0x3C,0xE0,0x01,0x3C,0xF0,0x00,0x3C,0x78,0x00,0xFF,0x0F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0045(E)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x01,0xF0,0xC0,0x01,0xF0,0x80,0x01,0xF0,0x00,
+0x01,0xF0,0x00,0x01,0xF0,0x10,0x00,0xF0,0x10,0x00,0xF0,0x18,0x00,0xF0,0x1C,0x00,
+0xF0,0x1F,0x00,0xF0,0x1C,0x00,0xF0,0x18,0x00,0xF0,0x10,0x00,0xF0,0x10,0x00,0xF0,
+0x00,0x02,0xF0,0x00,0x02,0xF0,0x00,0x03,0xF0,0xC0,0x01,0xFE,0xFF,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0046(F)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x01,0xF0,0xC0,0x01,0xF0,0x80,0x01,0xF0,0x00,
+0x01,0xF0,0x00,0x01,0xF0,0x10,0x00,0xF0,0x10,0x00,0xF0,0x18,0x00,0xF0,0x18,0x00,
+0xF0,0x1F,0x00,0xF0,0x18,0x00,0xF0,0x18,0x00,0xF0,0x10,0x00,0xF0,0x10,0x00,0xF0,
+0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xFE,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0047(G)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x04,0xE0,0xC1,0x07,0xF0,0x00,0x07,0x78,0x00,
+0x06,0x7C,0x00,0x06,0x7C,0x00,0x04,0x3C,0x00,0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,
+0x3E,0x00,0x00,0x3E,0x00,0x00,0x3E,0xF0,0x3F,0x3E,0x80,0x0F,0x3C,0x80,0x07,0x7C,
+0x80,0x07,0x78,0x80,0x07,0xF0,0x80,0x07,0xE0,0x83,0x07,0x00,0xFF,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0048(H)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0xF3,0x3F,0x78,0x80,0x07,0x78,0x80,0x07,0x78,0x80,
+0x07,0x78,0x80,0x07,0x78,0x80,0x07,0x78,0x80,0x07,0x78,0x80,0x07,0x78,0x80,0x07,
+0xF8,0xFF,0x07,0x78,0x80,0x07,0x78,0x80,0x07,0x78,0x80,0x07,0x78,0x80,0x07,0x78,
+0x80,0x07,0x78,0x80,0x07,0x78,0x80,0x07,0x78,0x80,0x07,0xFF,0xF3,0x3F,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0049(I)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0x03,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,
+0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,
+0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,
+0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0xFF,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x004A(J)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF0,0x3F,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,
+0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,
+0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x86,0x07,0x00,0x8F,
+0x07,0x00,0x8F,0x07,0x00,0x87,0x03,0x00,0xC6,0x01,0x00,0xF8,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x004B(K)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0x87,0x3F,0xF0,0x00,0x0E,0xF0,0x00,0x02,0xF0,0x00,
+0x01,0xF0,0x80,0x00,0xF0,0x60,0x00,0xF0,0x10,0x00,0xF0,0x08,0x00,0xF0,0x0E,0x00,
+0xF0,0x1F,0x00,0xF0,0x3E,0x00,0xF0,0x7C,0x00,0xF0,0xF8,0x00,0xF0,0xF0,0x01,0xF0,
+0xF0,0x01,0xF0,0xE0,0x03,0xF0,0xC0,0x07,0xF0,0xC0,0x1F,0xFE,0xE7,0x7F,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x004C(L)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,
+0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,
+0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x02,0xF0,0x00,0x02,0xF0,
+0x00,0x03,0xF0,0x00,0x03,0xF0,0x80,0x01,0xF0,0xC0,0x01,0xFE,0xFF,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x004D(M)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF8,0xF8,0x00,0x7C,0xF8,0x00,0x7C,0xF8,0x01,
+0x7A,0xE8,0x01,0x7A,0xE8,0x03,0x7A,0xC8,0x03,0x79,0xC8,0x03,0x79,0xC8,0x87,0x78,
+0x88,0x87,0x78,0x88,0x8F,0x78,0x08,0x4F,0x78,0x08,0x5F,0x78,0x08,0x3E,0x78,0x08,
+0x3E,0x78,0x08,0x3C,0x78,0x08,0x1C,0x78,0x08,0x18,0x78,0x7F,0x08,0xFF,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x004E(N)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x7E,0xE0,0x0F,0xF8,0x80,0x03,0xF8,0x01,0x01,0xE8,0x03,
+0x01,0xC8,0x03,0x01,0xC8,0x07,0x01,0x88,0x0F,0x01,0x08,0x1F,0x01,0x08,0x1E,0x01,
+0x08,0x3E,0x01,0x08,0x7C,0x01,0x08,0xF8,0x01,0x08,0xF0,0x01,0x08,0xF0,0x01,0x08,
+0xE0,0x01,0x08,0xC0,0x01,0x08,0x80,0x01,0x1C,0x80,0x01,0x7F,0x00,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x004F(O)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x80,0x7F,0x00,0xE0,0xE1,0x01,0xF0,0xC0,0x03,0x78,0x80,
+0x07,0x7C,0x80,0x0F,0x3C,0x00,0x0F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,
+0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3C,0x00,0x0F,0x7C,
+0x80,0x0F,0x78,0x80,0x07,0xF0,0xC0,0x03,0xE0,0xE1,0x01,0x80,0x7F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0050(P)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0x1F,0x00,0x78,0x78,0x00,0x78,0xF0,0x00,0x78,0xE0,
+0x01,0x78,0xE0,0x01,0x78,0xE0,0x01,0x78,0xE0,0x01,0x78,0xF0,0x00,0x78,0x78,0x00,
+0xF8,0x1F,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,
+0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0xFF,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0051(Q)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0xE0,0xE1,0x01,0xF0,0xC0,0x03,0x78,0x80,
+0x07,0x7C,0x80,0x0F,0x3C,0x00,0x0F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,
+0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3E,0x00,0x1F,0x3C,0x00,0x0F,0x7C,
+0x80,0x0F,0x78,0x80,0x07,0xF0,0xC0,0x03,0xE0,0xE1,0x01,0x80,0x7F,0x00,0x00,0x3E,
+0x00,0x00,0x3E,0x00,0x00,0x7C,0x00,0x00,0xF8,0x00,0x00,0xE0,0x0F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0052(R)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0x3F,0x00,0x78,0xF0,0x00,0x78,0xE0,0x01,0x78,0xC0,
+0x03,0x78,0xC0,0x03,0x78,0xC0,0x03,0x78,0xC0,0x03,0x78,0xE0,0x01,0x78,0xF0,0x00,
+0xF8,0x7F,0x00,0x78,0x3E,0x00,0x78,0x3C,0x00,0x78,0x7C,0x00,0x78,0xF8,0x00,0x78,
+0xF0,0x01,0x78,0xE0,0x01,0x78,0xE0,0x03,0x78,0xC0,0x07,0xFF,0x83,0x0F,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0053(S)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF0,0x23,0x00,0x38,0x3C,0x00,0x1C,0x38,0x00,0x1E,0x30,
+0x00,0x1E,0x20,0x00,0x3E,0x20,0x00,0xFE,0x00,0x00,0xFC,0x01,0x00,0xF8,0x07,0x00,
+0xF0,0x0F,0x00,0xC0,0x3F,0x00,0x00,0x3F,0x00,0x02,0x7E,0x00,0x02,0x7C,0x00,0x06,
+0x78,0x00,0x06,0x78,0x00,0x0E,0x38,0x00,0x3E,0x1C,0x00,0xE2,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0054(T)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x01,0x8E,0xC7,0x01,0x86,0x87,0x01,0x82,0x07,
+0x01,0x82,0x07,0x01,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,
+0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,
+0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0x80,0x07,0x00,0xF0,0x3F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0055(U)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0xE3,0x0F,0x78,0x80,0x03,0x78,0x00,0x01,0x78,0x00,
+0x01,0x78,0x00,0x01,0x78,0x00,0x01,0x78,0x00,0x01,0x78,0x00,0x01,0x78,0x00,0x01,
+0x78,0x00,0x01,0x78,0x00,0x01,0x78,0x00,0x01,0x78,0x00,0x01,0x78,0x00,0x01,0x78,
+0x00,0x01,0x78,0x80,0x00,0xF0,0x80,0x00,0xE0,0x61,0x00,0x80,0x1F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0056(V)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0xC1,0x0F,0x7C,0x00,0x07,0x78,0x00,0x03,0x78,0x00,
+0x01,0xF0,0x80,0x00,0xF0,0x80,0x00,0xF0,0x81,0x00,0xE0,0x41,0x00,0xE0,0x41,0x00,
+0xC0,0x23,0x00,0xC0,0x23,0x00,0xC0,0x17,0x00,0x80,0x17,0x00,0x80,0x17,0x00,0x00,
+0x0F,0x00,0x00,0x0F,0x00,0x00,0x07,0x00,0x00,0x06,0x00,0x00,0x06,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0057(W)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0xFC,0xC7,0x3E,0xF0,0x01,0x3C,0xF0,0x01,0x78,0xE0,
+0x01,0x78,0xE0,0x83,0xF8,0xE0,0x83,0xF0,0xE0,0x83,0xF0,0xE0,0x47,0xF0,0x91,0x47,
+0xE0,0x91,0x47,0xE0,0x11,0x2F,0xC0,0x0B,0x2F,0xC0,0x0B,0x2F,0xC0,0x07,0x1E,0x80,
+0x07,0x1E,0x80,0x07,0x1E,0x80,0x03,0x0C,0x00,0x03,0x0C,0x00,0x03,0x0C,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0058(X)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFF,0xF1,0x03,0x7C,0xC0,0x00,0x78,0x40,0x00,0xF8,0x20,
+0x00,0xF0,0x31,0x00,0xE0,0x11,0x00,0xE0,0x0B,0x00,0xC0,0x07,0x00,0x80,0x07,0x00,
+0x80,0x0F,0x00,0x00,0x0F,0x00,0x80,0x1F,0x00,0x40,0x3E,0x00,0x40,0x3C,0x00,0x20,
+0x7C,0x00,0x10,0xF8,0x00,0x08,0xF0,0x00,0x1C,0xF0,0x01,0x7F,0xFC,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0059(Y)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0xC1,0x0F,0x7C,0x00,0x03,0x78,0x00,0x01,0xF0,0x00,
+0x01,0xF0,0x81,0x00,0xE0,0x41,0x00,0xE0,0x43,0x00,0xC0,0x23,0x00,0xC0,0x27,0x00,
+0x80,0x17,0x00,0x80,0x1F,0x00,0x00,0x0F,0x00,0x00,0x0F,0x00,0x00,0x0F,0x00,0x00,
+0x0F,0x00,0x00,0x0F,0x00,0x00,0x0F,0x00,0x00,0x0F,0x00,0xE0,0x7F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x005A(Z)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x00,0x1E,0x78,0x00,0x06,0x3C,0x00,0x06,0x3E,
+0x00,0x02,0x1E,0x00,0x00,0x1F,0x00,0x00,0x0F,0x00,0x80,0x07,0x00,0xC0,0x07,0x00,
+0xC0,0x03,0x00,0xE0,0x03,0x00,0xE0,0x01,0x00,0xF0,0x00,0x01,0xF8,0x00,0x01,0x78,
+0x80,0x01,0x7C,0x80,0x01,0x3C,0xC0,0x01,0x1E,0xF0,0x00,0xFF,0xFF,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x005B([)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xF8,0x01,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,
+0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,
+0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,
+0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,
+0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0xF8,0x01,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x005C(\)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x07,0x00,0x00,0x06,0x00,0x00,0x06,0x00,
+0x00,0x06,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x18,0x00,0x00,
+0x18,0x00,0x00,0x18,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x30,0x00,0x00,0x60,
+0x00,0x00,0x60,0x00,0x00,0x60,0x00,0x00,0xE0,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x005D(])
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,
+0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,
+0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,
+0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,
+0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x3F,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x005E(^)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x80,0x03,0x00,0xC0,0x06,0x00,0xC0,0x06,
+0x00,0x60,0x0C,0x00,0x60,0x0C,0x00,0x30,0x18,0x00,0x18,0x30,0x00,0x18,0x30,0x00,
+0x0C,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x005F(_)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x3F,0x00,0xFF,0x3F,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0060(`)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x18,0x00,
+0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0061(a)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x03,0x00,0x0C,0x07,0x00,0x0E,0x0F,0x00,
+0x1E,0x0F,0x00,0x8C,0x0F,0x00,0x40,0x0F,0x00,0x30,0x0F,0x00,0x18,0x0F,0x00,0x1C,
+0x0F,0x00,0x1E,0x0F,0x00,0x9E,0x0F,0x00,0x7E,0x1F,0x00,0x3C,0x0E,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0062(b)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x0F,0x00,0xFC,0x1F,0x00,0x7C,0x3C,0x00,
+0x3C,0x78,0x00,0x3C,0x78,0x00,0x3C,0x78,0x00,0x3C,0x78,0x00,0x3C,0x78,0x00,0x3C,
+0x78,0x00,0x3C,0x38,0x00,0x3C,0x38,0x00,0x7C,0x1C,0x00,0xCC,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0063(c)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0x00,0xB8,0x07,0x00,0x1C,0x07,0x00,
+0x1C,0x07,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x3E,
+0x00,0x00,0x3E,0x00,0x00,0x7C,0x06,0x00,0xF8,0x03,0x00,0xF0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0064(d)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,
+0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0xF0,0x3C,0x00,0x38,0x3F,0x00,0x1C,0x3E,0x00,
+0x1C,0x3C,0x00,0x1E,0x3C,0x00,0x1E,0x3C,0x00,0x1E,0x3C,0x00,0x1E,0x3C,0x00,0x1E,
+0x3C,0x00,0x3E,0x3C,0x00,0x3C,0x3E,0x00,0xF8,0x7F,0x00,0xF0,0x1C,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0065(e)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xB8,0x03,0x00,0x1C,0x03,0x00,
+0x1C,0x07,0x00,0x1E,0x07,0x00,0xFE,0x07,0x00,0x1E,0x00,0x00,0x1E,0x00,0x00,0x1E,
+0x00,0x00,0x3E,0x04,0x00,0x7C,0x02,0x00,0xF8,0x01,0x00,0xF0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0066(f)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x00,0x38,0x07,0x00,0x3C,0x07,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0xFF,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,
+0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,
+0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0067(g)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x1F,0x00,0xBC,0x1F,0x00,0x1E,0x07,0x00,
+0x1E,0x0F,0x00,0x1E,0x0F,0x00,0x1E,0x0F,0x00,0x1C,0x0F,0x00,0xBC,0x07,0x00,0xF0,
+0x01,0x00,0x0C,0x00,0x00,0x0E,0x00,0x00,0xFE,0x07,0x00,0xFE,0x0F,0x00,0xFC,0x1F,
+0x00,0x0C,0x1C,0x00,0x06,0x18,0x00,0x06,0x08,0x00,0x0C,0x0C,0x00,0xF8,0x03,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0068(h)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x0F,0x00,0xBC,0x1F,0x00,0x7C,0x3C,0x00,
+0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,
+0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x7E,0x7E,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0069(i)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x18,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,
+0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,
+0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x006A(j)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x30,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,
+0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,
+0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,0x00,0x78,0x00,
+0x00,0x78,0x00,0x00,0x79,0x00,0x00,0x79,0x00,0x00,0x39,0x00,0x00,0x1F,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x006B(k)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x3E,0x00,0x3C,0x1C,0x00,0x3C,0x0C,0x00,
+0x3C,0x04,0x00,0x3C,0x02,0x00,0xBC,0x03,0x00,0xFC,0x07,0x00,0xBC,0x0F,0x00,0x3C,
+0x0F,0x00,0x3C,0x1E,0x00,0x3C,0x3E,0x00,0x3C,0x7C,0x00,0x7E,0xFE,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x006C(l)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,
+0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,
+0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x006D(m)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x87,0x03,0xBC,0xCF,0x07,0x7C,0x3E,0x0F,
+0x3C,0x1E,0x0F,0x3C,0x1E,0x0F,0x3C,0x1E,0x0F,0x3C,0x1E,0x0F,0x3C,0x1E,0x0F,0x3C,
+0x1E,0x0F,0x3C,0x1E,0x0F,0x3C,0x1E,0x0F,0x3C,0x1E,0x0F,0x7E,0xBF,0x1F,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x006E(n)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x0F,0x00,0xBC,0x1F,0x00,0x7C,0x3C,0x00,
+0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,
+0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x7E,0x7E,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x006F(o)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x03,0x00,0x38,0x07,0x00,0x1C,0x0E,0x00,
+0x1C,0x0E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,0x1E,0x00,0x1E,
+0x1E,0x00,0x1C,0x0E,0x00,0x1C,0x0E,0x00,0x38,0x07,0x00,0xF0,0x03,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0070(p)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBE,0x0F,0x00,0xFC,0x1F,0x00,0x7C,0x3C,0x00,
+0x3C,0x38,0x00,0x3C,0x78,0x00,0x3C,0x78,0x00,0x3C,0x78,0x00,0x3C,0x78,0x00,0x3C,
+0x78,0x00,0x3C,0x38,0x00,0x3C,0x38,0x00,0x7C,0x1C,0x00,0xBC,0x0F,0x00,0x3C,0x00,
+0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0071(q)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x33,0x00,0x38,0x3E,0x00,0x3C,0x3C,0x00,
+0x1C,0x3C,0x00,0x1E,0x3C,0x00,0x1E,0x3C,0x00,0x1E,0x3C,0x00,0x1E,0x3C,0x00,0x1E,
+0x3C,0x00,0x1E,0x3C,0x00,0x3C,0x3E,0x00,0xF8,0x3F,0x00,0xF0,0x3C,0x00,0x00,0x3C,
+0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x7E,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0072(r)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x07,0x00,0xBC,0x0F,0x00,0x7C,0x0F,0x00,
+0x3C,0x06,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,
+0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0073(s)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x01,0x00,0xCC,0x01,0x00,0x8E,0x01,0x00,
+0x1E,0x01,0x00,0x3E,0x00,0x00,0xFC,0x00,0x00,0xFC,0x01,0x00,0xF0,0x03,0x00,0xE0,
+0x03,0x00,0x82,0x03,0x00,0x86,0x03,0x00,0x8E,0x01,0x00,0xF2,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0074(t)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x30,0x00,0x00,0x30,0x00,
+0x00,0x38,0x00,0x00,0x3E,0x00,0x00,0xFF,0x01,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,
+0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00,0x3C,
+0x00,0x00,0x3C,0x00,0x00,0x3C,0x01,0x00,0xFC,0x00,0x00,0x70,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0075(u)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x3E,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,
+0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3C,0x00,0x3C,
+0x3C,0x00,0x3C,0x3C,0x00,0x3C,0x3E,0x00,0xF8,0x3F,0x00,0xF0,0x7C,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0076(v)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x3C,0x00,0x3E,0x18,0x00,0x3C,0x08,0x00,
+0x3C,0x04,0x00,0x78,0x04,0x00,0x78,0x04,0x00,0xF0,0x02,0x00,0xF0,0x02,0x00,0xF0,
+0x01,0x00,0xE0,0x01,0x00,0xE0,0x00,0x00,0xC0,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0077(w)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0xBF,0x07,0x1E,0x0F,0x03,0x3E,0x1E,0x01,
+0x3C,0x1E,0x01,0x3C,0xBF,0x00,0x78,0xBD,0x00,0x78,0xBD,0x00,0xF8,0x7C,0x00,0xF0,
+0x78,0x00,0xF0,0x78,0x00,0x70,0x78,0x00,0x60,0x30,0x00,0x60,0x30,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0078(x)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x1F,0x00,0x7C,0x0C,0x00,0x78,0x04,0x00,
+0xF0,0x02,0x00,0xF0,0x01,0x00,0xE0,0x01,0x00,0xE0,0x03,0x00,0xC0,0x03,0x00,0xE0,
+0x07,0x00,0xA0,0x07,0x00,0x10,0x0F,0x00,0x18,0x1F,0x00,0xBE,0x3F,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x0079(y)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x3C,0x00,0x3E,0x18,0x00,0x3C,0x08,0x00,
+0x7C,0x08,0x00,0x78,0x04,0x00,0xF8,0x04,0x00,0xF0,0x02,0x00,0xF0,0x03,0x00,0xE0,
+0x03,0x00,0xE0,0x01,0x00,0xC0,0x01,0x00,0xC0,0x00,0x00,0x80,0x00,0x00,0x80,0x00,
+0x00,0x40,0x00,0x00,0x4E,0x00,0x00,0x2F,0x00,0x00,0x3F,0x00,0x00,0x1E,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x007A(z)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x00,0xC6,0x03,0x00,0xC2,0x03,0x00,
+0xE2,0x01,0x00,0xE0,0x01,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x78,
+0x00,0x00,0x3C,0x04,0x00,0x3C,0x06,0x00,0x1E,0x07,0x00,0xFF,0x07,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x007B({)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0xE0,0x00,0x00,0x60,0x00,0x00,0x70,0x00,
+0x00,0x70,0x00,0x00,0x70,0x00,0x00,0xF0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,
+0xE0,0x00,0x00,0x60,0x00,0x00,0x30,0x00,0x00,0x0C,0x00,0x00,0x30,0x00,0x00,0x60,
+0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xE0,0x00,0x00,0xF0,0x00,0x00,0x70,0x00,
+0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x60,0x00,0x00,0xE0,0x00,0x00,0x80,0x03,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x007C(|)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,
+0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,
+0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,
+0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,
+0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x007D(})
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x38,0x00,0x00,0x30,0x00,0x00,0x70,0x00,
+0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x78,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,
+0x38,0x00,0x00,0x30,0x00,0x00,0x60,0x00,0x00,0x80,0x01,0x00,0x60,0x00,0x00,0x30,
+0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x38,0x00,0x00,0x78,0x00,0x00,0x70,0x00,
+0x00,0x70,0x00,0x00,0x70,0x00,0x00,0x30,0x00,0x00,0x38,0x00,0x00,0x0E,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x007E(~)
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x3C,0x40,0x00,0xFE,0x61,0x00,0xC3,0x3F,0x00,0x01,0x1E,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+//0x007F()
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,
+0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,
+0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,
+0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,
+0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xC6,0x01,0x00,0xFE,0x01,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+};

+ 763 - 0
tests/hpmicro/src/iperf/iperf.c

@@ -0,0 +1,763 @@
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <lwip/sockets.h>
+#include <FreeRTOS.h>
+#include <task.h>
+
+#include "iperf.h"
+
+#include "hpm_clock_drv.h"
+#include "hpm_csr_drv.h"
+#include "board.h"
+
+// TODO move to common
+#define xTaskCreatePinnedToCore(pvTaskCode, pcName, usStackDepth, \
+                                pvParameters, uxPriority,         \
+                                pvCreatedTask, xCoreID_)          \
+    xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters,   \
+                uxPriority, pvCreatedTask)
+
+int64_t iperf_timer_get_time()
+{
+    return (hpm_csr_get_core_mcycle() / (clock_get_frequency(clock_cpu0) / 1000000));
+}
+
+#define iperf_delay_us       board_delay_us
+#define IRAM_ATTR            __attribute__((section(".fast"))) // on tcm run
+#define IPERF_V6             0                // TODO sync with lwip config
+#define iperf_err_t          int
+#define IPERF_OK             0  /*!< iperf_err_t value indicating success (no error) */
+#define IPERF_FAIL           -1 /*!< Generic iperf_err_t code indicating failure */
+
+#define IPERF_LOGE(tag, format, ...)                       \
+    do {                                                   \
+        (void)tag;                                         \
+        printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
+    } while (0)
+
+#define IPERF_LOGW(tag, format, ...)                       \
+    do {                                                   \
+        (void)tag;                                         \
+        printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
+    } while (0)
+
+#define IPERF_LOGI(tag, format, ...)                       \
+    do {                                                   \
+        (void)tag;                                         \
+        printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
+    } while (0)
+
+#define IPERF_LOGD(tag, format, ...)                       \
+    do {                                                   \
+        (void)tag;                                         \
+        printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
+    } while (0)
+
+#define IPERF_LOGV(tag, format, ...)                       \
+    do {                                                   \
+        (void)tag;                                         \
+        printf("[%s] " format "\r\n", tag, ##__VA_ARGS__); \
+    } while (0)
+
+#define IPERF_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format, ...) \
+    do {                                                                 \
+        (void)log_tag;                                                   \
+        if ((!(a))) {                                            \
+            ret = err_code;                                              \
+            goto goto_tag;                                               \
+        }                                                                \
+    } while (0)
+
+#define NL "\r\n"
+
+typedef struct {
+    iperf_cfg_t cfg;
+    bool finish;
+    uint32_t actual_len;
+    uint32_t tot_len;
+    uint32_t buffer_len;
+    uint8_t *buffer;
+    uint32_t sockfd;
+} iperf_ctrl_t;
+
+static bool s_iperf_is_running = false;
+static iperf_ctrl_t s_iperf_ctrl;
+static const char *TAG = "iperf";
+
+inline static bool iperf_is_udp_client(void)
+{
+    return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
+}
+
+inline static bool iperf_is_udp_server(void)
+{
+    return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
+}
+
+inline static bool iperf_is_tcp_client(void)
+{
+    return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
+}
+
+inline static bool iperf_is_tcp_dual_client(void)
+{
+    return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_DUAL));
+}
+
+inline static bool iperf_is_tcp_server(void)
+{
+    return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
+}
+
+static int iperf_get_socket_error_code(int sockfd)
+{
+    return errno;
+}
+
+static int iperf_show_socket_error_reason(const char *str, int sockfd)
+{
+    int err = errno;
+    if (err != 0) {
+        IPERF_LOGW(TAG, "%s error, error code: %d, reason: %s", str, err, strerror(err));
+    }
+
+    return err;
+}
+
+static void iperf_report_task(void *arg)
+{
+    uint32_t interval = s_iperf_ctrl.cfg.interval;
+    uint32_t time = s_iperf_ctrl.cfg.time;
+    TickType_t delay_interval = (interval * 1000) / portTICK_PERIOD_MS;
+    uint32_t cur = 0;
+    double average = 0;
+    double actual_bandwidth = 0;
+    double actual_transfer = 0;
+    int k = 1;
+
+    printf("[ ID] Interval       Transfer     Bandwidth\r\n");
+    while (!s_iperf_ctrl.finish) {
+        vTaskDelay(delay_interval);
+        actual_bandwidth = (s_iperf_ctrl.actual_len / 1e6 * 8) / interval;
+        actual_transfer = s_iperf_ctrl.actual_len / 1e6;
+        printf("[%3d] %2d.0-%2d.0 sec  %.2f MByte  %.2f Mbits/sec\r\n",
+               s_iperf_ctrl.sockfd, cur, cur + interval, actual_transfer, actual_bandwidth);
+        cur += interval;
+        average = ((average * (k - 1) / k) + (actual_bandwidth / k));
+        k++;
+        s_iperf_ctrl.actual_len = 0;
+        if (cur >= time) {
+            actual_transfer = s_iperf_ctrl.tot_len / 1e6;
+            printf("[%3d] %2d.0-%2d.0 sec  %.2f MByte  %.2f Mbits/sec\r\n",
+                   s_iperf_ctrl.sockfd, 0, time, actual_transfer, average);
+            break;
+        }
+    }
+
+    s_iperf_ctrl.finish = true;
+    vTaskDelete(NULL);
+}
+
+static iperf_err_t iperf_start_report(void)
+{
+    int ret;
+
+    ret = xTaskCreatePinnedToCore(iperf_report_task, IPERF_REPORT_TASK_NAME, IPERF_REPORT_TASK_STACK, NULL, s_iperf_ctrl.cfg.traffic_task_priority, NULL, portNUM_PROCESSORS - 1);
+
+    if (ret != pdPASS) {
+        IPERF_LOGE(TAG, "create task %s failed", IPERF_REPORT_TASK_NAME);
+        return IPERF_FAIL;
+    }
+
+    return IPERF_OK;
+}
+
+static void socket_recv(int recv_socket, struct sockaddr_storage listen_addr, uint8_t type)
+{
+    bool iperf_recv_start = true;
+    uint8_t *buffer;
+    int want_recv = 0;
+    int actual_recv = 0;
+#if IPERF_V6
+    socklen_t socklen = (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+#else
+    socklen_t socklen = sizeof(struct sockaddr_in);
+#endif
+    const char *error_log = (type == IPERF_TRANS_TYPE_TCP) ? "tcp server recv" : "udp server recv";
+
+    buffer = s_iperf_ctrl.buffer;
+    want_recv = s_iperf_ctrl.buffer_len;
+    while (!s_iperf_ctrl.finish) {
+        actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &socklen);
+        if (actual_recv < 0) {
+            iperf_show_socket_error_reason(error_log, recv_socket);
+            s_iperf_ctrl.finish = true;
+            break;
+        } else {
+            if (iperf_recv_start) {
+                iperf_start_report();
+                iperf_recv_start = false;
+            }
+            s_iperf_ctrl.actual_len += actual_recv;
+            s_iperf_ctrl.tot_len += actual_recv;
+            if (s_iperf_ctrl.cfg.num_bytes > 0 && s_iperf_ctrl.tot_len > s_iperf_ctrl.cfg.num_bytes) {
+                break;
+            }
+        }
+    }
+}
+
+static void socket_recv_dual(int recv_socket, struct sockaddr_storage listen_addr, uint8_t type)
+{
+    uint8_t *buffer;
+    int want_recv = 0;
+    int actual_recv = 0;
+    socklen_t socklen = sizeof(struct sockaddr_in);
+
+#define RECV_DUAL_BUF_LEN (16 * 1024)
+    buffer = pvPortMalloc(RECV_DUAL_BUF_LEN);
+    want_recv = RECV_DUAL_BUF_LEN;
+    if (!buffer) {
+        return;
+    }
+    while (1) {
+        actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &socklen);
+        if (actual_recv <= 0) {
+            break;
+        }
+    }
+    vPortFree(buffer);
+}
+
+typedef struct {
+    int32_t flags;
+    int32_t numThreads;
+    int32_t mPort;
+    int32_t bufferlen;
+    int32_t mWindowSize;
+    int32_t mAmount;
+    int32_t mRate;
+    int32_t mUDPRateUnits;
+    int32_t mRealtime;
+} iperf_client_hdr_t;
+#define HEADER_VERSION1 0x80000000
+#define RUN_NOW         0x00000001
+#define UNITS_PPS       0x00000002
+
+static void send_dual_header(int sock, struct sockaddr *addr, socklen_t socklen)
+{
+    iperf_client_hdr_t hdr = {};
+    iperf_cfg_t *cfg = &s_iperf_ctrl.cfg;
+
+    hdr.flags = htonl(HEADER_VERSION1 | RUN_NOW);
+    hdr.numThreads = htonl(1);
+    hdr.mPort = htonl(cfg->sport);
+    hdr.mAmount = htonl(-(cfg->time * 100));
+
+    sendto(sock, &hdr, sizeof(hdr), 0, addr, socklen);
+}
+
+static void socket_send(int send_socket, struct sockaddr_storage dest_addr, uint8_t type, int bw_lim)
+{
+    uint8_t *buffer;
+    int32_t *pkt_id_p;
+    int32_t pkt_cnt = 0;
+    int actual_send = 0;
+    int want_send = 0;
+    int period_us = -1;
+    int delay_us = 0;
+    int64_t prev_time = 0;
+    int64_t send_time = 0;
+    int err = 0;
+#if IPERF_V6
+    const socklen_t socklen = (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+#else
+    const socklen_t socklen = sizeof(struct sockaddr_in);
+#endif
+    const char *error_log = (type == IPERF_TRANS_TYPE_TCP) ? "tcp client send" : "udp client send";
+
+    buffer = s_iperf_ctrl.buffer;
+    pkt_id_p = (int32_t *)s_iperf_ctrl.buffer;
+    want_send = s_iperf_ctrl.buffer_len;
+    iperf_start_report();
+
+    if (bw_lim > 0) {
+        period_us = want_send * 8 / bw_lim;
+    }
+
+    if (iperf_is_tcp_dual_client()) {
+        send_dual_header(send_socket, (struct sockaddr *)&dest_addr, socklen);
+    }
+
+    while (!s_iperf_ctrl.finish) {
+        if (period_us > 0) {
+            send_time = iperf_timer_get_time();
+            if (actual_send > 0) {
+                // Last packet "send" was successful, check how much off the previous loop duration was to the ideal send period. Result will adjust the
+                // next send delay.
+                delay_us += period_us + (int32_t)(prev_time - send_time);
+            } else {
+                // Last packet "send" was not successful. Ideally we should try to catch up the whole previous loop duration (e.g. prev_time - send_time).
+                // However, that's not possible since the most probable reason why the send was unsuccessful is the HW was not able to process the packet.
+                // Hence, we cannot queue more packets with shorter (or no) delay to catch up since we are already at the performance edge. The best we
+                // can do is to reset the send delay (which is probably big negative number) and start all over again.
+                delay_us = 0;
+            }
+            prev_time = send_time;
+        }
+        *pkt_id_p = htonl(pkt_cnt); // datagrams need to be sequentially numbered
+        if (pkt_cnt >= INT32_MAX) {
+            pkt_cnt = 0;
+        } else {
+            pkt_cnt++;
+        }
+        actual_send = sendto(send_socket, buffer, want_send, 0, (struct sockaddr *)&dest_addr, socklen);
+        if (actual_send != want_send) {
+            if (type == IPERF_TRANS_TYPE_UDP) {
+                err = iperf_get_socket_error_code(send_socket);
+                // ENOMEM is expected under heavy load => do not print it
+                if (err != ENOMEM) {
+                    iperf_show_socket_error_reason(error_log, send_socket);
+                }
+            } else if (type == IPERF_TRANS_TYPE_TCP) {
+                iperf_show_socket_error_reason(error_log, send_socket);
+                break;
+            }
+        } else {
+            s_iperf_ctrl.actual_len += actual_send;
+            s_iperf_ctrl.tot_len += actual_send;
+            if (s_iperf_ctrl.cfg.num_bytes > 0 && s_iperf_ctrl.tot_len >= s_iperf_ctrl.cfg.num_bytes) {
+                break;
+            }
+        }
+        // The send delay may be negative, it indicates we are trying to catch up and hence to not delay the loop at all.
+        if (delay_us > 0) {
+            iperf_delay_us(delay_us);
+        }
+    }
+}
+
+static iperf_err_t IRAM_ATTR iperf_run_tcp_server(void)
+{
+    int listen_socket = -1;
+    int client_socket = -1;
+    int opt = 1;
+    int err = 0;
+    iperf_err_t ret = IPERF_OK;
+    struct sockaddr_in remote_addr;
+    struct timeval timeout = { 0 };
+    socklen_t addr_len = sizeof(struct sockaddr);
+    struct sockaddr_storage listen_addr = { 0 };
+#if IPERF_V6
+    struct sockaddr_in6 listen_addr6 = { 0 };
+#endif
+    struct sockaddr_in listen_addr4 = { 0 };
+
+    IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
+
+#if IPERF_V6
+    if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
+        // The TCP server listen at the address "::", which means all addresses can be listened to.
+        inet6_aton("::", &listen_addr6.sin6_addr);
+        listen_addr6.sin6_family = AF_INET6;
+        listen_addr6.sin6_port = htons(s_iperf_ctrl.cfg.sport);
+
+        listen_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
+        IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+
+        setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+        setsockopt(listen_socket, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
+
+        IPERF_LOGI(TAG, "Socket created");
+
+        err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(listen_addr6));
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET6);
+        err = listen(listen_socket, 1);
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
+
+        timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
+        setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+        memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
+    } else
+#endif
+        if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
+        listen_addr4.sin_family = AF_INET;
+        listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
+        listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
+
+        listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+        IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+
+        setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+        IPERF_LOGI(TAG, "Socket created");
+
+        err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(listen_addr4));
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET);
+
+        err = listen(listen_socket, 5);
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
+        memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
+    }
+
+    client_socket = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
+    IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to accept connection: errno %d", errno);
+    IPERF_LOGI(TAG, "accept: %s,%d\n", inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
+
+    timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
+    setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+    socket_recv(client_socket, listen_addr, IPERF_TRANS_TYPE_TCP);
+exit:
+    if (client_socket != -1) {
+        close(client_socket);
+    }
+
+    if (listen_socket != -1) {
+        shutdown(listen_socket, 0);
+        close(listen_socket);
+        IPERF_LOGI(TAG, "TCP Socket server is closed.");
+    }
+    s_iperf_ctrl.finish = true;
+    return ret;
+}
+
+static void IRAM_ATTR iperf_tcp_dual_server_task(void *pvParameters)
+{
+    int listen_socket = -1;
+    int client_socket = -1;
+    int opt = 1;
+    int err = 0;
+    iperf_err_t ret = IPERF_OK;
+    struct sockaddr_in remote_addr;
+    struct timeval timeout = { 0 };
+    socklen_t addr_len = sizeof(struct sockaddr);
+    struct sockaddr_storage listen_addr = { 0 };
+    struct sockaddr_in listen_addr4 = { 0 };
+
+    (void)ret;
+    if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
+        listen_addr4.sin_family = AF_INET;
+        listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
+        listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
+
+        listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+        IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+
+        setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+        IPERF_LOGI(TAG, "Socket created");
+
+        err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(listen_addr4));
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET);
+
+        err = listen(listen_socket, 5);
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
+        memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
+    }
+
+    client_socket = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
+    IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to accept connection: errno %d", errno);
+    IPERF_LOGI(TAG, "accept: %s,%d\n", inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
+
+    timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
+    setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+    socket_recv_dual(client_socket, listen_addr, IPERF_TRANS_TYPE_TCP);
+exit:
+    if (client_socket != -1) {
+        close(client_socket);
+    }
+
+    if (listen_socket != -1) {
+        shutdown(listen_socket, 0);
+        close(listen_socket);
+        IPERF_LOGI(TAG, "TCP Socket server is closed.");
+    }
+
+    vTaskDelete(NULL);
+}
+
+static iperf_err_t iperf_run_tcp_client(void)
+{
+    int client_socket = -1;
+    int err = 0;
+    iperf_err_t ret = IPERF_OK;
+    struct sockaddr_storage dest_addr = { 0 };
+#if IPERF_V6
+    struct sockaddr_in6 dest_addr6 = { 0 };
+#endif
+    struct sockaddr_in dest_addr4 = { 0 };
+    int opt = s_iperf_ctrl.cfg.tos;
+
+    IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
+
+    if (iperf_is_tcp_dual_client()) {
+        xTaskCreate(iperf_tcp_dual_server_task, "dual_rx", IPERF_TRAFFIC_TASK_STACK, NULL, s_iperf_ctrl.cfg.traffic_task_priority, NULL);
+        vTaskDelay(pdMS_TO_TICKS(100));
+    }
+#if IPERF_V6
+    if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
+        client_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
+        IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+        setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
+
+        inet6_aton(s_iperf_ctrl.cfg.destination_ip6, &dest_addr6.sin6_addr);
+        dest_addr6.sin6_family = AF_INET6;
+        dest_addr6.sin6_port = htons(s_iperf_ctrl.cfg.dport);
+
+        err = connect(client_socket, (struct sockaddr *)&dest_addr6, sizeof(struct sockaddr_in6));
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to connect: errno %d", errno);
+        IPERF_LOGI(TAG, "Successfully connected");
+        memcpy(&dest_addr, &dest_addr6, sizeof(dest_addr6));
+    } else
+#endif
+        if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
+        client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+        IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+        setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
+
+        dest_addr4.sin_family = AF_INET;
+        dest_addr4.sin_port = htons(s_iperf_ctrl.cfg.dport);
+        dest_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.destination_ip4;
+        err = connect(client_socket, (struct sockaddr *)&dest_addr4, sizeof(struct sockaddr_in));
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to connect: errno %d", errno);
+        IPERF_LOGI(TAG, "Successfully connected");
+        memcpy(&dest_addr, &dest_addr4, sizeof(dest_addr4));
+    }
+
+    socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_TCP, s_iperf_ctrl.cfg.bw_lim);
+exit:
+    if (client_socket != -1) {
+        shutdown(client_socket, 0);
+        close(client_socket);
+        IPERF_LOGI(TAG, "TCP Socket client is closed.");
+    }
+    s_iperf_ctrl.finish = true;
+    return ret;
+}
+
+static iperf_err_t IRAM_ATTR iperf_run_udp_server(void)
+{
+    int listen_socket = -1;
+    int opt = 1;
+    int err = 0;
+    iperf_err_t ret = IPERF_OK;
+    struct timeval timeout = { 0 };
+    struct sockaddr_storage listen_addr = { 0 };
+#if IPERF_V6
+    struct sockaddr_in6 listen_addr6 = { 0 };
+#endif
+    struct sockaddr_in listen_addr4 = { 0 };
+
+    IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
+
+#if IPERF_V6
+    if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
+        // The UDP server listen at the address "::", which means all addresses can be listened to.
+        inet6_aton("::", &listen_addr6.sin6_addr);
+        listen_addr6.sin6_family = AF_INET6;
+        listen_addr6.sin6_port = htons(s_iperf_ctrl.cfg.sport);
+
+        listen_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+        IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+        IPERF_LOGI(TAG, "Socket created");
+
+        setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+        err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(struct sockaddr_in6));
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d", errno);
+        IPERF_LOGI(TAG, "Socket bound, port %d", listen_addr6.sin6_port);
+
+        memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
+    } else
+#endif
+        if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
+        listen_addr4.sin_family = AF_INET;
+        listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
+        listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
+
+        listen_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+        IPERF_GOTO_ON_FALSE((listen_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+        IPERF_LOGI(TAG, "Socket created");
+
+        setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+        err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(struct sockaddr_in));
+        IPERF_GOTO_ON_FALSE((err == 0), IPERF_FAIL, exit, TAG, "Socket unable to bind: errno %d", errno);
+        IPERF_LOGI(TAG, "Socket bound, port %d", listen_addr4.sin_port);
+        memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
+    }
+
+    timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
+    setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+    socket_recv(listen_socket, listen_addr, IPERF_TRANS_TYPE_UDP);
+exit:
+    if (listen_socket != -1) {
+        shutdown(listen_socket, 0);
+        close(listen_socket);
+    }
+    IPERF_LOGI(TAG, "Udp socket server is closed.");
+    s_iperf_ctrl.finish = true;
+    return ret;
+}
+
+static iperf_err_t iperf_run_udp_client(void)
+{
+    int client_socket = -1;
+    int opt = 1;
+    iperf_err_t ret = IPERF_OK;
+    struct sockaddr_storage dest_addr = { 0 };
+#if IPERF_V6
+    struct sockaddr_in6 dest_addr6 = { 0 };
+#endif
+    struct sockaddr_in dest_addr4 = { 0 };
+
+    IPERF_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), IPERF_FAIL, exit, TAG, "Ivalid AF types");
+
+#if IPERF_V6
+    if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
+        inet6_aton(s_iperf_ctrl.cfg.destination_ip6, &dest_addr6.sin6_addr);
+        dest_addr6.sin6_family = AF_INET6;
+        dest_addr6.sin6_port = htons(s_iperf_ctrl.cfg.dport);
+
+        client_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
+        IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+        IPERF_LOGI(TAG, "Socket created, sending to %s:%d", s_iperf_ctrl.cfg.destination_ip6, s_iperf_ctrl.cfg.dport);
+
+        setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+        opt = s_iperf_ctrl.cfg.tos;
+        setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
+        memcpy(&dest_addr, &dest_addr6, sizeof(dest_addr6));
+    } else
+#endif
+        if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
+        dest_addr4.sin_family = AF_INET;
+        dest_addr4.sin_port = htons(s_iperf_ctrl.cfg.dport);
+        dest_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.destination_ip4;
+
+        client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+        IPERF_GOTO_ON_FALSE((client_socket >= 0), IPERF_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
+        IPERF_LOGI(TAG, "Socket created, sending to %d:%d", s_iperf_ctrl.cfg.destination_ip4, s_iperf_ctrl.cfg.dport);
+
+        setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+        opt = s_iperf_ctrl.cfg.tos;
+        setsockopt(client_socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
+        memcpy(&dest_addr, &dest_addr4, sizeof(dest_addr4));
+    }
+
+    socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_UDP, s_iperf_ctrl.cfg.bw_lim);
+exit:
+    if (client_socket != -1) {
+        shutdown(client_socket, 0);
+        close(client_socket);
+    }
+    s_iperf_ctrl.finish = true;
+    IPERF_LOGI(TAG, "UDP Socket client is closed");
+    return ret;
+}
+
+static void iperf_task_traffic(void *arg)
+{
+    if (iperf_is_udp_client()) {
+        iperf_run_udp_client();
+    } else if (iperf_is_udp_server()) {
+        iperf_run_udp_server();
+    } else if (iperf_is_tcp_client()) {
+        iperf_run_tcp_client();
+    } else {
+        iperf_run_tcp_server();
+    }
+
+    if (s_iperf_ctrl.buffer) {
+        vPortFree(s_iperf_ctrl.buffer);
+        s_iperf_ctrl.buffer = NULL;
+    }
+    printf("iperf exit\r\n");
+    s_iperf_is_running = false;
+    vTaskDelete(NULL);
+}
+
+static uint32_t iperf_get_buffer_len(void)
+{
+    if (iperf_is_udp_client()) {
+        return (s_iperf_ctrl.cfg.len_buf == 0 ? IPERF_UDP_TX_LEN : s_iperf_ctrl.cfg.len_buf);
+    } else if (iperf_is_udp_server()) {
+        return IPERF_UDP_RX_LEN;
+    } else if (iperf_is_tcp_client()) {
+        return (s_iperf_ctrl.cfg.len_buf == 0 ? IPERF_TCP_TX_LEN : s_iperf_ctrl.cfg.len_buf);
+    } else {
+        return (s_iperf_ctrl.cfg.len_buf == 0 ? IPERF_TCP_RX_LEN : s_iperf_ctrl.cfg.len_buf);
+    }
+    return 0;
+}
+
+static void net_iperf_print_header(iperf_cfg_t *cfg)
+{
+    printf("------------------------------------------------------------\r\n");
+    if (iperf_is_udp_server()) {
+        printf("Server listening on UDP port %d\r\n",
+               cfg->sport);
+    } else if (iperf_is_tcp_server()) {
+        printf("Server listening on TCP port %d\r\n",
+               cfg->sport);
+    } else if (iperf_is_udp_client()) {
+        printf("Client connecting to %s, UDP port %d\r\n"
+               "Sending %d byte datagrams\r\n",
+               inet_ntoa(cfg->destination_ip4),
+               cfg->dport, cfg->num_bytes);
+    } else if (iperf_is_tcp_client()) {
+        printf("Client connecting to %s, TCP port %d\r\n",
+               inet_ntoa(cfg->destination_ip4), cfg->dport);
+    }
+    printf("------------------------------------------------------------\r\n");
+}
+
+iperf_err_t iperf_start(iperf_cfg_t *cfg)
+{
+    BaseType_t ret;
+
+    if (!cfg) {
+        return IPERF_FAIL;
+    }
+
+    if (s_iperf_is_running) {
+        IPERF_LOGW(TAG, "iperf is running");
+        printf("iperf is running\r\n");
+        return IPERF_FAIL;
+    }
+
+    memset(&s_iperf_ctrl, 0, sizeof(s_iperf_ctrl));
+    memcpy(&s_iperf_ctrl.cfg, cfg, sizeof(*cfg));
+    s_iperf_is_running = true;
+    s_iperf_ctrl.finish = false;
+    s_iperf_ctrl.buffer_len = iperf_get_buffer_len();
+    s_iperf_ctrl.buffer = (uint8_t *)pvPortMalloc(s_iperf_ctrl.buffer_len);
+    if (!s_iperf_ctrl.buffer) {
+        IPERF_LOGE(TAG, "create buffer: not enough memory");
+        return IPERF_FAIL;
+    }
+    memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len);
+    ret = xTaskCreatePinnedToCore(iperf_task_traffic, IPERF_TRAFFIC_TASK_NAME, IPERF_TRAFFIC_TASK_STACK, NULL, s_iperf_ctrl.cfg.traffic_task_priority, NULL, portNUM_PROCESSORS - 1);
+    if (ret != pdPASS) {
+        IPERF_LOGE(TAG, "create task %s failed", IPERF_TRAFFIC_TASK_NAME);
+        vPortFree(s_iperf_ctrl.buffer);
+        s_iperf_ctrl.buffer = NULL;
+        return IPERF_FAIL;
+    }
+    net_iperf_print_header(cfg);
+    return IPERF_OK;
+}
+
+iperf_err_t iperf_stop(void)
+{
+    if (s_iperf_is_running) {
+        s_iperf_ctrl.finish = true;
+    }
+
+    return IPERF_OK;
+}

+ 82 - 0
tests/hpmicro/src/iperf/iperf.h

@@ -0,0 +1,82 @@
+/* Iperf Example - iperf declaration
+
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+
+#ifndef __IPERF_H_
+#define __IPERF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IPERF_IP_TYPE_IPV4          0
+#define IPERF_IP_TYPE_IPV6          1
+#define IPERF_TRANS_TYPE_TCP        0
+#define IPERF_TRANS_TYPE_UDP        1
+
+#define IPERF_FLAG_SET(cfg, flag)   ((cfg) |= (flag))
+#define IPERF_FLAG_CLR(cfg, flag)   ((cfg) &= (~(flag)))
+
+#define IPERF_FLAG_CLIENT           (1)
+#define IPERF_FLAG_SERVER           (1 << 1)
+#define IPERF_FLAG_TCP              (1 << 2)
+#define IPERF_FLAG_UDP              (1 << 3)
+#define IPERF_FLAG_DUAL             (1 << 4)
+
+#define IPERF_DEFAULT_PORT          5001
+#define IPERF_DEFAULT_INTERVAL      1
+#define IPERF_DEFAULT_TIME          10
+#define IPERF_DEFAULT_NO_BW_LIMIT   -1
+
+#define IPERF_TRAFFIC_TASK_NAME     "iperf_traffic"
+#define IPERF_TRAFFIC_TASK_PRIORITY 10
+#define IPERF_TRAFFIC_TASK_STACK    2048
+#define IPERF_REPORT_TASK_NAME      "iperf_report"
+#define IPERF_REPORT_TASK_STACK     2048
+
+#define IPERF_UDP_TX_LEN            (1470)
+#define IPERF_UDP_RX_LEN            (1470)
+#define IPERF_TCP_TX_LEN            (8 << 10)
+#define IPERF_TCP_RX_LEN            (8 << 10)
+
+#define IPERF_MAX_DELAY             64
+
+#define IPERF_SOCKET_RX_TIMEOUT     10
+#define IPERF_SOCKET_ACCEPT_TIMEOUT 5
+
+typedef struct {
+    uint32_t flag;
+    union {
+        uint32_t destination_ip4;
+        char *destination_ip6;
+    };
+    union {
+        uint32_t source_ip4;
+        char *source_ip6;
+    };
+    uint8_t type;
+    uint16_t dport;
+    uint16_t sport;
+    uint32_t interval;
+    uint32_t time;
+    uint16_t len_buf;
+    int32_t bw_lim;
+    uint8_t tos;
+    uint8_t traffic_task_priority;
+    uint32_t num_bytes;
+} iperf_cfg_t;
+
+int iperf_start(iperf_cfg_t *cfg);
+
+int iperf_stop(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 115 - 0
tests/hpmicro/src/iperf/iperf_cli.c

@@ -0,0 +1,115 @@
+#include <string.h>
+#include <stdint.h>
+#include <utils_getopt.h>
+#include <iperf.h>
+#include <lwip/ip_addr.h>
+
+#define NL "\r\n"
+
+static void iperf_cmd(int argc, char **argv)
+{
+    int opt;
+    getopt_env_t opt_env;
+    int o_c = 0, o_s = 0, o_u = 0, o_a = 0;
+    int o_p = IPERF_DEFAULT_PORT, o_l = 0, o_i = IPERF_DEFAULT_INTERVAL, o_t = IPERF_DEFAULT_TIME, o_b = IPERF_DEFAULT_NO_BW_LIMIT, o_S = 0, o_n = 0;
+    int o_d = 0;
+    int o_P = IPERF_TRAFFIC_TASK_PRIORITY;
+    uint32_t dst_addr = 0;
+
+    iperf_cfg_t cfg;
+
+    utils_getopt_init(&opt_env, 0);
+    while ((opt = utils_getopt(&opt_env, argc, argv, ":c:sup:l:i:t:b:S:n:P:ad")) != -1) {
+        #define ARG_READ(v) v = atoi(opt_env.optarg)
+        switch (opt) {
+        case 'c':
+            ++o_c;
+            dst_addr = ipaddr_addr(opt_env.optarg);
+            break;
+        case 's': ++o_s; break;
+        case 'u': ++o_u; break;
+        case 'p': ARG_READ(o_p); break;
+        case 'l': ARG_READ(o_l); break;
+        case 'i': ARG_READ(o_i); break;
+        case 't': ARG_READ(o_t); break;
+        case 'b': ARG_READ(o_b); break;
+        case 'S': ARG_READ(o_S); break;
+        case 'n': ARG_READ(o_n); break;
+        case 'P': ARG_READ(o_P); break;
+        case 'd': ++o_d; break;
+        case 'a': ++o_a; break;
+        }
+        #undef ARG_READ
+    }
+
+    memset(&cfg, 0, sizeof(cfg));
+    cfg.type = IPERF_IP_TYPE_IPV4;
+
+    if (o_a) {
+        iperf_stop();
+        return;
+    }
+    if (!((o_c && !o_s) || (!o_c && o_s))) {
+        printf("client/server required" NL);
+        return;
+    }
+    if (o_c) {
+        cfg.destination_ip4 = dst_addr;
+        cfg.flag |= IPERF_FLAG_CLIENT;
+    } else {
+        cfg.flag |= IPERF_FLAG_SERVER;
+    }
+    if (o_u) {
+        cfg.flag |= IPERF_FLAG_UDP;
+    } else {
+        cfg.flag |= IPERF_FLAG_TCP;
+    }
+
+    if (o_c && !o_u && o_d) {
+        cfg.flag |= IPERF_FLAG_DUAL;
+    }
+
+    cfg.len_buf = o_l;
+    cfg.sport = o_p;
+    cfg.dport = o_p;
+    cfg.interval = o_i;
+    cfg.time = o_t;
+    if (cfg.time < cfg.interval) {
+        cfg.time = cfg.interval;
+    }
+    cfg.bw_lim = o_b;
+    cfg.tos = o_S;
+    cfg.num_bytes = o_n * 1000 * 1000;
+    if (cfg.bw_lim <= 0) {
+        cfg.bw_lim = IPERF_DEFAULT_NO_BW_LIMIT;
+    }
+    cfg.traffic_task_priority = o_P;
+
+    iperf_start(&cfg);
+}
+
+#include <shell.h>
+#define ML(s) s NL
+#define IPERF_USAGE \
+    ML("iperf") \
+    ML(" -c server_addr: run in client mode") \
+    ML(" -s: run in server mode") \
+    ML(" -u: UDP") \
+    ML(" -p port: specify port") \
+    ML(" -l length: set read/write buffer size") \
+    ML(" -i interval: seconds between bandwidth reports") \
+    ML(" -t time: time in seconds to run") \
+    ML(" -b bandwith: bandwidth to send in Mbps") \
+    ML(" -S tos: TOS") \
+    ML(" -n MB: number of MB to send/recv") \
+    ML(" -P priority: traffic task priority") \
+    ML(" -d: dual mode") \
+    ML(" -a: abort running iperf") \
+
+#if 0
+const static struct cli_command iperf_cmds[] STATIC_CLI_CMD_ATTRIBUTE = {
+    {"iperf", IPERF_USAGE, iperf_cmd},
+};
+#endif
+CSH_CMD_EXPORT_ALIAS(iperf_cmd, iperf, iperf command);
+

+ 377 - 0
tests/hpmicro/src/iperf/utils_getopt.c

@@ -0,0 +1,377 @@
+/*
+ * This file is derived from musl v1.2.0.
+ * Modifications are applied.
+ * Copyright (C) Bouffalo Lab 2016-2020
+ */
+
+/*
+ * Copyright © 2005-2020 Rich Felker, et al.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <utils_getopt.h>
+
+int utils_getopt_init(getopt_env_t *env, int opterr)
+{
+    if (!env) {
+        return -1;
+    }
+    env->optarg = NULL;
+    env->optind = 1;
+    env->opterr = opterr;
+    env->optopt = 0;
+    env->__optpos = 0;
+    return 0;
+}
+
+#define NEWLINE "\r\n"
+
+int utils_getopt(getopt_env_t *env, int argc, char *const argv[], const char *optstring)
+{
+    int i;
+    char c, d;
+    char *optchar;
+
+    if (!env) {
+        return -1;
+    }
+
+    if (env->optind >= argc || !argv[env->optind])
+        return -1;
+
+    if (argv[env->optind][0] != '-') {
+        if (optstring[0] == '-') {
+            env->optarg = argv[env->optind++];
+            return 1;
+        }
+        return -1;
+    }
+
+    if (!argv[env->optind][1])
+        return -1;
+
+    if (argv[env->optind][1] == '-' && !argv[env->optind][2])
+        return env->optind++, -1;
+
+    if (!env->__optpos)
+        env->__optpos++;
+    c = argv[env->optind][env->__optpos];
+    optchar = argv[env->optind] + env->__optpos;
+    env->__optpos += !!c;
+
+    if (!argv[env->optind][env->__optpos]) {
+        env->optind++;
+        env->__optpos = 0;
+    }
+
+    if (optstring[0] == '-' || optstring[0] == '+')
+        optstring++;
+
+    i = 0;
+    do
+        d = optstring[i++];
+    while (d && d != c);
+
+    if (d != c || c == ':') {
+        env->optopt = c;
+        if (optstring[0] != ':' && env->opterr)
+            printf("%s: unrecognized option: %c" NEWLINE, argv[0], *optchar);
+        return '?';
+    }
+    if (optstring[i] == ':') {
+        env->optarg = 0;
+        if (optstring[i + 1] != ':' || env->__optpos) {
+            env->optarg = argv[env->optind++] + env->__optpos;
+            env->__optpos = 0;
+        }
+        if (env->optind > argc) {
+            env->optopt = c;
+            if (optstring[0] == ':')
+                return ':';
+            if (env->opterr) {
+                printf("%s: option requires an argument: %c" NEWLINE, argv[0], *optchar);
+            }
+            return '?';
+        }
+    }
+    return c;
+}
+
+static int params_filter(char **params, uint32_t *r)
+{
+    char *p;
+    uint32_t result = 0;
+    uint8_t base = 0;
+
+    p = *params;
+
+    if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X'))) {
+        p = p + 2;
+        base = 16;
+
+    } else {
+        base = 10;
+    }
+
+    while (*p) {
+        result *= base;
+        if (*p >= '0' && *p <= '9')
+            result += *p - '0';
+        else if (base == 10)
+            return -1;
+
+        if (base == 16) {
+            if (*p >= 'a' && *p <= 'f')
+                result += *p - 'a' + 10;
+            else if (*p >= 'A' && *p <= 'F')
+                result += *p - 'A' + 10;
+        }
+        p++;
+    }
+
+    *r = result;
+    return 0;
+}
+
+void get_bytearray_from_string(char **params, uint8_t *result, int array_size)
+{
+    int i = 0;
+    char rand[3];
+
+    for (i = 0; i < array_size; i++) {
+        memcpy(rand, *params, 2);
+        rand[2] = '\0';
+        result[i] = strtol(rand, NULL, 16);
+        *params = *params + 2;
+    }
+}
+
+void get_uint8_from_string(char **params, uint8_t *result)
+{
+    uint32_t p = 0;
+    int state = 0;
+
+    state = params_filter(params, &p);
+    if (!state) {
+        *result = p & 0xff;
+    } else
+        *result = 0;
+}
+
+void get_uint16_from_string(char **params, uint16_t *result)
+{
+    uint32_t p = 0;
+    int state = 0;
+
+    state = params_filter(params, &p);
+    if (!state) {
+        *result = p & 0xffff;
+    } else
+        *result = 0;
+}
+
+void get_uint32_from_string(char **params, uint32_t *result)
+{
+    uint32_t p = 0;
+    int state = 0;
+
+    state = params_filter(params, &p);
+    if (!state) {
+        *result = p;
+    } else
+        *result = 0;
+}
+
+void utils_parse_number(const char *str, char sep, uint8_t *buf, int buflen, int base)
+{
+    int i;
+    for (i = 0; i < buflen; i++) {
+        buf[i] = (uint8_t)strtol(str, NULL, base);
+        str = strchr(str, sep);
+        if (str == NULL || *str == '\0') {
+            break;
+        }
+        str++;
+    }
+}
+
+void utils_parse_number_adv(const char *str, char sep, uint8_t *buf, int buflen, int base, int *count)
+{
+    int i;
+
+    for (i = 0; i < buflen; i++) {
+        buf[i] = (uint8_t)strtol(str, NULL, base);
+        str = strchr(str, sep);
+        if (str == NULL || *str == '\0') {
+            break;
+        }
+        str++;
+    }
+    *count = (i + 1);
+}
+
+unsigned long long convert_arrayToU64(uint8_t *inputArray)
+{
+    unsigned long long result = 0;
+    for (uint8_t i = 0; i < 8; i++) {
+        result <<= 8;
+        result |= (unsigned long long)inputArray[7 - i];
+    }
+
+    return result;
+}
+
+void convert_u64ToArray(unsigned long long inputU64, uint8_t result[8])
+{
+    for (int i = 0; i < 8; i++) {
+        result[i] = inputU64 >> (i * 8);
+    }
+}
+
+void utils_memdrain8(void *src, size_t len)
+{
+    volatile uint8_t *s = (uint8_t *)src;
+    uint8_t tmp;
+
+    while (len--) {
+        tmp = *s++;
+    }
+
+    (void)tmp;
+}
+
+void utils_memdrain16(void *src, size_t len)
+{
+    volatile uint16_t *s = (uint16_t *)src;
+    uint16_t tmp;
+
+    len >>= 1; //convert to half words
+
+    while (len--) {
+        tmp = *s++;
+    }
+
+    (void)tmp;
+}
+
+void utils_memdrain32(void *src, size_t len)
+{
+    volatile uint32_t *s = (uint32_t *)src;
+    uint32_t tmp;
+
+    len >>= 2; //convert to words
+
+    while (len--) {
+        tmp = *s++;
+    }
+
+    (void)tmp;
+}
+
+void utils_memdrain64(void *src, size_t len)
+{
+    volatile uint64_t *s = (uint64_t *)src;
+    uint64_t tmp;
+
+    len >>= 3; //convert to two words
+
+    while (len--) {
+        tmp = *s++;
+    }
+
+    (void)tmp;
+}
+
+void *utils_memdrain8_with_check(void *src, size_t len, uint8_t seq)
+{
+    volatile uint8_t *s = (uint8_t *)src;
+    uint8_t tmp;
+
+    (void)tmp;
+
+    while (len--) {
+        tmp = *s++;
+        if ((seq++) != tmp) {
+            return (uint8_t *)s - 1;
+        }
+    }
+
+    return NULL;
+}
+
+void *utils_memdrain16_with_check(void *src, size_t len, uint16_t seq)
+{
+    volatile uint16_t *s = (uint16_t *)src;
+    uint16_t tmp;
+    (void)tmp;
+
+    len >>= 1; //convert to half words
+
+    while (len--) {
+        tmp = *s++;
+        if ((seq++) != tmp) {
+            return (uint16_t *)s - 1;
+        }
+    }
+
+    return NULL;
+}
+
+void *utils_memdrain32_with_check(void *src, size_t len, uint32_t seq)
+{
+    volatile uint32_t *s = (uint32_t *)src;
+    uint32_t tmp;
+    (void)tmp;
+
+    len >>= 2; //convert to words
+
+    while (len--) {
+        tmp = *s++;
+        if ((seq++) != tmp) {
+            return (uint32_t *)s - 1;
+        }
+    }
+
+    return NULL;
+}
+
+void *utils_memdrain64_with_check(void *src, size_t len, uint64_t seq)
+{
+    volatile uint64_t *s = (uint64_t *)src;
+    uint64_t tmp;
+    (void)tmp;
+
+    len >>= 3; //convert to two words
+
+    while (len--) {
+        tmp = *s++;
+        if ((seq++) != tmp) {
+            return (uint64_t *)s - 1;
+        }
+    }
+
+    return NULL;
+}

+ 107 - 0
tests/hpmicro/src/iperf/utils_getopt.h

@@ -0,0 +1,107 @@
+#ifndef __GETOPT_H__
+#define __GETOPT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Parameters needed to parse the command line
+ *
+ */
+typedef struct getopt_env {
+    char *optarg;    /*!< if the option accepts parameters, then optarg point to the option parameter*/
+    int optind;      /*!< current index of argv*/
+    int opterr;      /*!< non-zero enable error message output, while 0,no error message output*/
+    int optopt;      /*!< contain unrecognized option character*/
+    int __optpos;
+} getopt_env_t;
+
+/**
+ * @brief Initialize struct getopt_env
+ *
+ * @param env pointer to struct getopt_env
+ * @param opterr set error message output method
+ *
+ * @return
+ *     -  0: success
+ *     - -1: fail
+ */
+int utils_getopt_init(getopt_env_t *env, int opterr);
+
+/**
+ * @brief Parses the command-line arguments
+ *
+ * @param env pointer to struct getopt_env
+ * @param argc the argument count
+ * @param argv the argument array
+ *
+ * @return
+ *     -  option character : an option was successfully found
+ *     - -1 : all command-line options have been parsed
+ *     - '?' : option character was not in optstring
+ *     - ':' or '?' : If utils_getopt() encounters an option with a missing argument, then the return value depends on the first character in optstring: if it is ':', then ':' is returned; otherwise '?' is returned
+ *
+ * @note Example
+ * @code
+ *
+ * #include <utils_getopt.h>
+ * #include <stdio.h>
+ *
+ * void cmd(char *buf, int len, int argc, char **argv)
+ * {
+ *     int opt;
+       getopt_env_t getopt_env;
+       utils_getopt_init(&getopt_env, 0);
+ *     //put ':' in the starting of the string so that program can distinguish between '?' and ':'
+ *     while ((opt = utils_getopt(&getopt_env, argc, argv, ":if:lr")) != -1) {
+ *         switch(opt)
+ *         {
+ *             case 'i':
+ *             case 'l':
+ *             case 'r':
+ *                 printf("option: %c\r\n", opt);
+ *                 break;
+ *             case 'f':
+ *                 printf("filename: %s\r\n", getopt_env.optarg);
+ *                 break;
+ *             case ':':
+                   printf("%s: %c requires an argument\r\n", *argv, getopt_env.optopt);
+ *                 break;
+ *             case '?':
+ *                 printf("unknow option: %c\r\n", getopt_env.optopt);
+ *                 break;
+ *          }
+ *      }
+ *      //optind is for the extra arguments which are not parsed
+ *      for(; getopt_env.optind < argc; getopt_env.optind++){
+ *          printf("extra arguments: %s\r\n", argv[getopt_env.optind]);
+ *      }
+ *
+ *  }
+ *  @endcode
+ */
+int utils_getopt(getopt_env_t *env, int argc, char *const argv[], const char *optstring);
+
+void get_bytearray_from_string(char **params, uint8_t *result, int array_size);
+void get_uint8_from_string(char **params, uint8_t *result);
+void get_uint16_from_string(char **params, uint16_t *result);
+void get_uint32_from_string(char **params, uint32_t *result);
+void utils_parse_number(const char *str, char sep, uint8_t *buf, int buflen, int base);
+void utils_parse_number_adv(const char *str, char sep, uint8_t *buf, int buflen, int base, int *count);
+unsigned long long convert_arrayToU64(uint8_t *inputArray);
+void convert_u64ToArray(unsigned long long inputU64, uint8_t result[8]);
+void utils_memdrain8(void *src, size_t len);
+void utils_memdrain16(void *src, size_t len);
+void utils_memdrain32(void *src, size_t len);
+void utils_memdrain64(void *src, size_t len);
+void *utils_memdrain8_with_check(void *src, size_t len, uint8_t seq);
+void *utils_memdrain16_with_check(void *src, size_t len, uint16_t seq);
+void *utils_memdrain32_with_check(void *src, size_t len, uint32_t seq);
+void *utils_memdrain64_with_check(void *src, size_t len, uint64_t seq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GETOPT_H__ */

+ 102 - 2
tests/hpmicro/src/main.c

@@ -13,9 +13,14 @@
 #include <stdio.h>
 #include "board.h"
 #include "hpm_clock_drv.h"
+#include "hpm_l1c_drv.h"
 #include "shell.h"
 #include "usbh_core.h"
 #include "lwip/tcpip.h"
+#ifdef CONFIG_USB_EHCI_ISO
+#include "usbh_uvc_stream.h"
+#include "usbh_uac_stream.h"
+#endif
 
 SDK_DECLARE_EXT_ISR_M(BOARD_CONSOLE_UART_IRQ, shell_uart_isr)
 
@@ -36,7 +41,11 @@ int main(void)
     tcpip_init(NULL, NULL);
 
     printf("Start usb host task...\r\n");
+#ifdef CONFIG_USB_EHCI_ISO
+    extern void uvc2lcd_init(void);
 
+    uvc2lcd_init();
+#endif
     usbh_initialize(0, CONFIG_HPM_USBH_BASE, NULL);
 
     if (pdPASS != xTaskCreate(task_start, "task_start", 1024U, NULL, task_start_PRIORITY, NULL)) {
@@ -100,5 +109,96 @@ static void task_start(void *param)
     vTaskDelete(NULL);
 }
 
-extern int lsusb(int argc, char **argv);
-CSH_CMD_EXPORT(lsusb, );
+CSH_CMD_EXPORT(lsusb, );
+
+#ifdef CONFIG_USB_EHCI_ISO
+// clang-format off
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t src_buffer[1024 * 10];
+ATTR_PLACE_AT_WITH_ALIGNMENT(".framebuffer", 64) uint8_t dst_buffer[1024 * 10];
+// clang-format on
+
+void usb_dma_test()
+{
+    usbh_video_dma_init();
+    for (size_t i = 0; i < 10 * 1024; i++) {
+        src_buffer[i] = i & 0xff;
+    }
+    memset(dst_buffer, 0, 10 * 1024);
+
+    for (uint8_t i = 0; i < 10; i++) {
+        usbh_video_dma_lli_fill(i, (uint32_t)src_buffer + i * 1024, (uint32_t)dst_buffer + i * 1024, 1024);
+    }
+    volatile uint64_t start_tick = hpm_csr_get_core_mcycle();
+    usbh_video_dma_start();
+
+    while (usbh_video_dma_isbusy()) {
+    }
+    volatile uint64_t end_tick = hpm_csr_get_core_mcycle();
+
+    double consumed_seconds = (end_tick - start_tick) * 1.0l / (clock_get_frequency(clock_cpu0) / 1000000);
+    printf("dma done:%.2f us\n", consumed_seconds);
+    l1c_dc_invalidate((uint32_t)dst_buffer, 10 * 1024);
+    for (size_t i = 0; i < 10 * 1024; i++) {
+        if (dst_buffer[i] != src_buffer[i]) {
+            printf("error:%d\n", i);
+            break;
+        }
+    }
+}
+
+int dma_test(int argc, char **argv)
+{
+    usb_dma_test();
+    return 0;
+}
+CSH_CMD_EXPORT(dma_test, );
+
+int usbh_uvc_start(int argc, char **argv)
+{
+    uint8_t type;
+
+    if (argc < 2) {
+        USB_LOG_ERR("please input correct command: usbh_uvc_start type\r\n");
+        USB_LOG_ERR("type 0:yuyv, type 1:mjpeg\r\n");
+        return -1;
+    }
+
+    type = atoi(argv[1]);
+    usbh_video_stream_start(640, 480, type);
+    return 0;
+}
+
+CSH_CMD_EXPORT(usbh_uvc_start, usbh_uvc_start);
+
+int usbh_uvc_stop(int argc, char **argv)
+{
+    usbh_video_stream_stop();
+    return 0;
+}
+
+CSH_CMD_EXPORT(usbh_uvc_stop, usbh_uvc_stop);
+
+int usbh_uac_start(int argc, char **argv)
+{
+    uint32_t freq;
+
+    if (argc < 2) {
+        USB_LOG_ERR("please input correct command: usbh_uac_start freq\r\n");
+        return -1;
+    }
+
+    freq = atoi(argv[1]);
+    usbh_audio_mic_stream_start(freq);
+    return 0;
+}
+
+CSH_CMD_EXPORT(usbh_uac_start, usbh_uac_start);
+
+int usbh_uac_stop(int argc, char **argv)
+{
+    usbh_audio_mic_stream_stop();
+    return 0;
+}
+
+CSH_CMD_EXPORT(usbh_uac_stop, usbh_uac_stop);
+#endif

+ 257 - 0
tests/hpmicro/src/ping.c

@@ -0,0 +1,257 @@
+/*
+ * netutils: ping implementation
+ */
+
+#include <FreeRTOS.h>
+#include <task.h>
+
+#include <lwip/opt.h>
+#include <lwip/init.h>
+#include <lwip/mem.h>
+#include <lwip/icmp.h>
+#include <lwip/netif.h>
+#include <lwip/sys.h>
+#include <lwip/inet.h>
+#include <lwip/inet_chksum.h>
+#include <lwip/ip.h>
+#include <lwip/netdb.h>
+#include <lwip/sockets.h>
+
+/**
+ * PING_DEBUG: Enable debugging for PING.
+ */
+#ifndef PING_DEBUG
+#define PING_DEBUG LWIP_DBG_ON
+#endif
+
+/** ping receive timeout - in milliseconds */
+#define PING_RCV_TIMEO (2000 * portTICK_PERIOD_MS)
+/** ping delay - in milliseconds */
+#define PING_DELAY     (1000 * portTICK_PERIOD_MS)
+
+/** ping identifier - must fit on a u16_t */
+#ifndef PING_ID
+#define PING_ID 0xAFAF
+#endif
+
+/** ping additional data size to include in the packet */
+#ifndef PING_DATA_SIZE
+#define PING_DATA_SIZE 32
+#endif
+
+/* ping variables */
+static u16_t ping_seq_num;
+struct _ip_addr {
+    uint8_t addr0, addr1, addr2, addr3;
+};
+
+/** Prepare a echo ICMP request */
+static void ping_prepare_echo(struct icmp_echo_hdr *iecho, u16_t len)
+{
+    size_t i;
+    size_t data_len = len - sizeof(struct icmp_echo_hdr);
+
+    ICMPH_TYPE_SET(iecho, ICMP_ECHO);
+    ICMPH_CODE_SET(iecho, 0);
+    iecho->chksum = 0;
+    iecho->id = PING_ID;
+    iecho->seqno = htons(++ping_seq_num);
+
+    /* fill the additional data buffer with some data */
+    for (i = 0; i < data_len; i++) {
+        ((char *)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
+    }
+
+    iecho->chksum = inet_chksum(iecho, len);
+}
+
+/* Ping using the socket ip */
+err_t lwip_ping_send(int s, ip_addr_t *addr, int size)
+{
+    int err;
+    struct icmp_echo_hdr *iecho;
+    struct sockaddr_in to;
+    int ping_size = sizeof(struct icmp_echo_hdr) + size;
+    LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
+
+    iecho = mem_malloc(ping_size);
+    if (iecho == NULL) {
+        return ERR_MEM;
+    }
+
+    ping_prepare_echo(iecho, (u16_t)ping_size);
+
+    to.sin_len = sizeof(to);
+    to.sin_family = AF_INET;
+#if LWIP_IPV4 && LWIP_IPV6
+    to.sin_addr.s_addr = addr->u_addr.ip4.addr;
+#elif LWIP_IPV4
+    to.sin_addr.s_addr = addr->addr;
+#elif LWIP_IPV6
+#error Not supported IPv6.
+#endif
+
+    err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr *)&to, sizeof(to));
+    mem_free(iecho);
+
+    return (err == ping_size ? ERR_OK : ERR_VAL);
+}
+
+int lwip_ping_recv(int s, int *ttl)
+{
+    char buf[64];
+    int fromlen = sizeof(struct sockaddr_in), len;
+    struct sockaddr_in from;
+    struct ip_hdr *iphdr;
+    struct icmp_echo_hdr *iecho;
+
+    while ((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, (socklen_t *)&fromlen)) > 0) {
+        if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) {
+            iphdr = (struct ip_hdr *)buf;
+            iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
+            if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
+                *ttl = iphdr->_ttl;
+                return len;
+            }
+        }
+    }
+
+    return len;
+}
+
+/* using the lwIP custom ping */
+uint32_t cmd_ping(char *target_name, uint16_t interval, uint16_t size, uint32_t count)
+{
+#if LWIP_VERSION_MAJOR >= 2U
+    struct timeval timeout = { PING_RCV_TIMEO / (1000 * portTICK_PERIOD_MS), PING_RCV_TIMEO % (1000 * portTICK_PERIOD_MS) };
+#else
+    int timeout = PING_RCV_TIMEO * 1000UL / (1000 * portTICK_PERIOD_MS);
+#endif
+
+    int s, ttl = 0, recv_len;
+    ip_addr_t target_addr;
+    uint32_t send_times;
+    uint32_t recv_start_tick;
+    struct addrinfo hint, *res = NULL;
+    struct sockaddr_in *h = NULL;
+    struct in_addr ina;
+
+    send_times = 0;
+    ping_seq_num = 0;
+
+    if (size == 0) {
+        size = PING_DATA_SIZE;
+    }
+
+    memset(&hint, 0, sizeof(hint));
+    /* convert URL to IP */
+    if (lwip_getaddrinfo(target_name, NULL, &hint, &res) != 0) {
+        printf("ping: unknown host %s\n\r", target_name);
+        return -1;
+    }
+    memcpy(&h, &res->ai_addr, sizeof(struct sockaddr_in *));
+    memcpy(&ina, &h->sin_addr, sizeof(ina));
+    lwip_freeaddrinfo(res);
+    if (inet_aton(inet_ntoa(ina), &target_addr) == 0) {
+        printf("ping: unknown host %s\n\r", target_name);
+        return -1;
+    }
+    /* new a socket */
+    if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
+        printf("ping: create socket failed\n\r");
+        return -1;
+    }
+
+    lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+    while (1) {
+        int elapsed_time;
+
+        if (lwip_ping_send(s, &target_addr, size) == ERR_OK) {
+            recv_start_tick = sys_now();
+            if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0) {
+                elapsed_time = (sys_now() - recv_start_tick) * 1000UL / (1000 * portTICK_PERIOD_MS);
+                printf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n\r", recv_len, inet_ntoa(ina), send_times,
+                       ttl, elapsed_time);
+            } else {
+                printf("From %s icmp_seq=%d timeout\n\r", inet_ntoa(ina), send_times);
+            }
+        } else {
+            printf("Send %s - error\n\r", inet_ntoa(ina));
+        }
+
+        send_times++;
+        if (send_times >= count) {
+            /* send ping times reached, stop */
+            break;
+        }
+
+        vTaskDelay(interval); /* take a delay */
+    }
+
+    lwip_close(s);
+
+    return 0;
+}
+
+#include <shell.h>
+#include "utils_getopt.h"
+
+#define PING_USAGE \
+"ping [-c count] [-i interval] [-s size] [-h help] destination\r\n" \
+"\t\t-c count of ping requests. default is 4\r\n" \
+"\t\t-i interval in ms. default is 1000\r\n" \
+"\t\t-s ICMP payload size in bytes. default is 32\r\n" \
+"\t\t-h print this help\r\n"
+
+int ping(int argc, char **argv)
+{
+    int opt;
+    getopt_env_t getopt_env;
+    u16_t interval = PING_DELAY;
+    u16_t data_size = PING_DATA_SIZE;
+    u32_t total_count = 4;
+
+    if (argc == 1) {
+        goto usage;
+    } else {
+        utils_getopt_init(&getopt_env, 0);
+
+        while ((opt = utils_getopt(&getopt_env, argc, argv, ":i:s:c:W:h")) != -1) {
+            switch (opt) {
+                case 'i':
+                    interval = atoi(getopt_env.optarg);
+                    break;
+                case 's':
+                    data_size = atoi(getopt_env.optarg);
+                    break;
+                case 'c':
+                    total_count = atoi(getopt_env.optarg);
+                    break;
+                case 'h':
+                    goto usage;
+                case ':':
+                    printf("%s: %c requires an argument\r\n", *argv, getopt_env.optopt);
+                    goto usage;
+                case '?':
+                    printf("%s: unknown option %c\r\n", *argv, getopt_env.optopt);
+                    goto usage;
+            }
+        }
+
+        if (getopt_env.optind + 1 == argc) {
+            cmd_ping(argv[getopt_env.optind], interval, data_size, total_count);
+        } else {
+            printf("Need target address\r\n");
+            goto usage;
+        }
+    }
+
+    return 0;
+
+usage:
+    printf("%s", PING_USAGE);
+    return 0;
+}
+CSH_CMD_EXPORT(ping, ping network host);
+

+ 157 - 0
tests/hpmicro/src/uvc2lcd.c

@@ -0,0 +1,157 @@
+#include "board.h"
+#include "hpm_lcdc_drv.h"
+#include "hpm_l1c_drv.h"
+#include "usbh_uvc_stream.h"
+
+#define LCD          BOARD_LCD_BASE
+#define PIXEL_FORMAT display_pixel_format_ycbcr422
+
+#define IMAGE_WIDTH  640
+#define IMAGE_HEIGHT 480
+
+static ATTR_PLACE_AT_WITH_ALIGNMENT(".framebuffer", 64) uint8_t frame_buffer1[IMAGE_WIDTH * IMAGE_HEIGHT * 2];
+static ATTR_PLACE_AT_WITH_ALIGNMENT(".framebuffer", 64) uint8_t frame_buffer2[IMAGE_WIDTH * IMAGE_HEIGHT * 2];
+static struct usbh_videoframe frame_pool[2];
+
+void writefont2screen(uint16_t or_x, uint16_t or_y, uint16_t x_end, uint16_t y_end, uint8_t assic_id, uint16_t colour,
+                       uint8_t clearflag, uint8_t *str_font, uint32_t screen_addr, uint16_t font_size)
+{
+    uint8_t *strdisp;
+    uint16_t x, y;
+    uint8_t bit;
+    uint8_t temp1;
+    strdisp = (uint8_t *)screen_addr;
+    str_font += font_size * (assic_id - 0x20); /*get end encode*/
+    bit = 0;
+    for (y = or_y; y <= y_end; y++) {
+        for (x = or_x; x <= x_end; x++) {
+            if (clearflag == true) {
+                *(strdisp + y * (IMAGE_WIDTH * 2) + 2 * x) = colour & 0x00ff;
+                *(strdisp + y * (IMAGE_WIDTH * 2) + 2 * x + 1) = colour >> 8;
+            } else {
+                temp1 = (*str_font) >> bit;
+                if ((temp1 & 0x01) == 0x01) {
+                    *(strdisp + y * (IMAGE_WIDTH * 2) + 2 * x) = colour & 0x00ff;
+                    *(strdisp + y * (IMAGE_WIDTH * 2) + 2 * x + 1) = colour >> 8;
+                } else {
+                    *(strdisp + y * (IMAGE_WIDTH * 2) + 2 * x) = 0;
+                    *(strdisp + y * (IMAGE_WIDTH * 2) + 2 * x + 1) = 0;
+                }
+                bit++;
+                if (bit == 8) {
+                    bit = 0;
+                    str_font += 1;
+                }
+            }
+        }
+    }
+}
+
+char string2font(uint16_t line, uint16_t column, uint8_t *string, uint8_t string_num, uint16_t colour,
+                  uint8_t *str_font, uint32_t screen_addr, uint8_t font_width, uint8_t font_height)
+{
+    uint8_t i = 0, j = 0, numtemp = 0;
+    uint16_t or_x, or_y, x_end, y_end;
+    uint16_t font_stroage_size;
+    or_x = column * font_width;
+    or_y = line * font_height;
+    x_end = or_x + font_width - 1;
+    y_end = or_y + font_height - 1;
+    font_stroage_size = font_width * font_height / 8;
+    for (numtemp = 0; numtemp < string_num; numtemp++) {
+        if ((*(string + numtemp) != 10) && (*(string + numtemp) != 0)) { /*enter or end*/
+            if (*(string + numtemp) != 8) {                              /*delete*/
+                writefont2screen(or_x + font_width * i, or_y + font_height * j, x_end + font_width * i, y_end + font_height * j,
+                                  *(string + numtemp), colour, false, str_font, screen_addr, font_stroage_size);
+            } else {
+                writefont2screen(or_x + font_width * i, or_y + font_height * j, x_end + font_width * i, y_end + font_height * j,
+                                  *(string + numtemp), colour, true, str_font, screen_addr, font_stroage_size);
+            }
+        } else if (*(string + numtemp) == 10) {
+            i = 19; /* jump next line */
+        } else if (*(string + numtemp) == 0) {
+            return true;
+        }
+        i++;
+        if (i * font_width == IMAGE_WIDTH) {
+            j++;
+            i = 0;
+        }
+    }
+    return true;
+}
+
+extern const unsigned char nAsciiDot24x48[];
+extern volatile uint32_t g_uvc_fps;
+
+void usbh_video_run(struct usbh_video *video_class)
+{
+    usbh_video_stream_start(640, 480, USBH_VIDEO_FORMAT_UNCOMPRESSED);
+    lcdc_turn_on_display(LCD);
+}
+
+void usbh_video_stop(struct usbh_video *video_class)
+{
+    usbh_video_stream_stop();
+    lcdc_turn_off_display(LCD);
+}
+
+void usbh_video_frame_callback(struct usbh_videoframe *frame)
+{
+    char font_display_buf[50];
+
+    //USB_LOG_RAW("frame buf:%p,frame len:%d\r\n", frame->frame_buf, frame->frame_size);
+    l1c_dc_invalidate((uint32_t)frame->frame_buf, IMAGE_WIDTH * IMAGE_HEIGHT * 2);
+    sprintf(font_display_buf, "fps:%d", g_uvc_fps);
+    string2font(1, 1, (uint8_t *)font_display_buf, sizeof(font_display_buf), 0x001f, (uint8_t *)nAsciiDot24x48, (uint32_t)frame->frame_buf, 24, 48);
+    l1c_dc_writeback((uint32_t)frame->frame_buf, IMAGE_WIDTH * IMAGE_HEIGHT * 2);
+    lcdc_layer_set_next_buffer(LCD, 0, (uint32_t)frame->frame_buf);
+}
+
+void init_lcd(void)
+{
+    uint8_t layer_index = 0;
+    lcdc_config_t config = { 0 };
+    lcdc_layer_config_t layer = { 0 };
+
+    lcdc_get_default_config(LCD, &config);
+    board_panel_para_to_lcdc(&config);
+    lcdc_init(LCD, &config);
+
+    lcdc_get_default_layer_config(LCD, &layer, PIXEL_FORMAT, layer_index);
+
+    layer.position_x = (BOARD_LCD_WIDTH - IMAGE_WIDTH) / 2;
+    layer.position_y = (BOARD_LCD_HEIGHT - IMAGE_HEIGHT) / 2;
+    layer.width = IMAGE_WIDTH;
+    layer.height = IMAGE_HEIGHT;
+
+    layer.buffer = core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)frame_buffer1);
+    layer.alphablend.src_alpha = 0xF4; /* src */
+    layer.alphablend.dst_alpha = 0xF0; /* dst */
+    layer.alphablend.src_alpha_op = display_alpha_op_override;
+    layer.alphablend.dst_alpha_op = display_alpha_op_override;
+    layer.background.u = 0xffff0000;
+    layer.alphablend.mode = display_alphablend_mode_xor;
+
+    if (status_success != lcdc_config_layer(LCD, layer_index, &layer, true)) {
+        printf("failed to configure layer\n");
+        while (1)
+            ;
+    }
+}
+
+void uvc2lcd_init(void)
+{
+    board_init_lcd();
+    init_lcd();
+
+    frame_pool[0].frame_buf = frame_buffer1;
+    frame_pool[0].frame_bufsize = IMAGE_WIDTH * IMAGE_HEIGHT * 2;
+    frame_pool[1].frame_buf = frame_buffer2;
+    frame_pool[1].frame_bufsize = IMAGE_WIDTH * IMAGE_HEIGHT * 2;
+
+    usbh_video_stream_init(5, frame_pool, 2);
+
+    extern void usbh_video_fps_init(void);
+    usbh_video_fps_init();
+}