diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index fe51da16..5ce6e416 100644 --- a/.github/workflows/build_tests.yml +++ b/.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: diff --git a/tests/bouffalolab/CMakeLists.txt b/tests/bouffalolab/CMakeLists.txt new file mode 100644 index 00000000..7d56aaa9 --- /dev/null +++ b/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) diff --git a/tests/bouffalolab/Makefile b/tests/bouffalolab/Makefile new file mode 100644 index 00000000..c5b7d56d --- /dev/null +++ b/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 diff --git a/tests/bouffalolab/flash_prog_cfg.ini b/tests/bouffalolab/flash_prog_cfg.ini new file mode 100644 index 00000000..d0077a95 --- /dev/null +++ b/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 + diff --git a/tests/bouffalolab/inc/FreeRTOSConfig.h b/tests/bouffalolab/inc/FreeRTOSConfig.h new file mode 100644 index 00000000..064b2b22 --- /dev/null +++ b/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 + +#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 */ \ No newline at end of file diff --git a/tests/bouffalolab/inc/fatfs_conf_user.h b/tests/bouffalolab/inc/fatfs_conf_user.h new file mode 100644 index 00000000..a1addd77 --- /dev/null +++ b/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 ---*/ diff --git a/tests/bouffalolab/inc/lwipopts_user.h b/tests/bouffalolab/inc/lwipopts_user.h new file mode 100644 index 00000000..3792fa93 --- /dev/null +++ b/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__ */ diff --git a/tests/bouffalolab/inc/usb_config.h b/tests/bouffalolab/inc/usb_config.h new file mode 100644 index 00000000..d158eb92 --- /dev/null +++ b/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 + +#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 diff --git a/tests/bouffalolab/proj.conf b/tests/bouffalolab/proj.conf new file mode 100644 index 00000000..0e597231 --- /dev/null +++ b/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) diff --git a/tests/bouffalolab/src/main.c b/tests/bouffalolab/src/main.c new file mode 100644 index 00000000..12201af8 --- /dev/null +++ b/tests/bouffalolab/src/main.c @@ -0,0 +1,158 @@ +#include +#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); + 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 \ No newline at end of file diff --git a/tests/hpmicro/CMakeLists.txt b/tests/hpmicro/CMakeLists.txt index 5824878c..40b0e56c 100644 --- a/tests/hpmicro/CMakeLists.txt +++ b/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) diff --git a/tests/hpmicro/inc/FreeRTOSConfig.h b/tests/hpmicro/inc/FreeRTOSConfig.h index d2169531..89fd13a7 100644 --- a/tests/hpmicro/inc/FreeRTOSConfig.h +++ b/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. */ diff --git a/tests/hpmicro/inc/arch/cc.h b/tests/hpmicro/inc/arch/cc.h index 4c527c03..cca22bc8 100644 --- a/tests/hpmicro/inc/arch/cc.h +++ b/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 +#include + #define PACK_STRUCT_BEGIN #define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) #define PACK_STRUCT_END #define PACK_STRUCT_FIELD(x) x +#elif defined(__ICCRISCV__) + +#include +#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__ */ diff --git a/tests/hpmicro/inc/arch/sys_arch.c b/tests/hpmicro/inc/arch/sys_arch.c index 24e2dda8..cb32e9ca 100644 --- a/tests/hpmicro/inc/arch/sys_arch.c +++ b/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); + 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; - } + 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); - - 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) -{ - BaseType_t ret; - LWIP_ASSERT("sem != NULL", sem != NULL); - LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); - - 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) -{ - 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; + sem->sem = xSemaphoreCreateBinary(); + if (sem->sem == NULL) { + SYS_STATS_INC(sem.err); + return ERR_MEM; } - LWIP_ASSERT("taking semaphore failed", ret == pdTRUE); - } + SYS_STATS_INC_USED(sem); - /* 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) -{ - LWIP_ASSERT("sem != NULL", sem != NULL); - LWIP_ASSERT("sem->sem != NULL", 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) -{ - LWIP_ASSERT("mbox != NULL", mbox != NULL); - 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; -} - -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); - - 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) -{ - BaseType_t ret; - LWIP_ASSERT("mbox != NULL", mbox != NULL); - LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); - - 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) -{ - BaseType_t ret; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - LWIP_ASSERT("mbox != NULL", mbox != NULL); - LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); - - ret = xQueueSendToBackFromISR(mbox->mbx, &msg, &xHigherPriorityTaskWoken); - if (ret == pdTRUE) { - if (xHigherPriorityTaskWoken == pdTRUE) { - return ERR_NEED_SCHED; + if (initial_count == 1) { + BaseType_t ret = xSemaphoreGive(sem->sem); + LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE); } 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) +void sys_sem_signal(sys_sem_t *sem) { - BaseType_t ret; - void *msg_dummy; - LWIP_ASSERT("mbox != NULL", mbox != NULL); - LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); + BaseType_t ret; + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); /* NOLINT */ - if (!msg) { - msg = &msg_dummy; - } + 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)); +} - 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); +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); /* 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); + } + + /* 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) +{ + 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; +} + +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + 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; +} + +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); /* NOLINT */ + + 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) +{ + 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; + } +} + +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); /* NOLINT */ + + 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; + } +} + +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); /* NOLINT */ + + 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; + } + 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; +} + +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); /* NOLINT */ + + if (!msg) { + msg = &msg_dummy; + } + + ret = xQueueReceive(mbox->mbx, &(*msg), 0); if (ret == errQUEUE_EMPTY) { - /* timed out */ - *msg = NULL; - return SYS_ARCH_TIMEOUT; + *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; } -u32_t -sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +void sys_mbox_free(sys_mbox_t *mbox) { - BaseType_t ret; - void *msg_dummy; - LWIP_ASSERT("mbox != NULL", mbox != NULL); - LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); - - 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); - - /* 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) -{ - 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 sys_arch_netconn_sem_alloc(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; - 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); - } + 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 */ } diff --git a/tests/hpmicro/inc/lwipopts.h b/tests/hpmicro/inc/lwipopts.h index e8898bc5..09ec2fdc 100644 --- a/tests/hpmicro/inc/lwipopts.h +++ b/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 - -#define SYS_LIGHTWEIGHT_PROT 0 -#define LWIP_PROVIDE_ERRNO 1 - -#if defined(__SEGGER_RTL_VERSION) -#define LWIP_TIMEVAL_PRIVATE 1 -#else -#define LWIP_TIMEVAL_PRIVATE 0 +#ifdef USE_LWIPOPTS_APP_H +#include "lwipopts_app.h" #endif -#define LWIP_RAND rand +/** + * 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 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 -#define LWIP_DEBUG 1 +/* ---------- 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 -#define LWIP_DBG_MIN_LEVEL 1 +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL 0 +#endif -#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 +#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 -#define DHCP_DOES_ARP_CHECK 0 - /* - * --------------------------------- - * ---------- 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 -#include -#include -#endif /* __LWIPOPTS_H__ */ \ No newline at end of file +#ifndef LWIP_MEM_SECTION +#define LWIP_MEM_SECTION ".bss" +#endif + +#endif /* __LWIPOPTS_H__ */ diff --git a/tests/hpmicro/inc/usb_config.h b/tests/hpmicro/inc/usb_config.h index 1700635e..a9ee4fc5 100644 --- a/tests/hpmicro/inc/usb_config.h +++ b/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 diff --git a/tests/hpmicro/src/font24x48.c b/tests/hpmicro/src/font24x48.c new file mode 100644 index 00000000..c11c609b --- /dev/null +++ b/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, + +}; diff --git a/tests/hpmicro/src/iperf/iperf.c b/tests/hpmicro/src/iperf/iperf.c new file mode 100644 index 00000000..a7e1fa8f --- /dev/null +++ b/tests/hpmicro/src/iperf/iperf.c @@ -0,0 +1,763 @@ + +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/tests/hpmicro/src/iperf/iperf.h b/tests/hpmicro/src/iperf/iperf.h new file mode 100644 index 00000000..ea69b4ba --- /dev/null +++ b/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 diff --git a/tests/hpmicro/src/iperf/iperf_cli.c b/tests/hpmicro/src/iperf/iperf_cli.c new file mode 100644 index 00000000..8db3e050 --- /dev/null +++ b/tests/hpmicro/src/iperf/iperf_cli.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include + +#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 +#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); + diff --git a/tests/hpmicro/src/iperf/utils_getopt.c b/tests/hpmicro/src/iperf/utils_getopt.c new file mode 100644 index 00000000..f012b67c --- /dev/null +++ b/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 +#include +#include +#include +#include +#include + +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; +} diff --git a/tests/hpmicro/src/iperf/utils_getopt.h b/tests/hpmicro/src/iperf/utils_getopt.h new file mode 100644 index 00000000..5f6c9c97 --- /dev/null +++ b/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 + * #include + * + * 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__ */ diff --git a/tests/hpmicro/src/main.c b/tests/hpmicro/src/main.c index 7e62cb6f..aaadb1c8 100644 --- a/tests/hpmicro/src/main.c +++ b/tests/hpmicro/src/main.c @@ -13,9 +13,14 @@ #include #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); 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, ); \ No newline at end of file +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 \ No newline at end of file diff --git a/tests/hpmicro/src/ping.c b/tests/hpmicro/src/ping.c new file mode 100644 index 00000000..49e984a0 --- /dev/null +++ b/tests/hpmicro/src/ping.c @@ -0,0 +1,257 @@ +/* + * netutils: ping implementation + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * 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 +#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); + diff --git a/tests/hpmicro/src/uvc2lcd.c b/tests/hpmicro/src/uvc2lcd.c new file mode 100644 index 00000000..71d36865 --- /dev/null +++ b/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(); +} \ No newline at end of file