diff --git a/.github/workflows/CMake.yml b/.github/workflows/CMake.yml index 9221bcfd..9074d72e 100644 --- a/.github/workflows/CMake.yml +++ b/.github/workflows/CMake.yml @@ -4,9 +4,9 @@ name: CMake Build Test on: push: - branches: [ "main" ] + branches: [ "main", "v0.2.0" ] pull_request: - branches: [ "main" ] + branches: [ "main", "v0.2.0" ] env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) @@ -28,7 +28,7 @@ jobs: - name: Configure CMake arm-none-eabi # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build-arm-none-eabi -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + run: cmake -B ${{github.workspace}}/build-arm-none-eabi -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_BOARD_FILE=tinyvision.cmake - name: Build arm-none-eabi # Build your program with the given configuration @@ -37,7 +37,7 @@ jobs: - name: Configure CMake arm-linux-gnueabihf # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build-arm-linux-gnueabihf -DCROSS_COMPILE=arm-linux-gnueabihf- -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + run: cmake -B ${{github.workspace}}/build-arm-linux-gnueabihf -DCROSS_COMPILE=arm-linux-gnueabihf- -DCMAKE_BOARD_FILE=tinyvision.cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - name: Build arm-linux-gnueabihf # Build your program with the given configuration @@ -46,7 +46,7 @@ jobs: - name: Configure CMake arm-linux-gnueabi # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build-arm-linux-gnueabi -DCROSS_COMPILE=arm-linux-gnueabi- -DENABLE_HARDFP=OFF -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + run: cmake -B ${{github.workspace}}/build-arm-linux-gnueabi -DCROSS_COMPILE=arm-linux-gnueabi- -DCMAKE_BOARD_FILE=tinyvision.cmake -DENABLE_HARDFP=OFF -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - name: Build arm-linux-gnueabi # Build your program with the given configuration diff --git a/.gitignore b/.gitignore index ee89501c..77636951 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/ test/ tools/*.bin -mksunxi \ No newline at end of file +mksunxi +.vscode/settings.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bcad57e..654c2670 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,39 +1,43 @@ # SPDX-License-Identifier: Apache-2.0 +# Specify the minimum required version of CMake cmake_minimum_required(VERSION 3.10) -# Options +# Define the path to the board loader files +set(BOARD_FLOADER_PATH ${CMAKE_SOURCE_DIR}/cmake/board/) -# By setting ENABLE_HARDFP to ON, it indicates that the project is configured -# to utilize hard floating-point operations when applicable. This can be beneficial -# in scenarios where performance gains from hardware acceleration are desired. -option(ENABLE_HARDFP "Enable hardware floating-point operations" ON) - -set(CROSS_COMPILE "arm-none-eabi-") - -set(CROSS_COMPILE ${CROSS_COMPILE} CACHE STRING "CROSS_COMPILE Toolchain") - -set(CMAKE_C_COMPILER "${CROSS_COMPILE}gcc") -set(CMAKE_CXX_COMPILER "${CROSS_COMPILE}g++") - -if(ENABLE_HARDFP) -set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=hard") +# Check if the CMAKE_BOARD_FILE variable is defined +if(CMAKE_BOARD_FILE) + # Set the value of CMAKE_BOARD_FILE and include the file + set(CMAKE_BOARD_FILE ${BOARD_FLOADER_PATH}${CMAKE_BOARD_FILE}) + message(STATUS "CMAKE_BOARD_FILE = ${CMAKE_BOARD_FILE}") + include(${CMAKE_BOARD_FILE}) else() -set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=softfp") + set(CMAKE_AVALIABLE_BOARD "") + file(GLOB FILE_LIST "${BOARD_FLOADER_PATH}/*.cmake") + foreach(FILE_PATH ${FILE_LIST}) + get_filename_component(BOARD_FILE_NAME ${FILE_PATH} NAME) + set(CMAKE_AVALIABLE_BOARD "${CMAKE_AVALIABLE_BOARD}\n ${BOARD_FILE_NAME}") + endforeach() + message(FATAL_ERROR + "You need to select target Board:" + "${CMAKE_AVALIABLE_BOARD}" + "\nUse -DCMAKE_BOARD_FILE=xxx.cmake to define target board" + "\neg:" + "\n cmake -DCMAKE_BOARD_FILE=tinyvision.cmake .." + ) endif() -set(CMAKE_C_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers") -set(CMAKE_CXX_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast") - +# Set compilation flags set(CMAKE_C_FLAGS "${CMAKE_C_DISABLE_WARN_FLAGS} ${CMAKE_C_FLAGS} ${CMAKE_COMMON_FLAGS}" CACHE STRING "c flags") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_DISABLE_WARN_FLAGS} ${CMAKE_CXX_FLAGS} ${CMAKE_COMMON_FLAGS}" CACHE STRING "c++ flags") set(CMAKE_ASM_FLAGS "${CMAKE_C_DISABLE_WARN_FLAGS} ${CMAKE_ASM_FLAGS} ${CMAKE_COMMON_FLAGS}" CACHE STRING "asm flags") -# Set Version, Release need cmake +# Define the major and minor version numbers of the project set(PROJECT_VERSION_MAJOR 0) -set(PROJECT_VERSION_MINOR 0) +set(PROJECT_VERSION_MINOR 2) -# use git version as library version +# Use Git commands to get the Git version and hash values of the project find_package(Git QUIET) if (Git_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") execute_process( @@ -55,19 +59,24 @@ else () set(PROJECT_GIT_HASH "") endif () +# Define the project name and languages used project(SyterKit C CXX ASM) +# Include other CMake modules include(cmake/add_syterkit_app.cmake) include(ExternalProject) +# Get the name of the compiler string(SUBSTRING ${CMAKE_C_COMPILER} 1 -1 COMPILER_NAME) string(REGEX REPLACE ".*/" "" COMPILER_NAME ${COMPILER_NAME}) +# Configure file as required configure_file( "${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ) +# Create an external project and build it ExternalProject_Add( mksunxi PREFIX mksunxi @@ -78,74 +87,75 @@ ExternalProject_Add( BUILD_IN_SOURCE 1 ) +# Set tools required for the build process set(CMAKE_AR "${CROSS_COMPILE}ar") set(CMAKE_OBJCOPY "${CROSS_COMPILE}objcopy") set(CMAKE_SIZE "${CROSS_COMPILE}size") +# Define the path to the mksunxi tool set(CMAKE_MKSUNXI "${PROJECT_SOURCE_DIR}/tools/mksunxi") -set(LINK_SCRIPT_FEL ${CMAKE_SOURCE_DIR}/link/link_elf.ld) -set(LINK_SCRIPT_BIN ${CMAKE_SOURCE_DIR}/link/link_bin.ld) +# Define the paths to the linker scripts +set(LINK_SCRIPT_FEL ${PROJECT_BINARY_DIR}/link_elf.ld) +set(LINK_SCRIPT_BIN ${PROJECT_BINARY_DIR}/link_bin.ld) + +# If the CONFIG_ARCH_ARM32 variable is defined, execute the following content +if (CONFIG_ARCH_ARM32) +set(ARCH_INCLUDE include/arch/arm32) + +set(ARCH_START_ADDRESS "${ARCH_BIN_START_ADDRESS}") +set(ARCH_SRAM_LENGTH "${ARCH_BIN_SRAM_LENGTH}") + +configure_file( + "${PROJECT_SOURCE_DIR}/link/arm32/link.ld" + "${PROJECT_BINARY_DIR}/link_bin.ld" +) + +set(ARCH_START_ADDRESS "${ARCH_FEL_START_ADDRESS}") +set(ARCH_SRAM_LENGTH "${ARCH_FEL_SRAM_LENGTH}") + +configure_file( + "${PROJECT_SOURCE_DIR}/link/arm32/link.ld" + "${PROJECT_BINARY_DIR}/link_elf.ld" +) +endif() + +# If the CONFIG_ARCH_ARM32 variable is defined, execute the following content +if (CONFIG_ARCH_RISCV64) +set(ARCH_INCLUDE include/arch/riscv64) + +set(ARCH_START_ADDRESS "${ARCH_BIN_START_ADDRESS}") +set(ARCH_SRAM_LENGTH "${ARCH_BIN_SRAM_LENGTH}") + +configure_file( + "${PROJECT_SOURCE_DIR}/link/riscv64/link.ld" + "${PROJECT_BINARY_DIR}/link_bin.ld" +) +set(ARCH_START_ADDRESS "${ARCH_FEL_START_ADDRESS}") +set(ARCH_SRAM_LENGTH "${ARCH_FEL_SRAM_LENGTH}") + +configure_file( + "${PROJECT_SOURCE_DIR}/link/riscv64/link.ld" + "${PROJECT_BINARY_DIR}/link_elf.ld" +) +endif() + +# Specify the paths of the include files include_directories( include include/cli - include/arch include/drivers - include/reg + include/drivers/reg include/lib/fatfs include/lib/fdt include/lib/elf include/lib/ini + ${ARCH_INCLUDE} ${PROJECT_BINARY_DIR} ) -add_library(SyterKit - # log - src/log/log.c - src/log/xformat.c - # string - src/string/string.c - src/string/memcpy.S - src/string/memset.S - src/string/memcmp.S - # cli - src/cli/commands.c - src/cli/history.c - src/cli/lineedit.c - src/cli/parse.c - src/cli/shell.c - # exception & common - src/exception.c - src/common.c - # src - src/jmp.c - src/uart.c - src/ctype.c - src/fdt_wrapper.c - src/smalloc.c - src/sstdlib.c - src/cache.S - # deiver - drivers/sys-clk.c - drivers/sys-dma.c - drivers/sys-gpio.c - drivers/sys-dram.c - drivers/sys-sdcard.c - drivers/sys-sdhci.c - drivers/sys-rproc.c - drivers/sys-spi.c - drivers/sys-spi-nand.c - drivers/sys-sid.c - drivers/sys-timer.c - drivers/sys-uart.c - drivers/sys-wdt.c - drivers/sys-rtc.c - drivers/sys-i2c.c -) - -target_link_libraries(SyterKit gcc fdt) - +# Add subdirectories and execute the appropriate CMakeLists.txt files +add_subdirectory(src) add_subdirectory(lib) - -add_subdirectory(app) \ No newline at end of file +add_subdirectory(board) diff --git a/assets/post/README/image-20231206211759386.png b/assets/post/README/image-20231206211759386.png deleted file mode 100644 index 5781cc5f..00000000 Binary files a/assets/post/README/image-20231206211759386.png and /dev/null differ diff --git a/assets/post/README/image-20231206212123866.png b/assets/post/README/image-20231206212123866.png deleted file mode 100644 index 7e9a9ac2..00000000 Binary files a/assets/post/README/image-20231206212123866.png and /dev/null differ diff --git a/assets/post/README/image-20231206212457356.png b/assets/post/README/image-20231206212457356.png deleted file mode 100644 index bd361ac4..00000000 Binary files a/assets/post/README/image-20231206212457356.png and /dev/null differ diff --git a/assets/post/README/image-20231206212627062.png b/assets/post/README/image-20231206212627062.png deleted file mode 100644 index 19e3e86c..00000000 Binary files a/assets/post/README/image-20231206212627062.png and /dev/null differ diff --git a/assets/post/README/image-20231206213445553.png b/assets/post/README/image-20231206213445553.png deleted file mode 100644 index 7b878ac7..00000000 Binary files a/assets/post/README/image-20231206213445553.png and /dev/null differ diff --git a/board/100ask-t113i/CMakeLists.txt b/board/100ask-t113i/CMakeLists.txt new file mode 100644 index 00000000..f7d914a2 --- /dev/null +++ b/board/100ask-t113i/CMakeLists.txt @@ -0,0 +1,13 @@ +set(APP_COMMON_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/start.S + ${CMAKE_CURRENT_SOURCE_DIR}/board.c + ${CMAKE_CURRENT_SOURCE_DIR}/eabi_compat.c +) + +add_subdirectory(hello_world) + +add_subdirectory(sys_info) + +add_subdirectory(syter_boot) + +add_subdirectory(load_c906) \ No newline at end of file diff --git a/app/common/README.md b/board/100ask-t113i/README.md similarity index 100% rename from app/common/README.md rename to board/100ask-t113i/README.md diff --git a/board/100ask-t113i/board.c b/board/100ask-t113i/board.c new file mode 100644 index 00000000..10223383 --- /dev/null +++ b/board/100ask-t113i/board.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +sunxi_serial_t uart_dbg = { + .base = SUNXI_UART0_BASE, + .id = 0, + .gpio_tx = {GPIO_PIN(GPIO_PORTB, 8), GPIO_PERIPH_MUX6}, + .gpio_rx = {GPIO_PIN(GPIO_PORTB, 9), GPIO_PERIPH_MUX6}, +}; + +sunxi_spi_t sunxi_spi0 = { + .base = SUNXI_SPI0_BASE, + .id = 0, + .clk_rate = 75 * 1000 * 1000, + .gpio_cs = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX4}, + .gpio_sck = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX4}, + .gpio_mosi = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX4}, + .gpio_miso = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX4}, + .gpio_wp = {GPIO_PIN(GPIO_PORTC, 4), GPIO_PERIPH_MUX4}, + .gpio_hold = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX4}, +}; + +sdhci_t sdhci0 = { + .name = "sdhci0", + .reg = (sdhci_reg_t *) SUNXI_SMHC0_BASE, + .voltage = MMC_VDD_27_36, + .width = MMC_BUS_WIDTH_4, + .clock = MMC_CLK_50M, + .removable = 0, + .isspi = FALSE, + .gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2}, + .gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2}, + .gpio_d0 = {GPIO_PIN(GPIO_PORTF, 1), GPIO_PERIPH_MUX2}, + .gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2}, + .gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2}, + .gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2}, +}; + +sdhci_t sdhci2 = { + .name = "sdhci2", + .reg = (sdhci_reg_t *) SUNXI_SMHC2_BASE, + .voltage = MMC_VDD_27_36, + .width = MMC_BUS_WIDTH_4, + .clock = MMC_CLK_50M, + .removable = 0, + .isspi = FALSE, + .gpio_clk = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX3}, + .gpio_cmd = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX3}, + .gpio_d0 = {GPIO_PIN(GPIO_PORTC, 6), GPIO_PERIPH_MUX3}, + .gpio_d1 = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX3}, + .gpio_d2 = {GPIO_PIN(GPIO_PORTC, 4), GPIO_PERIPH_MUX3}, + .gpio_d3 = {GPIO_PIN(GPIO_PORTC, 7), GPIO_PERIPH_MUX3}, +}; + +dram_para_t dram_para = { + .dram_clk = 792, + .dram_type = 3, + .dram_zq = 0x7b7bfb, + .dram_odt_en = 0x01, + .dram_para1 = 0x000010d2, + .dram_para2 = 0, + .dram_mr0 = 0x1c70, + .dram_mr1 = 0x42, + .dram_mr2 = 0x18, + .dram_mr3 = 0, + .dram_tpr0 = 0x004a2195, + .dram_tpr1 = 0x02423190, + .dram_tpr2 = 0x0008b061, + .dram_tpr3 = 0xb4787896,// unused + .dram_tpr4 = 0, + .dram_tpr5 = 0x48484848, + .dram_tpr6 = 0x00000048, + .dram_tpr7 = 0x1620121e,// unused + .dram_tpr8 = 0, + .dram_tpr9 = 0,// clock? + .dram_tpr10 = 0, + .dram_tpr11 = 0x00770000, + .dram_tpr12 = 0x00000002, + .dram_tpr13 = 0x34050100, +}; + +void clean_syterkit_data(void) { + /* Disable MMU, data cache, instruction cache, interrupts */ + arm32_mmu_disable(); + printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); + arm32_dcache_disable(); + printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); + arm32_icache_disable(); + printk(LOG_LEVEL_INFO, "disable icache ok...\n"); + arm32_interrupt_disable(); + printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); +} diff --git a/app/common/eabi_compat.c b/board/100ask-t113i/eabi_compat.c similarity index 100% rename from app/common/eabi_compat.c rename to board/100ask-t113i/eabi_compat.c diff --git a/app/hello_world/CMakeLists.txt b/board/100ask-t113i/hello_world/CMakeLists.txt similarity index 100% rename from app/hello_world/CMakeLists.txt rename to board/100ask-t113i/hello_world/CMakeLists.txt diff --git a/app/hello_world/main.c b/board/100ask-t113i/hello_world/main.c similarity index 56% rename from app/hello_world/main.c rename to board/100ask-t113i/hello_world/main.c index 404afa24..b588126a 100644 --- a/app/hello_world/main.c +++ b/board/100ask-t113i/hello_world/main.c @@ -7,14 +7,7 @@ #include -#include - -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; int main(void) { sunxi_serial_init(&uart_dbg); diff --git a/board/100ask-t113i/load_c906/CMakeLists.txt b/board/100ask-t113i/load_c906/CMakeLists.txt new file mode 100644 index 00000000..edf4245a --- /dev/null +++ b/board/100ask-t113i/load_c906/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(load_c906 + main.c +) \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/CMakeLists.txt b/board/100ask-t113i/load_c906/c906_firmware/CMakeLists.txt new file mode 100644 index 00000000..f9109496 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/CMakeLists.txt @@ -0,0 +1,73 @@ +cmake_minimum_required(VERSION 3.10) + +set(RISCV_ROOT_PATH "~/sdk/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.8.0") + +set(RISCV_ROOT_PATH ${RISCV_ROOT_PATH} CACHE STRING "root path to riscv toolchain") + +set(CMAKE_C_COMPILER "${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-g++") + +set(CMAKE_SYSROOT "${RISCV_ROOT_PATH}/sysroot") + +set(CMAKE_COMMON_FLAGS "-march=rv64gvxthead -mabi=lp64d -mcmodel=medany -fno-stack-protector") +set(CMAKE_DISABLE_WARN_FLAGS "-Wint-to-pointer-cast -Wimplicit-function-declaration") + +set(CMAKE_C_FLAGS "${CMAKE_DISABLE_WARN_FLAGS} ${CMAKE_C_FLAGS} ${CMAKE_COMMON_FLAGS}" CACHE STRING "c flags") +set(CMAKE_CXX_FLAGS "${CMAKE_DISABLE_WARN_FLAGS} ${CMAKE_CXX_FLAGS} ${CMAKE_COMMON_FLAGS}" CACHE STRING "c++ flags") + +set(CMAKE_FIND_ROOT_PATH "${RISCV_ROOT_PATH}/riscv64-unknown-linux-gnu") + +set(CMAKE_SYSROOT "${RISCV_ROOT_PATH}/sysroot") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Set Version, Release need cmake +set(PROJECT_VERSION_MAJOR 0) +set(PROJECT_VERSION_MINOR 0) + +# use git version as library version +find_package(Git QUIET) +if (Git_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../.git") + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE _git_version + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%h + OUTPUT_VARIABLE PROJECT_GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR} + ) +else () + set(_git_version 0) + set(PROJECT_GIT_HASH "") +endif () + +project(D1s-DRAM C CXX ASM) + +configure_file( + "${PROJECT_SOURCE_DIR}/config.h.in" + "${PROJECT_BINARY_DIR}/config.h" +) + +set(CMAKE_AR "${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-ar") +set(CMAKE_OBJCOPY "${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-objcopy") + +set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/link.ld) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${LINKER_SCRIPT} -nostdlib") + +include_directories( + include + include/sys + ${PROJECT_BINARY_DIR} +) + +add_subdirectory(lib) +add_subdirectory(src) \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/README.md b/board/100ask-t113i/load_c906/c906_firmware/README.md new file mode 100644 index 00000000..6552d247 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/README.md @@ -0,0 +1,54 @@ +# Tiny C906 Firmware For T113-I + +## How to build + +``` +mkdir build && cd build +cmake -DRISCV_ROOT_PATH=/path/to/riscv/toolchain .. +make + +``` + +1. `mkdir build` creates a directory named "build". +2. `cd build` changes the current directory to "build". +3. `cmake -DRISCV_ROOT_PATH=/path/to/riscv/toolchain ..` configures the build system using CMake. The `-DRISCV_ROOT_PATH` option specifies the path to the RISC-V toolchain. +4. `make` compiles the project using the configured build system. + +By running these commands, a build directory is created, the build process is configured with the specified RISC-V toolchain path, and the project is compiled using the `make` command. + +## start.S + +This code is written in assembly language for a RISC-V processor. Here's a breakdown of its functionality: + +The `.global _start` directive indicates that `_start` is the entry point of the program. + +At the `_start` label: +1. `li t1, 0x1 << 22` loads the immediate value `0x1` shifted left by `22` into register `t1`. +2. `csrs mxstatus, t1` sets the MXSTATUS register with the value in `t1`, enabling machine-level interrupts. +3. `li t1, 0x30013` loads the immediate value `0x30013` into register `t1`. +4. `csrs mcor, t1` sets the MCOR register with the value in `t1`, configuring the machine-level interrupt controller. +5. `j reset` jumps to the `reset` label. + +At the `reset` label: +1. Memory is allocated on the stack by subtracting `32` from the stack pointer (`sp`). +2. Registers `s0`, `s1`, and `ra` are saved onto the stack using the `sd` instruction. +3. The value of `a0` is moved into `s0` register. +4. `li t0, 0x07090108` loads the immediate value `0x07090108` into register `t0`. +5. `sw zero, (t0)` stores the value of register `zero` (which holds the value `0`) at the memory address pointed to by `t0`. +6. `jal main` jumps and links to the `main` function. + +After the `jal` instruction, the execution will continue at the `main` function. Once the `main` function returns: +1. The saved registers are restored from the stack. +2. The stack pointer is adjusted by adding `32` to it. +3. `ret` instruction is executed, which returns control to the calling function. + +Overall, this code sets up machine-level interrupts, configures the interrupt controller, initializes the stack, and jumps to the `main` function before returning to the caller. + +## main.c + +This code defines a constant `OPENSBI_FW_TEXT_START` with the value `0x41fc0000`. + +The function `jmp_opensbi` takes an argument `opensbi_base` of type `uint32_t` and performs an assembly instruction that jumps to the address stored in register `a0`. After the jump, it enters an infinite loop where it executes a `WFI` (Wait for Interrupt) instruction and then jumps back to `__LOOP` label. + +The `main` function initializes UART0 and prints a series of messages to the console using `sys_uart_printf` function. It counts from 0 to 8 using a `for` loop and delays for 100,000 cycles between each count. Finally, it prints a message and calls `jmp_opensbi` function with the `OPENSBI_FW_TEXT_START` constant as the argument. + diff --git a/board/100ask-t113i/load_c906/c906_firmware/config.h.in b/board/100ask-t113i/load_c906/c906_firmware/config.h.in new file mode 100644 index 00000000..c1ee0954 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/config.h.in @@ -0,0 +1,11 @@ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +// Project Info +#define PROJECT_NAME "@PROJECT_NAME@" +#define PROJECT_GIT_HASH 0x@PROJECT_GIT_HASH@ + +// System Configure +#define UART0_BASE_ADDR 0x02500000 + +#endif // _CONFIG_H_ \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/byteorder.h b/board/100ask-t113i/load_c906/c906_firmware/include/byteorder.h new file mode 100644 index 00000000..3a77a4cf --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/byteorder.h @@ -0,0 +1,67 @@ +#ifndef __BYTEORDER_H__ +#define __BYTEORDER_H__ + +#include + +static inline u16_t __swab16(u16_t x) { return ((x << 8) | (x >> 8)); } + +static inline u32_t __swab32(u32_t x) { + return ((x << 24) | (x >> 24) | ((x & (u32_t)0x0000ff00UL) << 8) | + ((x & (u32_t)0x00ff0000UL) >> 8)); +} + +static inline u64_t __swab64(u64_t x) { + return ((x << 56) | (x >> 56) | ((x & (u64_t)0x000000000000ff00ULL) << 40) | + ((x & (u64_t)0x0000000000ff0000ULL) << 24) | + ((x & (u64_t)0x00000000ff000000ULL) << 8) | + ((x & (u64_t)0x000000ff00000000ULL) >> 8) | + ((x & (u64_t)0x0000ff0000000000ULL) >> 24) | + ((x & (u64_t)0x00ff000000000000ULL) >> 40)); +} + +/* + * swap bytes bizarrely. + * swahw32 - swap 16-bit half-words in a 32-bit word + */ +static inline u32_t __swahw32(u32_t x) { + return (((x & (u32_t)0x0000ffffUL) << 16) | + ((x & (u32_t)0xffff0000UL) >> 16)); +} + +/* + * swap bytes bizarrely. + * swahb32 - swap 8-bit halves of each 16-bit half-word in a 32-bit word + */ +static inline u32_t __swahb32(u32_t x) { + return (((x & (u32_t)0x00ff00ffUL) << 8) | ((x & (u32_t)0xff00ff00UL) >> 8)); +} + +#if (BYTE_ORDER == BIG_ENDIAN) +#define cpu_to_le64(x) (__swab64((u64_t)(x))) +#define le64_to_cpu(x) (__swab64((u64_t)(x))) +#define cpu_to_le32(x) (__swab32((u32_t)(x))) +#define le32_to_cpu(x) (__swab32((u32_t)(x))) +#define cpu_to_le16(x) (__swab16((u16_t)(x))) +#define le16_to_cpu(x) (__swab16((u16_t)(x))) +#define cpu_to_be64(x) ((u64_t)(x)) +#define be64_to_cpu(x) ((u64_t)(x)) +#define cpu_to_be32(x) ((u32_t)(x)) +#define be32_to_cpu(x) ((u32_t)(x)) +#define cpu_to_be16(x) ((u16_t)(x)) +#define be16_to_cpu(x) ((u16_t)(x)) +#else +#define cpu_to_le64(x) ((u64_t)(x)) +#define le64_to_cpu(x) ((u64_t)(x)) +#define cpu_to_le32(x) ((u32_t)(x)) +#define le32_to_cpu(x) ((u32_t)(x)) +#define cpu_to_le16(x) ((u16_t)(x)) +#define le16_to_cpu(x) ((u16_t)(x)) +#define cpu_to_be64(x) (__swab64((u64_t)(x))) +#define be64_to_cpu(x) (__swab64((u64_t)(x))) +#define cpu_to_be32(x) (__swab32((u32_t)(x))) +#define be32_to_cpu(x) (__swab32((u32_t)(x))) +#define cpu_to_be16(x) (__swab16((u16_t)(x))) +#define be16_to_cpu(x) (__swab16((u16_t)(x))) +#endif + +#endif /* __BYTEORDER_H__ */ diff --git a/include/arch/endian.h b/board/100ask-t113i/load_c906/c906_firmware/include/endian.h similarity index 55% rename from include/arch/endian.h rename to board/100ask-t113i/load_c906/c906_firmware/include/endian.h index da89a009..cb292519 100644 --- a/include/arch/endian.h +++ b/board/100ask-t113i/load_c906/c906_firmware/include/endian.h @@ -1,18 +1,8 @@ -/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef __RISCV64_ENDIAN_H__ +#define __RISCV64_ENDIAN_H__ -#ifndef __ARM32_ENDIAN_H__ -#define __ARM32_ENDIAN_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN (0x1234) -#endif -#ifndef BIG_ENDIAN #define BIG_ENDIAN (0x4321) -#endif #if (!defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)) #define __LITTLE_ENDIAN @@ -26,8 +16,4 @@ extern "C" { #error "Unknown byte order!" #endif -#ifdef __cplusplus -} -#endif - -#endif /* __ARM32_ENDIAN_H__ */ +#endif /* __RISCV64_ENDIAN_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/io.h b/board/100ask-t113i/load_c906/c906_firmware/include/io.h new file mode 100644 index 00000000..734f4503 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/io.h @@ -0,0 +1,38 @@ +#ifndef __IO_H__ +#define __IO_H__ + +#include + +static inline u8_t read8(virtual_addr_t addr) { + return (*((volatile u8_t *)(addr))); +} + +static inline u16_t read16(virtual_addr_t addr) { + return (*((volatile u16_t *)(addr))); +} + +static inline u32_t read32(virtual_addr_t addr) { + return (*((volatile u32_t *)(addr))); +} + +static inline u64_t read64(virtual_addr_t addr) { + return (*((volatile u64_t *)(addr))); +} + +static inline void write8(virtual_addr_t addr, u8_t value) { + *((volatile u8_t *)(addr)) = value; +} + +static inline void write16(virtual_addr_t addr, u16_t value) { + *((volatile u16_t *)(addr)) = value; +} + +static inline void write32(virtual_addr_t addr, u32_t value) { + *((volatile u32_t *)(addr)) = value; +} + +static inline void write64(virtual_addr_t addr, u64_t value) { + *((volatile u64_t *)(addr)) = value; +} + +#endif /* __IO_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/linkage.h b/board/100ask-t113i/load_c906/c906_firmware/include/linkage.h new file mode 100644 index 00000000..c982b6f9 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/linkage.h @@ -0,0 +1,24 @@ +#ifndef __RISCV64_LINKAGE_H__ +#define __RISCV64_LINKAGE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if __riscv_xlen == 64 +#define LREG ld +#define SREG sd +#define REGSZ 8 +#define RVPTR .dword +#elif __riscv_xlen == 32 +#define LREG lw +#define SREG sw +#define REGSZ 4 +#define RVPTR .word +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __RISCV64_LINKAGE_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/riscv64.h b/board/100ask-t113i/load_c906/c906_firmware/include/riscv64.h new file mode 100644 index 00000000..b6bbce8b --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/riscv64.h @@ -0,0 +1,45 @@ +#ifndef __RISCV64_H__ +#define __RISCV64_H__ + +#define MSTATUS_UIE (1 << 0) +#define MSTATUS_SIE (1 << 1) +#define MSTATUS_MIE (1 << 3) +#define MSTATUS_UPIE (1 << 4) +#define MSTATUS_SPIE (1 << 5) +#define MSTATUS_MPIE (1 << 7) +#define MSTATUS_SPP (1 << 8) +#define MSTATUS_MPP (3 << 11) +#define MSTATUS_FS (3 << 13) +#define MSTATUS_XS (3 << 15) +#define MSTATUS_MPRV (1 << 17) +#define MSTATUS_SUM (1 << 18) +#define MSTATUS_MXR (1 << 19) +#define MSTATUS_TVM (1 << 20) +#define MSTATUS_TW (1 << 21) +#define MSTATUS_TSR (1 << 22) +#define MSTATUS32_SD (1 << 31) +#define MSTATUS_UXL (3ULL << 32) +#define MSTATUS_SXL (3ULL << 34) +#define MSTATUS64_SD (1ULL << 63) + +#define MIP_USIP (1 << 0) +#define MIP_SSIP (1 << 1) +#define MIP_MSIP (1 << 3) +#define MIP_UTIP (1 << 4) +#define MIP_STIP (1 << 5) +#define MIP_MTIP (1 << 7) +#define MIP_UEIP (1 << 8) +#define MIP_SEIP (1 << 9) +#define MIP_MEIP (1 << 11) + +#define MIE_USIE (1 << 0) +#define MIE_SSIE (1 << 1) +#define MIE_MSIE (1 << 3) +#define MIE_UTIE (1 << 4) +#define MIE_STIE (1 << 5) +#define MIE_MTIE (1 << 7) +#define MIE_UEIE (1 << 8) +#define MIE_SEIE (1 << 9) +#define MIE_MEIE (1 << 11) + +#endif /* __RISCV64_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/stdarg.h b/board/100ask-t113i/load_c906/c906_firmware/include/stdarg.h new file mode 100644 index 00000000..319bc5dc --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/stdarg.h @@ -0,0 +1,26 @@ +#ifndef __STDARG_H__ +#define __STDARG_H__ + +typedef __builtin_va_list va_list; + +/* + * prepare to access variable args + */ +#define va_start(v, l) __builtin_va_start(v, l) + +/* + * the caller will get the value of current argument + */ +#define va_arg(v, l) __builtin_va_arg(v, l) + +/* + * end for variable args + */ +#define va_end(v) __builtin_va_end(v) + +/* + * copy variable args + */ +#define va_copy(d, s) __builtin_va_copy(d, s) + +#endif /* __STDARG_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/stddef.h b/board/100ask-t113i/load_c906/c906_firmware/include/stddef.h new file mode 100644 index 00000000..abce307b --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/stddef.h @@ -0,0 +1,57 @@ +#ifndef __STDDEF_H__ +#define __STDDEF_H__ + +#if defined(__cplusplus) +#define NULL (0) +#else +#define NULL ((void *)0) +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 4)) +#define offsetof(type, member) __builtin_offsetof(type, member) +#else +#define offsetof(type, field) ((size_t)(&((type *)0)->field)) +#endif +#define container_of(ptr, type, member) \ + ({ \ + const typeof(((type *)0)->member) *__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); \ + }) + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) +#define likely(expr) (__builtin_expect(!!(expr), 1)) +#define unlikely(expr) (__builtin_expect(!!(expr), 0)) +#else +#define likely(expr) (!!(expr)) +#define unlikely(expr) (!!(expr)) +#endif + +#define min(a, b) \ + ({ \ + typeof(a) _amin = (a); \ + typeof(b) _bmin = (b); \ + (void)(&_amin == &_bmin); \ + _amin < _bmin ? _amin : _bmin; \ + }) +#define max(a, b) \ + ({ \ + typeof(a) _amax = (a); \ + typeof(b) _bmax = (b); \ + (void)(&_amax == &_bmax); \ + _amax > _bmax ? _amax : _bmax; \ + }) +#define clamp(v, a, b) min(max(a, v), b) + +#define ifloor(x) ((x) > 0 ? (int)(x) : (int)((x)-0.9999999999)) +#define iround(x) ((x) > 0 ? (int)((x) + 0.5) : (int)((x)-0.5)) +#define iceil(x) ((x) > 0 ? (int)((x) + 0.9999999999) : (int)(x)) +#define idiv255(x) ((((int)(x) + 1) * 257) >> 16) + +#define X(...) ("" #__VA_ARGS__ "") + +enum { + FALSE = 0, + TRUE = 1, +}; + +#endif /* __STDDEF_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/stdint.h b/board/100ask-t113i/load_c906/c906_firmware/include/stdint.h new file mode 100644 index 00000000..d698c37f --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/stdint.h @@ -0,0 +1,23 @@ +#ifndef __STDINT_H__ +#define __STDINT_H__ + +#include + +typedef s8_t int8_t; +typedef u8_t uint8_t; + +typedef s16_t int16_t; +typedef u16_t uint16_t; + +typedef s32_t int32_t; +typedef u32_t uint32_t; + +typedef s64_t int64_t; +typedef u64_t uint64_t; + +#define UINT8_MAX (0xff) +#define UINT16_MAX (0xffff) +#define UINT32_MAX (0xffffffff) +#define UINT64_MAX (0xffffffffffffffffULL) + +#endif /* __STDINT_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/string.h b/board/100ask-t113i/load_c906/c906_firmware/include/string.h new file mode 100644 index 00000000..06146db2 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/string.h @@ -0,0 +1,9 @@ +#ifndef __STRING_H__ +#define __STRING_H__ + +#include + +void *memset(void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t len); + +#endif /* __STRING_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/sys/sys-clock.h b/board/100ask-t113i/load_c906/c906_firmware/include/sys/sys-clock.h new file mode 100644 index 00000000..cae27702 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/sys/sys-clock.h @@ -0,0 +1,16 @@ +#ifndef __SYS_CLOCK_H__ +#define __SYS_CLOCK_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void sdelay(unsigned long us); + +#endif // __SYS_CLOCK_H__ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/sys/sys-uart.h b/board/100ask-t113i/load_c906/c906_firmware/include/sys/sys-uart.h new file mode 100644 index 00000000..9ba30413 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/sys/sys-uart.h @@ -0,0 +1,19 @@ +#ifndef __SYS_UART_H__ +#define __SYS_UART_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Init System UART + */ +void sys_uart_init(); + +#endif // __SYS_UART_H__ \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/types.h b/board/100ask-t113i/load_c906/c906_firmware/include/types.h new file mode 100644 index 00000000..c7c5fd44 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/types.h @@ -0,0 +1,45 @@ +#ifndef __RISCV64_TYPES_H__ +#define __RISCV64_TYPES_H__ + +typedef signed char s8_t; +typedef unsigned char u8_t; + +typedef signed short s16_t; +typedef unsigned short u16_t; + +typedef signed int s32_t; +typedef unsigned int u32_t; + +typedef signed long long s64_t; +typedef unsigned long long u64_t; + +typedef signed long long intmax_t; +typedef unsigned long long uintmax_t; + +typedef signed long long ptrdiff_t; +typedef signed long long intptr_t; +typedef unsigned long long uintptr_t; + +typedef unsigned long long size_t; +typedef signed long long ssize_t; + +typedef signed long off_t; +typedef signed long long loff_t; + +typedef signed int bool_t; +typedef unsigned long irq_flags_t; + +typedef unsigned long long virtual_addr_t; +typedef unsigned long long virtual_size_t; +typedef unsigned long long physical_addr_t; +typedef unsigned long long physical_size_t; + +typedef struct { + volatile int counter; +} atomic_t; + +typedef struct { + volatile int lock; +} spinlock_t; + +#endif /* __RISCV64_TYPES_H__ */ diff --git a/board/100ask-t113i/load_c906/c906_firmware/include/uart.h b/board/100ask-t113i/load_c906/c906_firmware/include/uart.h new file mode 100644 index 00000000..cdab1869 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/include/uart.h @@ -0,0 +1,6 @@ +#ifndef __UART_H__ +#define __UART_H__ + +int sys_uart_printf(const char * fmt, ...); + +#endif // __UART_H__ \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/lib/CMakeLists.txt b/board/100ask-t113i/load_c906/c906_firmware/lib/CMakeLists.txt new file mode 100644 index 00000000..0bf8fe95 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/lib/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(libstring + memcpy.S + memset.S +) \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/lib/memcpy.S b/board/100ask-t113i/load_c906/c906_firmware/lib/memcpy.S new file mode 100644 index 00000000..34a359ce --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/lib/memcpy.S @@ -0,0 +1,79 @@ +#include + + .global memcpy + .type memcpy, %function + .align 3 +memcpy: + move t6, a0 + sltiu a3, a2, 128 + bnez a3, 4f + andi a3, t6, REGSZ - 1 + andi a4, a1, REGSZ - 1 + bne a3, a4, 4f + beqz a3, 2f + andi a3, a1, ~(REGSZ - 1) + addi a3, a3, REGSZ + sub a4, a3, a1 +1: lb a5, 0(a1) + addi a1, a1, 1 + sb a5, 0(t6) + addi t6, t6, 1 + bltu a1, a3, 1b + sub a2, a2, a4 +2: andi a4, a2, ~((16 * REGSZ) - 1) + beqz a4, 4f + add a3, a1, a4 +3: LREG a4, 0(a1) + LREG a5, REGSZ(a1) + LREG a6, 2 * REGSZ(a1) + LREG a7, 3 * REGSZ(a1) + LREG t0, 4 * REGSZ(a1) + LREG t1, 5 * REGSZ(a1) + LREG t2, 6 * REGSZ(a1) + LREG t3, 7 * REGSZ(a1) + LREG t4, 8 * REGSZ(a1) + LREG t5, 9 * REGSZ(a1) + SREG a4, 0(t6) + SREG a5, REGSZ(t6) + SREG a6, 2 * REGSZ(t6) + SREG a7, 3 * REGSZ(t6) + SREG t0, 4 * REGSZ(t6) + SREG t1, 5 * REGSZ(t6) + SREG t2, 6 * REGSZ(t6) + SREG t3, 7 * REGSZ(t6) + SREG t4, 8 * REGSZ(t6) + SREG t5, 9 * REGSZ(t6) + LREG a4, 10 * REGSZ(a1) + LREG a5, 11 * REGSZ(a1) + LREG a6, 12 * REGSZ(a1) + LREG a7, 13 * REGSZ(a1) + LREG t0, 14 * REGSZ(a1) + LREG t1, 15 * REGSZ(a1) + addi a1, a1, 16 * REGSZ + SREG a4, 10 * REGSZ(t6) + SREG a5, 11 * REGSZ(t6) + SREG a6, 12 * REGSZ(t6) + SREG a7, 13 * REGSZ(t6) + SREG t0, 14 * REGSZ(t6) + SREG t1, 15 * REGSZ(t6) + addi t6, t6, 16 * REGSZ + bltu a1, a3, 3b + andi a2, a2, (16 * REGSZ) - 1 +4: beqz a2, 6f + add a3, a1, a2 + or a5, a1, t6 + or a5, a5, a3 + andi a5, a5, 3 + bnez a5, 5f +7: lw a4, 0(a1) + addi a1, a1, 4 + sw a4, 0(t6) + addi t6, t6, 4 + bltu a1, a3, 7b + ret +5: lb a4, 0(a1) + addi a1, a1, 1 + sb a4, 0(t6) + addi t6, t6, 1 + bltu a1, a3, 5b +6: ret diff --git a/board/100ask-t113i/load_c906/c906_firmware/lib/memset.S b/board/100ask-t113i/load_c906/c906_firmware/lib/memset.S new file mode 100644 index 00000000..902b081c --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/lib/memset.S @@ -0,0 +1,80 @@ +#include + + .global memset + .type memset, %function + .align 3 +memset: + move t0, a0 + sltiu a3, a2, 16 + bnez a3, 4f + addi a3, t0, REGSZ - 1 + andi a3, a3, ~(REGSZ - 1) + beq a3, t0, 2f + sub a4, a3, t0 +1: sb a1, 0(t0) + addi t0, t0, 1 + bltu t0, a3, 1b + sub a2, a2, a4 +2: andi a1, a1, 0xff + slli a3, a1, 8 + or a1, a3, a1 + slli a3, a1, 16 + or a1, a3, a1 +#if __riscv_xlen == 64 + slli a3, a1, 32 + or a1, a3, a1 +#endif + andi a4, a2, ~(REGSZ - 1) + add a3, t0, a4 + andi a4, a4, 31 * REGSZ + beqz a4, 3f + neg a4, a4 + addi a4, a4, 32 * REGSZ + sub t0, t0, a4 + la a5, 3f +#if __riscv_xlen == 64 + srli a4, a4, 1 +#endif + add a5, a5, a4 + jr a5 +3: SREG a1, 0(t0) + SREG a1, REGSZ(t0) + SREG a1, 2 * REGSZ(t0) + SREG a1, 3 * REGSZ(t0) + SREG a1, 4 * REGSZ(t0) + SREG a1, 5 * REGSZ(t0) + SREG a1, 6 * REGSZ(t0) + SREG a1, 7 * REGSZ(t0) + SREG a1, 8 * REGSZ(t0) + SREG a1, 9 * REGSZ(t0) + SREG a1, 10 * REGSZ(t0) + SREG a1, 11 * REGSZ(t0) + SREG a1, 12 * REGSZ(t0) + SREG a1, 13 * REGSZ(t0) + SREG a1, 14 * REGSZ(t0) + SREG a1, 15 * REGSZ(t0) + SREG a1, 16 * REGSZ(t0) + SREG a1, 17 * REGSZ(t0) + SREG a1, 18 * REGSZ(t0) + SREG a1, 19 * REGSZ(t0) + SREG a1, 20 * REGSZ(t0) + SREG a1, 21 * REGSZ(t0) + SREG a1, 22 * REGSZ(t0) + SREG a1, 23 * REGSZ(t0) + SREG a1, 24 * REGSZ(t0) + SREG a1, 25 * REGSZ(t0) + SREG a1, 26 * REGSZ(t0) + SREG a1, 27 * REGSZ(t0) + SREG a1, 28 * REGSZ(t0) + SREG a1, 29 * REGSZ(t0) + SREG a1, 30 * REGSZ(t0) + SREG a1, 31 * REGSZ(t0) + addi t0, t0, 32 * REGSZ + bltu t0, a3, 3b + andi a2, a2, REGSZ - 1 +4: beqz a2, 6f + add a3, t0, a2 +5: sb a1, 0(t0) + addi t0, t0, 1 + bltu t0, a3, 5b +6: ret diff --git a/board/100ask-t113i/load_c906/c906_firmware/link.ld b/board/100ask-t113i/load_c906/c906_firmware/link.ld new file mode 100644 index 00000000..01676665 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/link.ld @@ -0,0 +1,81 @@ +OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(_start) + +STACK_SIZE = 0x400; + +MEMORY +{ + ram : org = 0x41000000, len = 0x00008000 /* 32KB */ +} + +SECTIONS +{ + .text : + { + PROVIDE(__image_start = .); + PROVIDE(__text_start = .); + *(.text*) + *(.iplt) + *(.note.gnu.build-id) + PROVIDE(__text_end = .); + } > ram + + .ksymtab ALIGN(16) : + { + PROVIDE(__ksymtab_start = .); + KEEP(*(.ksymtab.text)) + PROVIDE(__ksymtab_end = .); + } > ram + + .romdisk ALIGN(8) : + { + PROVIDE(__romdisk_start = .); + KEEP(*(.romdisk)) + PROVIDE(__romdisk_end = .); + } > ram + + .rodata ALIGN(8) : + { + PROVIDE(__rodata_start = .); + *(.rodata*) + *(.srodata*) + PROVIDE(__rodata_end = .); + } > ram + + .data ALIGN(8) : + { + PROVIDE(__data_start = .); + PROVIDE(__global_pointer$ = . + 0x800); + *(.sdata*) + *(.data*) + . = ALIGN(8); + PROVIDE(__data_end = .); + PROVIDE(__image_end = .); + } > ram + + .bss ALIGN(8) (NOLOAD) : + { + PROVIDE(__bss_start = .); + *(.bss*) + *(.sbss*) + *(COMMON) + . = ALIGN(8); + PROVIDE(__bss_end = .); + } > ram + + .stack ALIGN(16) (NOLOAD) : + { + PROVIDE(__stack_start = .); + . += STACK_SIZE; + . = ALIGN(16); + PROVIDE(__stack_end = .); + } > ram + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/board/100ask-t113i/load_c906/c906_firmware/src/CMakeLists.txt b/board/100ask-t113i/load_c906/c906_firmware/src/CMakeLists.txt new file mode 100644 index 00000000..80c64558 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/src/CMakeLists.txt @@ -0,0 +1,10 @@ +add_subdirectory(sys) + +add_executable(c906.elf + start.S + main.c + uart.c +) + +set_target_properties(c906.elf PROPERTIES LINK_DEPENDS "${LINK_SCRIPT}") +target_link_libraries(c906.elf PRIVATE libstring libsys) diff --git a/board/100ask-t113i/load_c906/c906_firmware/src/main.c b/board/100ask-t113i/load_c906/c906_firmware/src/main.c new file mode 100644 index 00000000..56e94dee --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/src/main.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OPENSBI_FW_TEXT_START 0x41fc0000 + +void jmp_opensbi(uint32_t opensbi_base) { + asm volatile("jr a0"); +__LOOP: + asm volatile("WFI"); + goto __LOOP; +} + +int main() { + int i = 0; + + sys_uart_init();// init UART0 + + sys_uart_printf(" _____ _ _____ _ _ _____ ___ ___ ___ \r\n"); + sys_uart_printf("| __|_ _| |_ ___ ___| | |_| |_ | | . | | _|\r\n"); + sys_uart_printf("|__ | | | _| -_| _| -| | _| | --|_ | | | . |\r\n"); + sys_uart_printf("|_____|_ |_| |___|_| |__|__|_|_| |_____|___|___|___|\r\n"); + sys_uart_printf(" |___| \r\n\r\n"); + + sys_uart_printf("This Message is from C906 RISC-V Core\r\n"); + + sys_uart_printf("Countting to 9\r\nCount: "); + + for (i = 0; i < 9; i++) { + sys_uart_printf("%d ", i); + sdelay(100000); + } + + sys_uart_printf("Jump to OpenSBI...\r\n"); + + jmp_opensbi(OPENSBI_FW_TEXT_START); +} diff --git a/board/100ask-t113i/load_c906/c906_firmware/src/start.S b/board/100ask-t113i/load_c906/c906_firmware/src/start.S new file mode 100644 index 00000000..27c4e426 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/src/start.S @@ -0,0 +1,27 @@ +#include +#include + + .global _start +_start: + li t1, 0x1 << 22 + csrs mxstatus, t1 + li t1, 0x30013 + csrs mcor, t1 + j reset + +reset: + addi sp, sp, -32 + sd s0, 8(sp) + sd s1, 16(sp) + sd ra, 24(sp) + mv s0, a0 + + li t0, 0x07090108 + sw zero, (t0) + jal main + + ld ra, 24(sp) + ld s0, 8(sp) + ld s1, 16(sp) + addi sp, sp, 32 + ret diff --git a/board/100ask-t113i/load_c906/c906_firmware/src/sys/CMakeLists.txt b/board/100ask-t113i/load_c906/c906_firmware/src/sys/CMakeLists.txt new file mode 100644 index 00000000..36434856 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/src/sys/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(libsys + sys-clock.c + sys-uart.c +) + +target_link_libraries(libsys PRIVATE libstring) \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/src/sys/sys-clock.c b/board/100ask-t113i/load_c906/c906_firmware/src/sys/sys-clock.c new file mode 100644 index 00000000..401f3b52 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/src/sys/sys-clock.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline uint64_t counter() { + uint64_t cnt; + __asm__ __volatile__("csrr %0, time\n" : "=r"(cnt)::"memory"); + return cnt; +} + +void sdelay(unsigned long us) { + uint64_t t1 = counter(); + uint64_t t2 = t1 + us * 24; + do { + t1 = counter(); + } while (t2 >= t1); +} diff --git a/board/100ask-t113i/load_c906/c906_firmware/src/sys/sys-uart.c b/board/100ask-t113i/load_c906/c906_firmware/src/sys/sys-uart.c new file mode 100644 index 00000000..5e35d102 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/src/sys/sys-uart.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void sys_uart_init() { + virtual_addr_t addr; + u32_t val; + + /* Config GPIOE2 and GPIOE3 to txd0 and rxd0 */ + addr = 0x020000c0 + 0x0; + val = read32(addr); + val &= ~(0xf << ((2 & 0x7) << 2)); + val |= ((0x6 & 0xf) << ((2 & 0x7) << 2)); + write32(addr, val); + + val = read32(addr); + val &= ~(0xf << ((3 & 0x7) << 2)); + val |= ((0x6 & 0xf) << ((3 & 0x7) << 2)); + write32(addr, val); + + /* Open the clock gate for uart0 */ + addr = 0x0200190c; + val = read32(addr); + val |= 1 << 0; + write32(addr, val); + + /* Deassert uart0 reset */ + addr = 0x0200190c; + val = read32(addr); + val |= 1 << 16; + write32(addr, val); + + /* Config uart0 to 115200-8-1-0 */ + addr = UART0_BASE_ADDR; + write32(addr + 0x04, 0x0); + write32(addr + 0x08, 0xf7); + write32(addr + 0x10, 0x0); + val = read32(addr + 0x0c); + val |= (1 << 7); + write32(addr + 0x0c, val); + write32(addr + 0x00, 0xd & 0xff); + write32(addr + 0x04, (0xd >> 8) & 0xff); + val = read32(addr + 0x0c); + val &= ~(1 << 7); + write32(addr + 0x0c, val); + val = read32(addr + 0x0c); + val &= ~0x1f; + val |= (0x3 << 0) | (0 << 2) | (0x0 << 3); + write32(addr + 0x0c, val); +} \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/c906_firmware/src/uart.c b/board/100ask-t113i/load_c906/c906_firmware/src/uart.c new file mode 100644 index 00000000..4d200262 --- /dev/null +++ b/board/100ask-t113i/load_c906/c906_firmware/src/uart.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +void sys_uart_putc(char c) { + virtual_addr_t addr = UART0_BASE_ADDR; + + while ((read32(addr + 0x7c) & (0x1 << 1)) == 0) + ; + write32(addr + 0x00, c); +} + +static int v_printf_str_to_num(const char *fmt, int *num) { + const char *p; + int res, d, isd; + + res = 0; + for (p = fmt; *fmt != '\0'; p++) { + isd = (*p >= '0' && *p <= '9'); + if (!isd) + break; + d = *p - '0'; + res *= 10; + res += d; + } + *num = res; + return ((int) (p - fmt)); +} + +static void v_printf_num_to_str(uint32_t a, int ish, int pl, int pc) { + char buf[32]; + uint32_t base; + int idx, i, t; + + for (i = 0; i < sizeof(buf); i++) + buf[i] = pc; + base = 10; + if (ish) + base = 16; + + idx = 0; + do { + t = a % base; + if (t >= 10) + buf[idx] = t - 10 + 'a'; + else + buf[idx] = t + '0'; + a /= base; + idx++; + } while (a > 0); + + if (pl > 0) { + if (pl >= sizeof(buf)) + pl = sizeof(buf) - 1; + if (idx < pl) + idx = pl; + } + buf[idx] = '\0'; + + for (i = idx - 1; i >= 0; i--) + sys_uart_putc(buf[i]); +} + +static int v_printf(const char *fmt, va_list va) { + const char *p, *q; + int f, c, vai, pl, pc, i; + unsigned char t; + + pc = ' '; + for (p = fmt; *p != '\0'; p++) { + f = 0; + pl = 0; + c = *p; + q = p; + if (*p == '%') { + q = p; + p++; + if (*p >= '0' && *p <= '9') + p += v_printf_str_to_num(p, &pl); + f = *p; + } + if ((f == 'd') || (f == 'x')) { + vai = va_arg(va, int); + v_printf_num_to_str(vai, f == 'x', pl, pc); + } else { + for (i = 0; i < (p - q); i++) + sys_uart_putc(q[i]); + t = (unsigned char) (f != 0 ? f : c); + sys_uart_putc(t); + } + } + return 0; +} + +int sys_uart_printf(const char *fmt, ...) { + va_list va; + + va_start(va, fmt); + v_printf(fmt, va); + va_end(va); + return 0; +} diff --git a/board/100ask-t113i/load_c906/main.c b/board/100ask-t113i/load_c906/main.c new file mode 100644 index 00000000..1f65fcca --- /dev/null +++ b/board/100ask-t113i/load_c906/main.c @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" + +#include "elf_loader.h" +#include "ff.h" + +#define CONFIG_RISCV_ELF_FILENAME "c906.elf" +#define CONFIG_RISCV_ELF_LOADADDR (0x45000000) + +#define CONFIG_RISCV_OPENSBI_FILENAME "fw_jump.bin" +#define CONFIG_RISCV_OPENSBI_LOADADDR (0x41fc0000) + +#define CONFIG_RISCV_UBOOT_FILENAME "u-boot.bin" +#define CONFIG_RISCV_UBOOT_LOADADDR (0x42000000) + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +extern sunxi_serial_t uart_dbg; + +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; + +#define FILENAME_MAX_LEN 64 +typedef struct { + unsigned char *dest; + char filename[FILENAME_MAX_LEN]; + + unsigned char *sbi_dest; + char sbi_filename[FILENAME_MAX_LEN]; + + unsigned char *uboot_dest; + char uboot_filename[FILENAME_MAX_LEN]; +} image_info_t; + +image_info_t image; + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, + "FATFS: open, filename: [%s]: error %d\n", filename, + fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, + CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, (unsigned int) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->sbi_filename, (unsigned int) image->sbi_dest); + ret = fatfs_loadimage(image->sbi_filename, image->sbi_dest); + if (ret) + return ret; + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->uboot_filename, (unsigned int) image->uboot_dest); + ret = fatfs_loadimage(image->uboot_filename, image->uboot_dest); + if (ret) + return ret; + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + +int main(void) { + sunxi_serial_init(&uart_dbg); // Initialize the serial interface for debugging + + show_banner(); // Display a banner + + sunxi_clk_init(); // Initialize clock configurations + + sunxi_dram_init(&dram_para); // Initialize DRAM parameters + + sunxi_clk_dump(); // Dump clock information + + memset(&image, 0, sizeof(image_info_t)); // Clear the image structure + + // Set destination addresses for different images + image.dest = (uint8_t *) CONFIG_RISCV_ELF_LOADADDR; + image.sbi_dest = (uint8_t *) CONFIG_RISCV_OPENSBI_LOADADDR; + image.uboot_dest = (uint8_t *) CONFIG_RISCV_UBOOT_LOADADDR; + + // Set filenames for different images + strcpy(image.filename, CONFIG_RISCV_ELF_FILENAME); + strcpy(image.sbi_filename, CONFIG_RISCV_OPENSBI_FILENAME); + strcpy(image.uboot_filename, CONFIG_RISCV_UBOOT_FILENAME); + + // Initialize SDHCI controller + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + return 0; + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + + // Initialize SD/MMC card + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + return 0; + } + + // Load image from SD card + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + return 0; + } + + sunxi_c906_clock_reset(); // Reset C906 clock + + // Get entry address of RISC-V ELF + uint32_t elf_run_addr = elf64_get_entry_addr((phys_addr_t) image.dest); + printk(LOG_LEVEL_INFO, "RISC-V ELF run addr: 0x%08x\n", elf_run_addr); + + // Load RISC-V ELF image + if (load_elf64_image((phys_addr_t) image.dest)) { + printk(LOG_LEVEL_ERROR, "RISC-V ELF load FAIL\n"); + } + + printk(LOG_LEVEL_INFO, "RISC-V C906 Core now Running... \n"); + + mdelay(100); // Delay for 100 milliseconds + + sunxi_c906_clock_init(elf_run_addr); // Initialize C906 clock with entry address + + abort(); // Abort A7 execution, loop forever + + jmp_to_fel(); // Jump to FEL mode + + return 0; +} \ No newline at end of file diff --git a/board/100ask-t113i/load_c906/opensbi_bin/fw_jump.bin b/board/100ask-t113i/load_c906/opensbi_bin/fw_jump.bin new file mode 100644 index 00000000..6242c87a Binary files /dev/null and b/board/100ask-t113i/load_c906/opensbi_bin/fw_jump.bin differ diff --git a/board/100ask-t113i/load_c906/uboot_bin/u-boot.bin b/board/100ask-t113i/load_c906/uboot_bin/u-boot.bin new file mode 100644 index 00000000..6aa198cc Binary files /dev/null and b/board/100ask-t113i/load_c906/uboot_bin/u-boot.bin differ diff --git a/app/common/start.S b/board/100ask-t113i/start.S similarity index 100% rename from app/common/start.S rename to board/100ask-t113i/start.S diff --git a/board/100ask-t113i/sys_info/CMakeLists.txt b/board/100ask-t113i/sys_info/CMakeLists.txt new file mode 100644 index 00000000..c559a1ab --- /dev/null +++ b/board/100ask-t113i/sys_info/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(sys_info + main.c +) \ No newline at end of file diff --git a/board/100ask-t113i/sys_info/main.c b/board/100ask-t113i/sys_info/main.c new file mode 100644 index 00000000..0d5d8c90 --- /dev/null +++ b/board/100ask-t113i/sys_info/main.c @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +extern sunxi_serial_t uart_dbg; +extern dram_para_t dram_para; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + sunxi_dram_init(&dram_para); + + printk(LOG_LEVEL_INFO, "Hello World!\n"); + + dump_efuse(); + + sunxi_clk_reset(); + + clean_syterkit_data(); + + jmp_to_fel(); + + return 0; +} \ No newline at end of file diff --git a/app/syter_boot/CMakeLists.txt b/board/100ask-t113i/syter_boot/CMakeLists.txt similarity index 100% rename from app/syter_boot/CMakeLists.txt rename to board/100ask-t113i/syter_boot/CMakeLists.txt diff --git a/board/100ask-t113i/syter_boot/main.c b/board/100ask-t113i/syter_boot/main.c new file mode 100644 index 00000000..0b3e6593 --- /dev/null +++ b/board/100ask-t113i/syter_boot/main.c @@ -0,0 +1,692 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-rtc.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" + +#include "fdt_wrapper.h" +#include "ff.h" +#include "libfdt.h" +#include "uart.h" + +#define CONFIG_KERNEL_FILENAME "zImage" +#define CONFIG_DTB_FILENAME "sunxi.dtb" +#define CONFIG_CONFIG_FILENAME "config.txt" + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +#define CONFIG_DTB_LOAD_ADDR (0x41008000) +#define CONFIG_KERNEL_LOAD_ADDR (0x41800000) +#define CONFIG_CONFIG_LOAD_ADDR (0x40008000) +#define CONFIG_HEAP_BASE (0x40800000) +#define CONFIG_HEAP_SIZE (16 * 1024 * 1024) + +#define CONFIG_DEFAULT_BOOTDELAY 5 + +#define FILENAME_MAX_LEN 64 +typedef struct { + uint8_t *dest; + + uint8_t *of_dest; + + uint8_t *config_dest; + uint8_t is_config; + + char filename[FILENAME_MAX_LEN]; + + char of_filename[FILENAME_MAX_LEN]; + + char config_filename[FILENAME_MAX_LEN]; +} image_info_t; + +#define MAX_SECTION_LEN 16 +#define MAX_KEY_LEN 16 +#define MAX_VALUE_LEN 512 +#define CONFIG_MAX_ENTRY 3 + +typedef struct { + char section[MAX_SECTION_LEN]; + char key[MAX_KEY_LEN]; + char value[MAX_VALUE_LEN]; +} IniEntry; + +IniEntry entries[CONFIG_MAX_ENTRY]; + +/* Linux zImage Header */ +#define LINUX_ZIMAGE_MAGIC 0x016f2818 +typedef struct { + uint32_t code[9]; + uint32_t magic; + uint32_t start; + uint32_t end; +} linux_zimage_header_t; + +extern sunxi_serial_t uart_dbg; + +extern sunxi_spi_t sunxi_spi0; + +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; + +image_info_t image; + +uint32_t code[9]; +uint32_t magic; +uint32_t start; +uint32_t end; + +static int boot_image_setup(uint8_t *addr, uint32_t *entry) { + linux_zimage_header_t *zimage_header = (linux_zimage_header_t *) addr; + + printk(LOG_LEVEL_INFO, "Linux zImage->code = 0x"); + for (int i = 0; i < 9; i++) + printk(LOG_LEVEL_MUTE, "%x", code[i]); + + printk(LOG_LEVEL_MUTE, "\n"); + printk(LOG_LEVEL_DEBUG, "Linux zImage->magic = 0x%x\n", + zimage_header->magic); + printk(LOG_LEVEL_DEBUG, "Linux zImage->start = 0x%x\n", + (uint32_t) addr + zimage_header->start); + printk(LOG_LEVEL_DEBUG, "Linux zImage->end = 0x%x\n", + (uint32_t) addr + zimage_header->end); + + if (zimage_header->magic == LINUX_ZIMAGE_MAGIC) { + *entry = ((uint32_t) addr + zimage_header->start); + return 0; + } + + printk(LOG_LEVEL_ERROR, "unsupported kernel image\n"); + + return -1; +} + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret = 1; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: open, filename: [%s]: error %d\n", filename, fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_INFO, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + /* load DTB */ + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->of_filename, (uint32_t) image->of_dest); + ret = fatfs_loadimage(image->of_filename, image->of_dest); + if (ret) + return ret; + + /* load Kernel */ + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, (uint32_t) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + /* load config */ + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->config_filename, (uint32_t) image->config_dest); + ret = fatfs_loadimage(image->config_filename, image->config_dest); + if (ret) { + printk(LOG_LEVEL_INFO, "CONFIG: Cannot find config file, Using default config.\n"); + image->is_config = 0; + } else { + image->is_config = 1; + } + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_INFO, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + +static void trim(char *str) { + int len = strlen(str); + while (len > 0 && (str[len - 1] == ' ' || str[len - 1] == '\n' || str[len - 1] == '\r')) { + str[--len] = '\0'; + } + while (*str && (*str == ' ' || *str == '\n' || *str == '\r')) { + ++str; + --len; + } +} + +static int parse_ini_data(const char *data, size_t size, IniEntry *entries, int max_entries) { + char line[MAX_VALUE_LEN]; + char current_section[MAX_SECTION_LEN] = ""; + int entry_count = 0; + + const char *p = data; + const char *end = data + size; + + while (p < end) { + /* Read a line of data */ + size_t len = 0; + while (p + len < end && *(p + len) != '\n') { + ++len; + } + if (p + len < end && *(p + len) == '\n') { + ++len; + } + if (len > 0) { + strncpy(line, p, len); + line[len] = '\0'; + p += len; + + trim(line); + + /* Ignore empty lines and comments */ + if (line[0] == '\0' || line[0] == ';' || line[0] == '#') { + continue; + } + + /* Parse the section name */ + if (line[0] == '[' && line[strlen(line) - 1] == ']') { + strncpy(current_section, &line[1], strlen(line) - 2); + current_section[strlen(line) - 2] = '\0'; + continue; + } + + /* Parse key-value pairs */ + char *pos = strchr(line, '='); + if (pos != NULL) { + char *key_start = line; + char *value_start = pos + 1; + *pos = '\0'; + trim(key_start); + trim(value_start); + + if (strlen(current_section) > 0 && strlen(key_start) > 0 && strlen(value_start) > 0) { + if (entry_count >= max_entries) { + printk(LOG_LEVEL_ERROR, "INI: Too many entries!\n"); + break; + } + strncpy(entries[entry_count].section, current_section, MAX_SECTION_LEN - 1); + strncpy(entries[entry_count].key, key_start, MAX_KEY_LEN - 1); + strncpy(entries[entry_count].value, value_start, MAX_VALUE_LEN - 1); + ++entry_count; + } + } + } + } + + return entry_count; +} + +static const char *find_entry_value(const IniEntry *entries, int entry_count, const char *section, const char *key) { + for (int i = 0; i < entry_count; ++i) { + if (strcmp(entries[i].section, section) == 0 && strcmp(entries[i].key, key) == 0) { + return entries[i].value; + } + } + return NULL; +} + +static int update_bootargs_from_config(uint64_t dram_size) { + int ret = 0; + char *bootargs_str_config = NULL; + char *mac_addr = NULL; + + /* Check if using config file, get bootargs in the config file */ + if (image.is_config) { + size_t size_a = strlen(image.config_dest); + int entry_count = parse_ini_data(image.config_dest, size_a, entries, CONFIG_MAX_ENTRY); + for (int i = 0; i < entry_count; ++i) { + /* Print parsed INI entries */ + printk(LOG_LEVEL_DEBUG, "INI: [%s] %s = %s\n", entries[i].section, entries[i].key, entries[i].value); + } + bootargs_str_config = find_entry_value(entries, entry_count, "configs", "bootargs"); + mac_addr = find_entry_value(entries, entry_count, "configs", "mac_addr"); + } + + /* Force image.dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + /* Check if DTB header is valid */ + if ((ret = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(ret)); + return -1; + } + + /* Get the total size of DTB */ + uint32_t size = fdt_totalsize(image.of_dest); + printk(LOG_LEVEL_DEBUG, "%s: FDT Size = %d\n", image.of_filename, size); + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + + /* If config file read fail or not using */ + if (bootargs_str_config == NULL) { + printk(LOG_LEVEL_WARNING, "INI: Cannot parse bootargs, using default bootargs in DTB.\n"); + bootargs_str_config = bootargs_str; + } + + /* update mac address of board */ + if (mac_addr != NULL) { + strcat(bootargs_str_config, " mac_addr="); + strcat(bootargs_str_config, mac_addr); + } + + /* Add dram size to dtb */ + char dram_size_str[8]; + strcat(bootargs_str_config, " mem="); + strcat(bootargs_str_config, ltoa(dram_size, dram_size_str, 10)); + strcat(bootargs_str_config, "M"); + + /* Set bootargs based on the configuration file */ + printk(LOG_LEVEL_DEBUG, "INI: Set bootargs to %s\n", bootargs_str_config); + +_add_dts_size: + /* Modify bootargs string */ + ret = fdt_setprop(image.of_dest, bootargs_node, "bootargs", bootargs_str_config, strlen(bootargs_str_config) + 1); + if (ret == -FDT_ERR_NOSPACE) { + printk(LOG_LEVEL_DEBUG, "FDT: FDT_ERR_NOSPACE, Size = %d, Increase Size = %d\n", size, 512); + ret = fdt_increase_size(image.of_dest, 512); + if (!ret) + goto _add_dts_size; + else + goto _err_size; + } else if (ret < 0) { + printk(LOG_LEVEL_ERROR, "Can't change bootargs node: %s\n", fdt_strerror(ret)); + return -1; + } + + /* Get the total size of DTB */ + printk(LOG_LEVEL_DEBUG, "Modify FDT Size = %d\n", fdt_totalsize(image.of_dest)); + + if (ret < 0) { + printk(LOG_LEVEL_ERROR, "libfdt fdt_setprop() error: %s\n", fdt_strerror(ret)); + return -1; + } + + return 0; +_err_size: + printk(LOG_LEVEL_ERROR, "DTB: Can't increase blob size: %s\n", fdt_strerror(ret)); + return -1; +} + +static int abortboot_single_key(int bootdelay) { + int abort = 0; + unsigned long ts; + + printk(LOG_LEVEL_INFO, "Hit any key to stop autoboot: %2d ", bootdelay); + + /* Check if key already pressed */ + if (tstc()) { /* we got a key press */ + uart_getchar(); /* consume input */ + printk(LOG_LEVEL_MUTE, "\b\b\b%2d", bootdelay); + abort = 1; /* don't auto boot */ + } + + while ((bootdelay > 0) && (!abort)) { + --bootdelay; + /* delay 1000 ms */ + ts = time_ms(); + do { + if (tstc()) { /* we got a key press */ + abort = 1; /* don't auto boot */ + break; + } + udelay(10000); + } while (!abort && time_ms() - ts < 1000); + printk(LOG_LEVEL_MUTE, "\b\b\b%2d ", bootdelay); + } + uart_putchar('\n'); + return abort; +} + +msh_declare_command(bootargs); +msh_define_help(bootargs, "get/set bootargs for kernel", + "Usage: bootargs set \"bootargs\" - set new bootargs for zImage\n" + " bootargs get - get current bootargs\n"); +int cmd_bootargs(int argc, const char **argv) { + int err = 0; + + if (argc < 2) { + uart_puts(cmd_bootargs_usage); + return 0; + } + + if (strncmp(argv[1], "set", 3) == 0) { + if (argc != 3) { + uart_puts(cmd_bootargs_usage); + return 0; + } + /* Force image.of_dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + return 0; + } + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB OLD bootargs = \"%s\"\n", bootargs_str); + + /* New bootargs string */ + char *new_bootargs_str = argv[2]; + printk(LOG_LEVEL_MUTE, "Now set bootargs to \"%s\"\n", new_bootargs_str); + + _add_dts_size: + /* Modify bootargs string */ + err = fdt_setprop(image.of_dest, bootargs_node, "bootargs", new_bootargs_str, strlen(new_bootargs_str) + 1); + if (err == -FDT_ERR_NOSPACE) { + printk(LOG_LEVEL_DEBUG, "FDT: FDT_ERR_NOSPACE, Increase Size = %d\n", 512); + err = fdt_increase_size(image.of_dest, 512); + if (!err) + goto _add_dts_size; + else + goto _err_size; + } else if (err < 0) { + printk(LOG_LEVEL_ERROR, "Can't change bootargs node: %s\n", fdt_strerror(err)); + abort(); + } + + /* Get updated bootargs string */ + char *updated_bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB NEW bootargs = \"%s\"\n", updated_bootargs_str); + } else if (strncmp(argv[1], "get", 3) == 0) { + /* Force image.of_dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + int err = 0; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + return 0; + } + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB bootargs = \"%s\"\n", bootargs_str); + } else { + uart_puts(cmd_bootargs_usage); + } + return 0; + +_err_size: + printk(LOG_LEVEL_ERROR, "DTB: Can't increase blob size: %s\n", fdt_strerror(err)); + abort(); +} + +msh_declare_command(reload); +msh_define_help(reload, "rescan TF Card and reload DTB, Kernel zImage", "Usage: reload\n"); +int cmd_reload(int argc, const char **argv) { + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + return 0; + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + return 0; + } + return 0; +} + +msh_declare_command(print); +msh_define_help(print, "print out env config", "Usage: print\n"); +int cmd_print(int argc, const char **argv) { + if (image.is_config) { + size_t size_a = strlen(image.config_dest); + int entry_count = parse_ini_data(image.config_dest, size_a, entries, CONFIG_MAX_ENTRY); + for (int i = 0; i < entry_count; ++i) { + /* Print parsed INI entries */ + printk(LOG_LEVEL_MUTE, "ENV: [%s] %s = %s\n", entries[i].section, entries[i].key, entries[i].value); + } + } else { + printk(LOG_LEVEL_WARNING, "ENV: Can not find env file\n"); + } + return 0; +} + +msh_declare_command(boot); +msh_define_help(boot, "boot to linux", "Usage: boot\n"); +int cmd_boot(int argc, const char **argv) { + /* Initialize variables for kernel entry point and SD card access. */ + uint32_t entry_point = 0; + void (*kernel_entry)(int zero, int arch, uint32_t params); + + /* Set up boot parameters for the kernel. */ + if (boot_image_setup((uint8_t *) image.dest, &entry_point)) { + printk(LOG_LEVEL_ERROR, "boot setup failed\n"); + abort(); + } + + /* Disable MMU, data cache, instruction cache, interrupts */ + clean_syterkit_data(); + + enable_kernel_smp(); + printk(LOG_LEVEL_INFO, "enable kernel smp ok...\n"); + + /* Debug message to indicate the kernel address that the system is jumping to. */ + printk(LOG_LEVEL_INFO, "jump to kernel address: 0x%x\n\n", image.dest); + + /* Jump to the kernel entry point. */ + kernel_entry = (void (*)(int, int, uint32_t)) entry_point; + kernel_entry(0, ~0, (uint32_t) image.of_dest); + + // if kernel boot not success, jump to fel. + jmp_to_fel(); + return 0; +} + +const msh_command_entry commands[] = { + msh_define_command(bootargs), + msh_define_command(reload), + msh_define_command(boot), + msh_define_command(print), + msh_command_end, +}; + +/* + * main function for the bootloader. Initializes and sets up the system, loads the kernel and device tree binary from + * an SD card, sets boot arguments, and boots the kernel. If the kernel fails to boot, the function jumps to FEL mode. + */ +int main(void) { + /* Initialize the debug serial interface. */ + sunxi_serial_init(&uart_dbg); + + /* Display the bootloader banner. */ + show_banner(); + + /* Initialize the system clock. */ + sunxi_clk_init(); + + /* Check rtc fel flag. if set flag, goto fel */ + if (rtc_probe_fel_flag()) { + printk(LOG_LEVEL_INFO, "RTC: get fel flag, jump to fel mode.\n"); + clean_syterkit_data(); + rtc_clear_fel_flag(); + sunxi_clk_reset(); + mdelay(100); + goto _fel; + } + + /* Initialize the DRAM and enable memory management unit (MMU). */ + uint64_t dram_size = sunxi_dram_init(&dram_para); + arm32_mmu_enable(SDRAM_BASE, dram_size); + + /* Debug message to indicate that MMU is enabled. */ + printk(LOG_LEVEL_DEBUG, "enable mmu ok\n"); + + /* Initialize the small memory allocator. */ + smalloc_init(CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE); + + /* Dump information about the system clocks. */ + sunxi_clk_dump(); + + /* Clear the image_info_t struct. */ + memset(&image, 0, sizeof(image_info_t)); + + /* Set the destination address for the device tree binary (DTB), kernel image, and configuration data. */ + image.of_dest = (uint8_t *) CONFIG_DTB_LOAD_ADDR; + image.dest = (uint8_t *) CONFIG_KERNEL_LOAD_ADDR; + image.config_dest = (uint8_t *) CONFIG_CONFIG_LOAD_ADDR; + image.is_config = 0; + + /* Copy the filenames for the DTB, kernel image, and configuration data. */ + strcpy(image.filename, CONFIG_KERNEL_FILENAME); + strcpy(image.of_filename, CONFIG_DTB_FILENAME); + strcpy(image.config_filename, CONFIG_CONFIG_FILENAME); + + /* Initialize the SD host controller. */ + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + goto _shell; + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + + /* Initialize the SD card and check if initialization is successful. */ + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: init failed\n"); + goto _shell; + } + + /* Load the DTB, kernel image, and configuration data from the SD card. */ + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: loading failed\n"); + goto _shell; + } + + /* Update boot arguments based on configuration file. */ + if (update_bootargs_from_config(dram_size)) { + goto _shell; + } + + int bootdelay = CONFIG_DEFAULT_BOOTDELAY; + + if (image.is_config) { + size_t size_a = strlen(image.config_dest); + int entry_count = parse_ini_data(image.config_dest, size_a, entries, CONFIG_MAX_ENTRY); + for (int i = 0; i < entry_count; ++i) { + /* Print parsed INI entries */ + printk(LOG_LEVEL_DEBUG, "INI: [%s] %s = %s\n", entries[i].section, entries[i].key, entries[i].value); + } + char *bootdelay_str = find_entry_value(entries, entry_count, "configs", "bootdelay"); + if (bootdelay_str != NULL) { + bootdelay = simple_atoi(bootdelay_str); + } + } + + /* Showing boot delays */ + if (abortboot_single_key(bootdelay)) { + goto _shell; + } + + cmd_boot(0, NULL); + +_shell: + syterkit_shell_attach(commands); + +_fel: + /* If the kernel boot fails, jump to FEL mode. */ + jmp_to_fel(); + + /* Return 0 to indicate successful execution. */ + return 0; +} diff --git a/board/100ask-t113s3/CMakeLists.txt b/board/100ask-t113s3/CMakeLists.txt new file mode 100644 index 00000000..27e2805d --- /dev/null +++ b/board/100ask-t113s3/CMakeLists.txt @@ -0,0 +1,7 @@ +set(APP_COMMON_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/start.S + ${CMAKE_CURRENT_SOURCE_DIR}/board.c + ${CMAKE_CURRENT_SOURCE_DIR}/eabi_compat.c +) + +add_subdirectory(hello_world) diff --git a/board/100ask-t113s3/README.md b/board/100ask-t113s3/README.md new file mode 100644 index 00000000..fc121158 --- /dev/null +++ b/board/100ask-t113s3/README.md @@ -0,0 +1,29 @@ +# SyterKit Common + +## start.S + +This code snippet is an ARM assembly language program that includes initialization settings and exception handlers. Here's a breakdown of its functionalities: + +1. Initialization Settings: It sets registers and writes specific values to configure the processor's working mode, interrupt enable, etc. + +2. Set Vector Table: It writes the address of the vector table to the Vector Base Address Register, which is used for handling exceptions and interrupts. + +3. Enable NEON/VFP Unit: It configures the processor to enable the NEON (Advanced SIMD) and VFP (Floating-Point) units. + +4. Clear BSS Section: It zeroes out variables in the BSS section. + +5. Disable Interrupts: It disables FIQ and IRQ interrupts and switches the processor to SVC32 mode. + +6. Set Timer Frequency: It sets the timer frequency to 24M. + +7. Call the main Function: It jumps to the main function to execute the main logic. + +## eabi_compat.c + +This code snippet appears to be providing implementations for the functions `abort`, `raise`, and `__aeabi_unwind_cpp_pr0`. Here's a breakdown of their functionalities: + +1. `void abort(void)`: This function creates an infinite loop, causing the program to hang indefinitely. It is typically used to indicate a critical error or unrecoverable condition in a program. + +2. `int raise(int signum)`: This function is a placeholder and always returns 0. In standard C, this function is used to raise a signal and initiate the corresponding signal handler. However, in this implementation, it does nothing and simply returns 0. + +3. `void __aeabi_unwind_cpp_pr0(void)`: This is a dummy function that serves as a placeholder to avoid linker complaints. Its purpose is to satisfy the linker when using C++ exceptions and unwinding, but it does not contain any actual functionality. diff --git a/board/100ask-t113s3/board.c b/board/100ask-t113s3/board.c new file mode 100644 index 00000000..74a4a176 --- /dev/null +++ b/board/100ask-t113s3/board.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +sunxi_serial_t uart_dbg = { + .base = SUNXI_UART3_BASE, + .id = 3, + .gpio_tx = {GPIO_PIN(GPIO_PORTB, 6), GPIO_PERIPH_MUX7}, + .gpio_rx = {GPIO_PIN(GPIO_PORTB, 7), GPIO_PERIPH_MUX7}, +}; + +sunxi_spi_t sunxi_spi0 = { + .base = SUNXI_SPI0_BASE, + .id = 0, + .clk_rate = 75 * 1000 * 1000, + .gpio_cs = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX4}, + .gpio_sck = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX4}, + .gpio_mosi = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX4}, + .gpio_miso = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX4}, + .gpio_wp = {GPIO_PIN(GPIO_PORTC, 4), GPIO_PERIPH_MUX4}, + .gpio_hold = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX4}, +}; + +sdhci_t sdhci0 = { + .name = "sdhci0", + .reg = (sdhci_reg_t *) SUNXI_SMHC0_BASE, + .voltage = MMC_VDD_27_36, + .width = MMC_BUS_WIDTH_4, + .clock = MMC_CLK_50M, + .removable = 0, + .isspi = FALSE, + .gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2}, + .gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2}, + .gpio_d0 = {GPIO_PIN(GPIO_PORTF, 1), GPIO_PERIPH_MUX2}, + .gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2}, + .gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2}, + .gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2}, +}; + +dram_para_t dram_para = { + .dram_clk = 792, + .dram_type = 3, + .dram_zq = 0x7b7bfb, + .dram_odt_en = 0x00, + .dram_para1 = 0x000010d2, + .dram_para2 = 0, + .dram_mr0 = 0x1c70, + .dram_mr1 = 0x42, + .dram_mr2 = 0x18, + .dram_mr3 = 0, + .dram_tpr0 = 0x004a2195, + .dram_tpr1 = 0x02423190, + .dram_tpr2 = 0x0008b061, + .dram_tpr3 = 0xb4787896,// unused + .dram_tpr4 = 0, + .dram_tpr5 = 0x48484848, + .dram_tpr6 = 0x00000048, + .dram_tpr7 = 0x1620121e,// unused + .dram_tpr8 = 0, + .dram_tpr9 = 0,// clock? + .dram_tpr10 = 0, + .dram_tpr11 = 0x00340000, + .dram_tpr12 = 0x00000046, + .dram_tpr13 = 0x34000100, +}; + +void clean_syterkit_data(void) { + /* Disable MMU, data cache, instruction cache, interrupts */ + arm32_mmu_disable(); + printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); + arm32_dcache_disable(); + printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); + arm32_icache_disable(); + printk(LOG_LEVEL_INFO, "disable icache ok...\n"); + arm32_interrupt_disable(); + printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); +} diff --git a/board/100ask-t113s3/eabi_compat.c b/board/100ask-t113s3/eabi_compat.c new file mode 100644 index 00000000..93303d89 --- /dev/null +++ b/board/100ask-t113s3/eabi_compat.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +void abort(void) { + while (1) + ; +} + +int raise(int signum) { + return 0; +} + +/* Dummy function to avoid linker complaints */ +void __aeabi_unwind_cpp_pr0(void) { +} \ No newline at end of file diff --git a/board/100ask-t113s3/hello_world/CMakeLists.txt b/board/100ask-t113s3/hello_world/CMakeLists.txt new file mode 100644 index 00000000..b5ce1ea5 --- /dev/null +++ b/board/100ask-t113s3/hello_world/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(helloworld + main.c +) \ No newline at end of file diff --git a/board/100ask-t113s3/hello_world/main.c b/board/100ask-t113s3/hello_world/main.c new file mode 100644 index 00000000..b588126a --- /dev/null +++ b/board/100ask-t113s3/hello_world/main.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +extern sunxi_serial_t uart_dbg; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + printk(LOG_LEVEL_INFO, "Hello World!\n"); + + return 0; +} \ No newline at end of file diff --git a/board/100ask-t113s3/start.S b/board/100ask-t113s3/start.S new file mode 100644 index 00000000..b55ac933 --- /dev/null +++ b/board/100ask-t113s3/start.S @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#define ARMV7_USR_MODE 0x10 +#define ARMV7_FIQ_MODE 0x11 +#define ARMV7_IRQ_MODE 0x12 +#define ARMV7_SVC_MODE 0x13 +#define ARMV7_MON_MODE 0x16 +#define ARMV7_ABT_MODE 0x17 +#define ARMV7_UND_MODE 0x1b +#define ARMV7_SYSTEM_MODE 0x1f +#define ARMV7_MODE_MASK 0x1f +#define ARMV7_FIQ_MASK 0x40 +#define ARMV7_IRQ_MASK 0x80 + +.arm +.globl reset +.text + +reset: + /* Boot head information for BROM */ + .long 0xea000016 + .byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0' + .long 0x12345678 /* checksum */ + .long __spl_size /* spl size */ + .long 0x30 /* boot header size */ + .long 0x30303033 /* boot header version */ + .long 0x00020000 /* return value */ + .long 0x00028000 /* run address */ + .long 0x0 /* eGON version */ + .byte 0x00, 0x00, 0x00, 0x00 /* platform information - 8byte */ + .byte 0x34, 0x2e, 0x30, 0x00 + + /* + * The actual reset code + */ + mrs r0, cpsr + bic r0, r0, #ARMV7_MODE_MASK + orr r0, r0, #ARMV7_SVC_MODE + orr r0, r0, #(ARMV7_IRQ_MASK | ARMV7_FIQ_MASK) + bic r0, r0, #(1<<9) @set little-endian + msr cpsr_c, r0 + + /* Set vector base address register */ + + ldr r0, =_vector + mcr p15, 0, r0, c12, c0, 0 + mrc p15, 0, r0, c1, c0, 0 + bic r0, #(1 << 13) + mcr p15, 0, r0, c1, c0, 0 + + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002000 @ clear bits 13 (--V-) + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache + mcr p15, 0, r0, c1, c0, 0 + + /* Enable neon/vfp unit */ + mrc p15, 0, r0, c1, c0, 2 + orr r0, r0, #(0xf << 20) + mcr p15, 0, r0, c1, c0, 2 + isb + mov r0, #0x40000000 + vmsr fpexc, r0 + + /* Set stack pointer */ + ldr sp, =__stack_srv_end + + bl clear_bss + + /* + * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, + * except if in HYP mode already + */ + mrs r0, cpsr + and r1, r0, #0x1f @ mask mode bits + teq r1, #0x1a @ test for HYP mode + bicne r0, r0, #0x1f @ clear all mode bits + orrne r0, r0, #0x13 @ set SVC mode + orr r0, r0, #0xc0 @ disable FIQ and IRQ + msr cpsr,r0 + + @set cntfrq to 24M + ldr r0, =24000000 + mcr p15, 0, r0, c14, c0, 0 + + bl set_timer_count + + bl main + + clear_bss: + ldr r0, =_sbss + ldr r1, =_ebss + mov r2, #0 + + clbss_1: + stmia r0!, {r2} + cmp r0, r1 + blt clbss_1 + + mov pc, lr + +_vector: + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq + +.macro save_regs + str lr, [sp, #-4] + mrs lr, spsr_all + str lr, [sp, #-8] + str r1, [sp, #-12] + str r0, [sp, #-16] + mov r0, sp + cps #0x13 + ldr r1, [r0, #-4] + str r1, [sp, #-4]! + ldr r1, [r0, #-8] + str r1, [sp, #-(4 * 16)] + ldr r1, [r0, #-12] + ldr r0, [r0, #-16] + stmdb sp, {r0 - r14}^ + sub sp, sp, #(4 * 16) + ldr r4, [sp] + and r0, r4, #0x1f + cmp r0, #0x10 + beq 10f + cmp r0, #0x13 + beq 11f + b . +11: add r1, sp, #(4 * 17) + str r1, [sp, #(4 * 14)] + str lr, [sp, #(4 * 15)] +10: add r1, sp, #(4 * 17) + str r1, [sp, #-4]! + mov r0, sp +.endm + +.macro restore_regs + mov r12, sp + ldr sp, [r12], #4 + ldr r1, [r12], #4 + msr spsr_cxsf, r1 + and r0, r1, #0x1f + cmp r0, #0x10 + beq 20f + cmp r0, #0x13 + beq 21f + b . +20: ldr lr, [r12, #(4 * 15)] + ldmia r12, {r0 - r14}^ + movs pc, lr +21: ldm r12, {r0 - r15}^ + mov r0, r0 +.endm + + /* + * Exception handlers + */ + .align 5 +undefined_instruction: + sub lr, lr, #4 + save_regs + bl arm32_do_undefined_instruction + restore_regs + + .align 5 +software_interrupt: + sub lr, lr, #4 + save_regs + bl arm32_do_software_interrupt + restore_regs + + .align 5 +prefetch_abort: + sub lr, lr, #4 + save_regs + bl arm32_do_prefetch_abort + restore_regs + + .align 5 +data_abort: + sub lr, lr, #8 + save_regs + bl arm32_do_data_abort + restore_regs + + .align 5 +not_used: + b . + + .align 5 +irq: + sub lr, lr, #4 + save_regs + bl arm32_do_irq + restore_regs + + .align 5 +fiq: + sub lr, lr, #4 + save_regs + bl arm32_do_fiq + restore_regs diff --git a/board/CMakeLists.txt b/board/CMakeLists.txt new file mode 100644 index 00000000..4fca92f9 --- /dev/null +++ b/board/CMakeLists.txt @@ -0,0 +1,15 @@ +if(CONFIG_BOARD_TINYVISION) + add_subdirectory(tinyvision) +endif() + +if(CONFIG_BOARD_YUZUKILIZARD) + add_subdirectory(yuzukilizard) +endif() + +if(CONFIG_BOARD_100ASK-T113S3) + add_subdirectory(100ask-t113s3) +endif() + +if(CONFIG_BOARD_100ASK-T113I) + add_subdirectory(100ask-t113i) +endif() \ No newline at end of file diff --git a/app/CMakeLists.txt b/board/tinyvision/CMakeLists.txt similarity index 70% rename from app/CMakeLists.txt rename to board/tinyvision/CMakeLists.txt index 97dd38dd..d589023a 100644 --- a/app/CMakeLists.txt +++ b/board/tinyvision/CMakeLists.txt @@ -1,4 +1,8 @@ -# SPDX-License-Identifier: Apache-2.0 +set(APP_COMMON_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/start.S + ${CMAKE_CURRENT_SOURCE_DIR}/board.c + ${CMAKE_CURRENT_SOURCE_DIR}/eabi_compat.c +) add_subdirectory(hello_world) @@ -28,4 +32,4 @@ add_subdirectory(i2c_test) add_subdirectory(i2c_oled) -add_subdirectory(spi_lcd) \ No newline at end of file +add_subdirectory(spi_lcd) diff --git a/board/tinyvision/README.md b/board/tinyvision/README.md new file mode 100644 index 00000000..fc121158 --- /dev/null +++ b/board/tinyvision/README.md @@ -0,0 +1,29 @@ +# SyterKit Common + +## start.S + +This code snippet is an ARM assembly language program that includes initialization settings and exception handlers. Here's a breakdown of its functionalities: + +1. Initialization Settings: It sets registers and writes specific values to configure the processor's working mode, interrupt enable, etc. + +2. Set Vector Table: It writes the address of the vector table to the Vector Base Address Register, which is used for handling exceptions and interrupts. + +3. Enable NEON/VFP Unit: It configures the processor to enable the NEON (Advanced SIMD) and VFP (Floating-Point) units. + +4. Clear BSS Section: It zeroes out variables in the BSS section. + +5. Disable Interrupts: It disables FIQ and IRQ interrupts and switches the processor to SVC32 mode. + +6. Set Timer Frequency: It sets the timer frequency to 24M. + +7. Call the main Function: It jumps to the main function to execute the main logic. + +## eabi_compat.c + +This code snippet appears to be providing implementations for the functions `abort`, `raise`, and `__aeabi_unwind_cpp_pr0`. Here's a breakdown of their functionalities: + +1. `void abort(void)`: This function creates an infinite loop, causing the program to hang indefinitely. It is typically used to indicate a critical error or unrecoverable condition in a program. + +2. `int raise(int signum)`: This function is a placeholder and always returns 0. In standard C, this function is used to raise a signal and initiate the corresponding signal handler. However, in this implementation, it does nothing and simply returns 0. + +3. `void __aeabi_unwind_cpp_pr0(void)`: This is a dummy function that serves as a placeholder to avoid linker complaints. Its purpose is to satisfy the linker when using C++ exceptions and unwinding, but it does not contain any actual functionality. diff --git a/board/tinyvision/board.c b/board/tinyvision/board.c new file mode 100644 index 00000000..58a58e7e --- /dev/null +++ b/board/tinyvision/board.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +sunxi_serial_t uart_dbg = { + .base = 0x02500000, + .id = 0, + .gpio_tx = {GPIO_PIN(GPIO_PORTH, 9), GPIO_PERIPH_MUX5}, + .gpio_rx = {GPIO_PIN(GPIO_PORTH, 10), GPIO_PERIPH_MUX5}, +}; + +sunxi_spi_t sunxi_spi0 = { + .base = 0x04025000, + .id = 0, + .clk_rate = 75 * 1000 * 1000, + .gpio_cs = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX4}, + .gpio_sck = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX4}, + .gpio_mosi = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX4}, + .gpio_miso = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX4}, + .gpio_wp = {GPIO_PIN(GPIO_PORTC, 4), GPIO_PERIPH_MUX4}, + .gpio_hold = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX4}, +}; + +sdhci_t sdhci0 = { + .name = "sdhci0", + .reg = (sdhci_reg_t *) 0x04020000, + .voltage = MMC_VDD_27_36, + .width = MMC_BUS_WIDTH_4, + .clock = MMC_CLK_50M, + .removable = 0, + .isspi = FALSE, + .gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2}, + .gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2}, + .gpio_d0 = {GPIO_PIN(GPIO_PORTF, 1), GPIO_PERIPH_MUX2}, + .gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2}, + .gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2}, + .gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2}, +}; + +dram_para_t dram_para = { + .dram_clk = 528, + .dram_type = 2, + .dram_zq = 0x7b7bf9, + .dram_odt_en = 0x0, + .dram_para1 = 0x00d2, + .dram_para2 = 0x0, + .dram_mr0 = 0xe73, + .dram_mr1 = 0x02, + .dram_mr2 = 0x0, + .dram_mr3 = 0x0, + .dram_tpr0 = 0x00471992, + .dram_tpr1 = 0x0131a10c, + .dram_tpr2 = 0x00057041, + .dram_tpr3 = 0xb4787896, + .dram_tpr4 = 0x0, + .dram_tpr5 = 0x48484848, + .dram_tpr6 = 0x48, + .dram_tpr7 = 0x1621121e, + .dram_tpr8 = 0x0, + .dram_tpr9 = 0x0, + .dram_tpr10 = 0x00000000, + .dram_tpr11 = 0x00000022, + .dram_tpr12 = 0x00000077, + .dram_tpr13 = 0x34000100, +}; + +void clean_syterkit_data(void) { + /* Disable MMU, data cache, instruction cache, interrupts */ + arm32_mmu_disable(); + printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); + arm32_dcache_disable(); + printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); + arm32_icache_disable(); + printk(LOG_LEVEL_INFO, "disable icache ok...\n"); + arm32_interrupt_disable(); + printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); +} + +void rtc_set_vccio_det_spare(void) { + u32 val = 0; + val = readl(SUNXI_RTC_BASE + 0x1f4); + val &= ~(0xff << 4); + val |= (VCCIO_THRESHOLD_VOLTAGE_2_9 | FORCE_DETECTER_OUTPUT); + val &= ~VCCIO_DET_BYPASS_EN; + writel(val, SUNXI_RTC_BASE + 0x1f4); +} + +void sys_ldo_check(void) { + uint32_t reg_val = 0; + uint32_t roughtrim_val = 0, finetrim_val = 0; + + /* reset */ + reg_val = readl(CCU_AUDIO_CODEC_BGR_REG); + reg_val &= ~(1 << 16); + writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); + + sdelay(2); + + reg_val |= (1 << 16); + writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); + + /* enable AUDIO gating */ + reg_val = readl(CCU_AUDIO_CODEC_BGR_REG); + reg_val |= (1 << 0); + writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); + + /* enable pcrm CTRL */ + reg_val = readl(ANA_PWR_RST_REG); + reg_val &= ~(1 << 0); + writel(reg_val, ANA_PWR_RST_REG); + + /* read efuse */ + printk(LOG_LEVEL_DEBUG, "Audio: avcc calibration\n"); + reg_val = readl(SUNXI_SID_SRAM_BASE + 0x28); + roughtrim_val = (reg_val >> 0) & 0xF; + reg_val = readl(SUNXI_SID_SRAM_BASE + 0x24); + finetrim_val = (reg_val >> 16) & 0xFF; + + if (roughtrim_val == 0 && finetrim_val == 0) { + reg_val = readl(SUNXI_VER_REG); + reg_val = (reg_val >> 0) & 0x7; + if (reg_val) { + printk(LOG_LEVEL_DEBUG, "Audio: chip not version A\n"); + } else { + roughtrim_val = 0x5; + finetrim_val = 0x19; + printk(LOG_LEVEL_DEBUG, "Audio: chip version A\n"); + } + } + reg_val = readl(AUDIO_POWER_REG); + reg_val &= ~(0xF << 8 | 0xFF); + reg_val |= roughtrim_val << 8 | finetrim_val; + writel(reg_val, AUDIO_POWER_REG); +} \ No newline at end of file diff --git a/app/cli_test/CMakeLists.txt b/board/tinyvision/cli_test/CMakeLists.txt similarity index 100% rename from app/cli_test/CMakeLists.txt rename to board/tinyvision/cli_test/CMakeLists.txt diff --git a/app/cli_test/main.c b/board/tinyvision/cli_test/main.c similarity index 79% rename from app/cli_test/main.c rename to board/tinyvision/cli_test/main.c index 557e4dd4..4410288f 100644 --- a/app/cli_test/main.c +++ b/board/tinyvision/cli_test/main.c @@ -13,12 +13,7 @@ #include #include -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; msh_declare_command(helloworld); diff --git a/board/tinyvision/eabi_compat.c b/board/tinyvision/eabi_compat.c new file mode 100644 index 00000000..93303d89 --- /dev/null +++ b/board/tinyvision/eabi_compat.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +void abort(void) { + while (1) + ; +} + +int raise(int signum) { + return 0; +} + +/* Dummy function to avoid linker complaints */ +void __aeabi_unwind_cpp_pr0(void) { +} \ No newline at end of file diff --git a/app/fdt_cli/CMakeLists.txt b/board/tinyvision/fdt_cli/CMakeLists.txt similarity index 100% rename from app/fdt_cli/CMakeLists.txt rename to board/tinyvision/fdt_cli/CMakeLists.txt diff --git a/app/fdt_cli/main.c b/board/tinyvision/fdt_cli/main.c similarity index 94% rename from app/fdt_cli/main.c rename to board/tinyvision/fdt_cli/main.c index 62959632..583292f6 100644 --- a/app/fdt_cli/main.c +++ b/board/tinyvision/fdt_cli/main.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -35,28 +35,11 @@ #define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; -sdhci_t sdhci0 = { - .name = "sdhci0", - .reg = (sdhci_reg_t *) 0x04020000, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .removable = 0, - .isspi = FALSE, - .gpio_clk = {GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2}, -}; +extern dram_para_t dram_para; + +extern sdhci_t sdhci0; #define FILENAME_MAX_LEN 64 typedef struct { @@ -429,7 +412,7 @@ int main(void) { sunxi_clk_init(); /* Initialize DRAM */ - sunxi_dram_init(); + sunxi_dram_init(&dram_para); /* Print clock information */ sunxi_clk_dump(); diff --git a/app/fdt_parser/CMakeLists.txt b/board/tinyvision/fdt_parser/CMakeLists.txt similarity index 100% rename from app/fdt_parser/CMakeLists.txt rename to board/tinyvision/fdt_parser/CMakeLists.txt diff --git a/app/fdt_parser/main.c b/board/tinyvision/fdt_parser/main.c similarity index 86% rename from app/fdt_parser/main.c rename to board/tinyvision/fdt_parser/main.c index 4826e00d..3441fd4c 100644 --- a/app/fdt_parser/main.c +++ b/board/tinyvision/fdt_parser/main.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include @@ -27,35 +27,18 @@ #define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; sunxi_serial_t uart_e907 = { .base = 0x02500C00, .id = 3, - .gpio_tx = {GPIO_PIN(PORTE, 0), GPIO_PERIPH_MUX7}, - .gpio_rx = {GPIO_PIN(PORTE, 1), GPIO_PERIPH_MUX7}, + .gpio_tx = {GPIO_PIN(GPIO_PORTE, 0), GPIO_PERIPH_MUX7}, + .gpio_rx = {GPIO_PIN(GPIO_PORTE, 1), GPIO_PERIPH_MUX7}, }; -sdhci_t sdhci0 = { - .name = "sdhci0", - .reg = (sdhci_reg_t *) 0x04020000, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .removable = 0, - .isspi = FALSE, - .gpio_clk = {GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2}, -}; +extern sdhci_t sdhci0; #define FILENAME_MAX_LEN 64 typedef struct { @@ -171,7 +154,7 @@ int main(void) { sunxi_clk_init(); /* Initialize DRAM */ - sunxi_dram_init(); + sunxi_dram_init(&dram_para); /* Print clock information */ sunxi_clk_dump(); diff --git a/board/tinyvision/hello_world/CMakeLists.txt b/board/tinyvision/hello_world/CMakeLists.txt new file mode 100644 index 00000000..b5ce1ea5 --- /dev/null +++ b/board/tinyvision/hello_world/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(helloworld + main.c +) \ No newline at end of file diff --git a/board/tinyvision/hello_world/main.c b/board/tinyvision/hello_world/main.c new file mode 100644 index 00000000..b588126a --- /dev/null +++ b/board/tinyvision/hello_world/main.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +extern sunxi_serial_t uart_dbg; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + printk(LOG_LEVEL_INFO, "Hello World!\n"); + + return 0; +} \ No newline at end of file diff --git a/app/i2c_oled/CMakeLists.txt b/board/tinyvision/i2c_oled/CMakeLists.txt similarity index 100% rename from app/i2c_oled/CMakeLists.txt rename to board/tinyvision/i2c_oled/CMakeLists.txt diff --git a/app/i2c_oled/main.c b/board/tinyvision/i2c_oled/main.c similarity index 71% rename from app/i2c_oled/main.c rename to board/tinyvision/i2c_oled/main.c index e665cda8..0a9d11ac 100644 --- a/app/i2c_oled/main.c +++ b/board/tinyvision/i2c_oled/main.c @@ -13,12 +13,7 @@ #include "oled.h" -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; int main(void) { sunxi_serial_init(&uart_dbg); diff --git a/app/i2c_oled/oled.c b/board/tinyvision/i2c_oled/oled.c similarity index 98% rename from app/i2c_oled/oled.c rename to board/tinyvision/i2c_oled/oled.c index 3b3c57bc..d853dc03 100644 --- a/app/i2c_oled/oled.c +++ b/board/tinyvision/i2c_oled/oled.c @@ -12,7 +12,7 @@ #include "oledfont.h" #define OLED_IIC_ADDR 0x3c -#define OLED_IIC_PORT 0 +#define OLED_IIC_GPIO_PORT 0 #define OLED_CMD 0 /*写命令 */ #define OLED_DATA 1 /* 写数据 */ @@ -23,8 +23,8 @@ sunxi_i2c_t i2c_0 = { .base = 0x02502000, .id = 0, .speed = 4000000, - .gpio_scl = {GPIO_PIN(PORTE, 4), GPIO_PERIPH_MUX8}, - .gpio_sda = {GPIO_PIN(PORTE, 5), GPIO_PERIPH_MUX8}, + .gpio_scl = {GPIO_PIN(GPIO_PORTE, 4), GPIO_PERIPH_MUX8}, + .gpio_sda = {GPIO_PIN(GPIO_PORTE, 5), GPIO_PERIPH_MUX8}, }; void OLED_WR_Byte(uint8_t dat, uint8_t mode) { diff --git a/app/i2c_oled/oled.h b/board/tinyvision/i2c_oled/oled.h similarity index 100% rename from app/i2c_oled/oled.h rename to board/tinyvision/i2c_oled/oled.h diff --git a/app/i2c_oled/oledfont.h b/board/tinyvision/i2c_oled/oledfont.h similarity index 100% rename from app/i2c_oled/oledfont.h rename to board/tinyvision/i2c_oled/oledfont.h diff --git a/app/i2c_test/CMakeLists.txt b/board/tinyvision/i2c_test/CMakeLists.txt similarity index 100% rename from app/i2c_test/CMakeLists.txt rename to board/tinyvision/i2c_test/CMakeLists.txt diff --git a/app/i2c_test/main.c b/board/tinyvision/i2c_test/main.c similarity index 69% rename from app/i2c_test/main.c rename to board/tinyvision/i2c_test/main.c index 35a0f5ef..01a8f131 100644 --- a/app/i2c_test/main.c +++ b/board/tinyvision/i2c_test/main.c @@ -12,19 +12,14 @@ #include "sys-i2c.h" #include "sys-uart.h" -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; sunxi_i2c_t i2c_0 = { .base = 0x02502000, .id = 0, .speed = 4000000, - .gpio_scl = {GPIO_PIN(PORTE, 4), GPIO_PERIPH_MUX8}, - .gpio_sda = {GPIO_PIN(PORTE, 5), GPIO_PERIPH_MUX8}, + .gpio_scl = {GPIO_PIN(GPIO_PORTE, 4), GPIO_PERIPH_MUX8}, + .gpio_sda = {GPIO_PIN(GPIO_PORTE, 5), GPIO_PERIPH_MUX8}, }; int main(void) { diff --git a/app/init_dram/CMakeLists.txt b/board/tinyvision/init_dram/CMakeLists.txt similarity index 100% rename from app/init_dram/CMakeLists.txt rename to board/tinyvision/init_dram/CMakeLists.txt diff --git a/app/init_dram/main.c b/board/tinyvision/init_dram/main.c similarity index 62% rename from app/init_dram/main.c rename to board/tinyvision/init_dram/main.c index 93556572..aa251a43 100644 --- a/app/init_dram/main.c +++ b/board/tinyvision/init_dram/main.c @@ -11,12 +11,7 @@ #include -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; diff --git a/app/load_e907/CMakeLists.txt b/board/tinyvision/load_e907/CMakeLists.txt similarity index 100% rename from app/load_e907/CMakeLists.txt rename to board/tinyvision/load_e907/CMakeLists.txt diff --git a/app/load_e907/main.c b/board/tinyvision/load_e907/main.c similarity index 81% rename from app/load_e907/main.c rename to board/tinyvision/load_e907/main.c index ebb475be..0aae797b 100644 --- a/app/load_e907/main.c +++ b/board/tinyvision/load_e907/main.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -25,28 +25,11 @@ #define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; - -sdhci_t sdhci0 = { - .name = "sdhci0", - .reg = (sdhci_reg_t *) 0x04020000, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .removable = 0, - .isspi = FALSE, - .gpio_clk = {GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2}, -}; +extern sunxi_serial_t uart_dbg; + +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; #define FILENAME_MAX_LEN 64 typedef struct { @@ -158,7 +141,7 @@ int main(void) { sunxi_clk_init(); - sunxi_dram_init(); + sunxi_dram_init(&dram_para); sunxi_clk_dump(); @@ -187,10 +170,10 @@ int main(void) { sunxi_e907_clock_reset(); - uint32_t elf_run_addr = elf_get_entry_addr((phys_addr_t) image.dest); + uint32_t elf_run_addr = elf32_get_entry_addr((phys_addr_t) image.dest); printk(LOG_LEVEL_INFO, "RISC-V ELF run addr: 0x%08x\n", elf_run_addr); - if (load_elf_image((phys_addr_t) image.dest)) { + if (load_elf32_image((phys_addr_t) image.dest)) { printk(LOG_LEVEL_ERROR, "RISC-V ELF load FAIL\n"); } diff --git a/app/read_chip_efuse/CMakeLists.txt b/board/tinyvision/read_chip_efuse/CMakeLists.txt similarity index 100% rename from app/read_chip_efuse/CMakeLists.txt rename to board/tinyvision/read_chip_efuse/CMakeLists.txt diff --git a/app/read_chip_efuse/main.c b/board/tinyvision/read_chip_efuse/main.c similarity index 73% rename from app/read_chip_efuse/main.c rename to board/tinyvision/read_chip_efuse/main.c index 60aa838b..13130e33 100644 --- a/app/read_chip_efuse/main.c +++ b/board/tinyvision/read_chip_efuse/main.c @@ -9,12 +9,7 @@ #include -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; int main(void) { sunxi_serial_init(&uart_dbg); diff --git a/app/read_chipsid/CMakeLists.txt b/board/tinyvision/read_chipsid/CMakeLists.txt similarity index 100% rename from app/read_chipsid/CMakeLists.txt rename to board/tinyvision/read_chipsid/CMakeLists.txt diff --git a/app/read_chipsid/main.c b/board/tinyvision/read_chipsid/main.c similarity index 60% rename from app/read_chipsid/main.c rename to board/tinyvision/read_chipsid/main.c index 393a3291..965ef55d 100644 --- a/app/read_chipsid/main.c +++ b/board/tinyvision/read_chipsid/main.c @@ -11,12 +11,7 @@ #include -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; int main(void) { sunxi_serial_init(&uart_dbg); diff --git a/app/spi_lcd/CMakeLists.txt b/board/tinyvision/spi_lcd/CMakeLists.txt similarity index 100% rename from app/spi_lcd/CMakeLists.txt rename to board/tinyvision/spi_lcd/CMakeLists.txt diff --git a/app/spi_lcd/lcd.c b/board/tinyvision/spi_lcd/lcd.c similarity index 99% rename from app/spi_lcd/lcd.c rename to board/tinyvision/spi_lcd/lcd.c index 3124ef00..20280433 100644 --- a/app/spi_lcd/lcd.c +++ b/board/tinyvision/spi_lcd/lcd.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/app/spi_lcd/lcd.h b/board/tinyvision/spi_lcd/lcd.h similarity index 100% rename from app/spi_lcd/lcd.h rename to board/tinyvision/spi_lcd/lcd.h diff --git a/app/spi_lcd/lcd_font.h b/board/tinyvision/spi_lcd/lcd_font.h similarity index 100% rename from app/spi_lcd/lcd_font.h rename to board/tinyvision/spi_lcd/lcd_font.h diff --git a/app/spi_lcd/lcd_init.h b/board/tinyvision/spi_lcd/lcd_init.h similarity index 100% rename from app/spi_lcd/lcd_init.h rename to board/tinyvision/spi_lcd/lcd_init.h diff --git a/app/spi_lcd/main.c b/board/tinyvision/spi_lcd/main.c similarity index 84% rename from app/spi_lcd/main.c rename to board/tinyvision/spi_lcd/main.c index a7551604..d7ba91b1 100644 --- a/app/spi_lcd/main.c +++ b/board/tinyvision/spi_lcd/main.c @@ -7,7 +7,7 @@ #include -#include +#include #include #include #include @@ -24,30 +24,27 @@ #define CONFIG_HEAP_BASE (0x40800000) #define CONFIG_HEAP_SIZE (16 * 1024 * 1024) -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; -sunxi_spi_t sunxi_spi0 = { +sunxi_spi_t sunxi_spi0_lcd = { .base = 0x04025000, .id = 0, .clk_rate = 120 * 1000 * 1000, - .gpio_cs = {GPIO_PIN(PORTC, 1), GPIO_PERIPH_MUX4}, - .gpio_sck = {GPIO_PIN(PORTC, 0), GPIO_PERIPH_MUX4}, - .gpio_mosi = {GPIO_PIN(PORTC, 2), GPIO_PERIPH_MUX4}, - .gpio_miso = {GPIO_PIN(PORTC, 3), GPIO_PERIPH_MUX4}, + .gpio_cs = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX4}, + .gpio_sck = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX4}, + .gpio_mosi = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX4}, + .gpio_miso = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX4}, }; static gpio_mux_t lcd_dc_pins = { - .pin = GPIO_PIN(PORTC, 4), + .pin = GPIO_PIN(GPIO_PORTC, 4), .mux = GPIO_OUTPUT, }; static gpio_mux_t lcd_res_pins = { - .pin = GPIO_PIN(PORTC, 5), + .pin = GPIO_PIN(GPIO_PORTC, 5), .mux = GPIO_OUTPUT, }; @@ -64,13 +61,13 @@ static void LCD_Write_Bus(uint8_t dat) { int r; /* Return value */ tx[0] = dat; - r = sunxi_spi_transfer(&sunxi_spi0, SPI_IO_SINGLE, tx, 1, 0, 0); /* Perform SPI transfer */ + r = sunxi_spi_transfer(&sunxi_spi0_lcd, SPI_IO_SINGLE, tx, 1, 0, 0); /* Perform SPI transfer */ if (r < 0) printk(LOG_LEVEL_ERROR, "SPI: SPI Xfer error!\n"); } void LCD_Write_Data_Bus(void *dat, uint32_t len) { - int r = sunxi_spi_transfer(&sunxi_spi0, SPI_IO_SINGLE, dat, len, 0, 0); /* Perform SPI transfer */ + int r = sunxi_spi_transfer(&sunxi_spi0_lcd, SPI_IO_SINGLE, dat, len, 0, 0); /* Perform SPI transfer */ if (r < 0) printk(LOG_LEVEL_ERROR, "SPI: SPI Xfer error!\n"); } @@ -196,7 +193,7 @@ int main(void) { sunxi_clk_init(); - uint64_t dram_size = sunxi_dram_init(); + uint64_t dram_size = sunxi_dram_init(&dram_para); arm32_mmu_enable(SDRAM_BASE, dram_size); printk(LOG_LEVEL_DEBUG, "enable mmu ok\n"); @@ -210,7 +207,7 @@ int main(void) { dma_init(); - if (sunxi_spi_init(&sunxi_spi0) != 0) { + if (sunxi_spi_init(&sunxi_spi0_lcd) != 0) { printk(LOG_LEVEL_ERROR, "SPI: init failed\n"); } @@ -234,7 +231,7 @@ int main(void) { LCD_ShowString(0, 240, "1.0.2", BLACK, WHITE, 32, 0); - sunxi_spi_disable(&sunxi_spi0); + sunxi_spi_disable(&sunxi_spi0_lcd); arm32_mmu_disable(); diff --git a/board/tinyvision/start.S b/board/tinyvision/start.S new file mode 100644 index 00000000..b55ac933 --- /dev/null +++ b/board/tinyvision/start.S @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#define ARMV7_USR_MODE 0x10 +#define ARMV7_FIQ_MODE 0x11 +#define ARMV7_IRQ_MODE 0x12 +#define ARMV7_SVC_MODE 0x13 +#define ARMV7_MON_MODE 0x16 +#define ARMV7_ABT_MODE 0x17 +#define ARMV7_UND_MODE 0x1b +#define ARMV7_SYSTEM_MODE 0x1f +#define ARMV7_MODE_MASK 0x1f +#define ARMV7_FIQ_MASK 0x40 +#define ARMV7_IRQ_MASK 0x80 + +.arm +.globl reset +.text + +reset: + /* Boot head information for BROM */ + .long 0xea000016 + .byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0' + .long 0x12345678 /* checksum */ + .long __spl_size /* spl size */ + .long 0x30 /* boot header size */ + .long 0x30303033 /* boot header version */ + .long 0x00020000 /* return value */ + .long 0x00028000 /* run address */ + .long 0x0 /* eGON version */ + .byte 0x00, 0x00, 0x00, 0x00 /* platform information - 8byte */ + .byte 0x34, 0x2e, 0x30, 0x00 + + /* + * The actual reset code + */ + mrs r0, cpsr + bic r0, r0, #ARMV7_MODE_MASK + orr r0, r0, #ARMV7_SVC_MODE + orr r0, r0, #(ARMV7_IRQ_MASK | ARMV7_FIQ_MASK) + bic r0, r0, #(1<<9) @set little-endian + msr cpsr_c, r0 + + /* Set vector base address register */ + + ldr r0, =_vector + mcr p15, 0, r0, c12, c0, 0 + mrc p15, 0, r0, c1, c0, 0 + bic r0, #(1 << 13) + mcr p15, 0, r0, c1, c0, 0 + + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002000 @ clear bits 13 (--V-) + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache + mcr p15, 0, r0, c1, c0, 0 + + /* Enable neon/vfp unit */ + mrc p15, 0, r0, c1, c0, 2 + orr r0, r0, #(0xf << 20) + mcr p15, 0, r0, c1, c0, 2 + isb + mov r0, #0x40000000 + vmsr fpexc, r0 + + /* Set stack pointer */ + ldr sp, =__stack_srv_end + + bl clear_bss + + /* + * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, + * except if in HYP mode already + */ + mrs r0, cpsr + and r1, r0, #0x1f @ mask mode bits + teq r1, #0x1a @ test for HYP mode + bicne r0, r0, #0x1f @ clear all mode bits + orrne r0, r0, #0x13 @ set SVC mode + orr r0, r0, #0xc0 @ disable FIQ and IRQ + msr cpsr,r0 + + @set cntfrq to 24M + ldr r0, =24000000 + mcr p15, 0, r0, c14, c0, 0 + + bl set_timer_count + + bl main + + clear_bss: + ldr r0, =_sbss + ldr r1, =_ebss + mov r2, #0 + + clbss_1: + stmia r0!, {r2} + cmp r0, r1 + blt clbss_1 + + mov pc, lr + +_vector: + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq + +.macro save_regs + str lr, [sp, #-4] + mrs lr, spsr_all + str lr, [sp, #-8] + str r1, [sp, #-12] + str r0, [sp, #-16] + mov r0, sp + cps #0x13 + ldr r1, [r0, #-4] + str r1, [sp, #-4]! + ldr r1, [r0, #-8] + str r1, [sp, #-(4 * 16)] + ldr r1, [r0, #-12] + ldr r0, [r0, #-16] + stmdb sp, {r0 - r14}^ + sub sp, sp, #(4 * 16) + ldr r4, [sp] + and r0, r4, #0x1f + cmp r0, #0x10 + beq 10f + cmp r0, #0x13 + beq 11f + b . +11: add r1, sp, #(4 * 17) + str r1, [sp, #(4 * 14)] + str lr, [sp, #(4 * 15)] +10: add r1, sp, #(4 * 17) + str r1, [sp, #-4]! + mov r0, sp +.endm + +.macro restore_regs + mov r12, sp + ldr sp, [r12], #4 + ldr r1, [r12], #4 + msr spsr_cxsf, r1 + and r0, r1, #0x1f + cmp r0, #0x10 + beq 20f + cmp r0, #0x13 + beq 21f + b . +20: ldr lr, [r12, #(4 * 15)] + ldmia r12, {r0 - r14}^ + movs pc, lr +21: ldm r12, {r0 - r15}^ + mov r0, r0 +.endm + + /* + * Exception handlers + */ + .align 5 +undefined_instruction: + sub lr, lr, #4 + save_regs + bl arm32_do_undefined_instruction + restore_regs + + .align 5 +software_interrupt: + sub lr, lr, #4 + save_regs + bl arm32_do_software_interrupt + restore_regs + + .align 5 +prefetch_abort: + sub lr, lr, #4 + save_regs + bl arm32_do_prefetch_abort + restore_regs + + .align 5 +data_abort: + sub lr, lr, #8 + save_regs + bl arm32_do_data_abort + restore_regs + + .align 5 +not_used: + b . + + .align 5 +irq: + sub lr, lr, #4 + save_regs + bl arm32_do_irq + restore_regs + + .align 5 +fiq: + sub lr, lr, #4 + save_regs + bl arm32_do_fiq + restore_regs diff --git a/app/syter_amp/CMakeLists.txt b/board/tinyvision/syter_amp/CMakeLists.txt similarity index 100% rename from app/syter_amp/CMakeLists.txt rename to board/tinyvision/syter_amp/CMakeLists.txt diff --git a/app/syter_amp/main.c b/board/tinyvision/syter_amp/main.c similarity index 82% rename from app/syter_amp/main.c rename to board/tinyvision/syter_amp/main.c index 1667779f..a84259d3 100644 --- a/app/syter_amp/main.c +++ b/board/tinyvision/syter_amp/main.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -59,47 +59,20 @@ typedef struct { unsigned int end; } linux_zimage_header_t; -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; sunxi_serial_t uart_e907 = { .base = 0x02500C00, .id = 3, - .gpio_tx = {GPIO_PIN(PORTE, 0), GPIO_PERIPH_MUX7}, - .gpio_rx = {GPIO_PIN(PORTE, 1), GPIO_PERIPH_MUX7}, + .gpio_tx = {GPIO_PIN(GPIO_PORTE, 0), GPIO_PERIPH_MUX7}, + .gpio_rx = {GPIO_PIN(GPIO_PORTE, 1), GPIO_PERIPH_MUX7}, }; -sunxi_spi_t sunxi_spi0 = { - .base = 0x04025000, - .id = 0, - .clk_rate = 75 * 1000 * 1000, - .gpio_cs = {GPIO_PIN(PORTC, 1), GPIO_PERIPH_MUX4}, - .gpio_sck = {GPIO_PIN(PORTC, 0), GPIO_PERIPH_MUX4}, - .gpio_mosi = {GPIO_PIN(PORTC, 2), GPIO_PERIPH_MUX4}, - .gpio_miso = {GPIO_PIN(PORTC, 3), GPIO_PERIPH_MUX4}, - .gpio_wp = {GPIO_PIN(PORTC, 4), GPIO_PERIPH_MUX4}, - .gpio_hold = {GPIO_PIN(PORTC, 5), GPIO_PERIPH_MUX4}, -}; +extern sunxi_spi_t sunxi_spi0; -sdhci_t sdhci0 = { - .name = "sdhci0", - .reg = (sdhci_reg_t *) 0x04020000, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .removable = 0, - .isspi = FALSE, - .gpio_clk = {GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2}, -}; +extern sdhci_t sdhci0; image_info_t image; @@ -239,7 +212,7 @@ int main(void) { sunxi_clk_init(); - sunxi_dram_init(); + sunxi_dram_init(&dram_para); unsigned int entry_point = 0; void (*kernel_entry)(int zero, int arch, unsigned int params); @@ -272,10 +245,10 @@ int main(void) { sunxi_e907_clock_reset(); - uint32_t elf_run_addr = elf_get_entry_addr((phys_addr_t) image.dest); + uint32_t elf_run_addr = elf32_get_entry_addr((phys_addr_t) image.dest); printk(LOG_LEVEL_INFO, "RISC-V ELF run addr: 0x%08x\n", elf_run_addr); - if (load_elf_image((phys_addr_t) image.dest)) { + if (load_elf32_image((phys_addr_t) image.dest)) { printk(LOG_LEVEL_ERROR, "RISC-V ELF load FAIL\n"); } diff --git a/board/tinyvision/syter_boot/CMakeLists.txt b/board/tinyvision/syter_boot/CMakeLists.txt new file mode 100644 index 00000000..5bfbb5f4 --- /dev/null +++ b/board/tinyvision/syter_boot/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(syter_boot + main.c +) \ No newline at end of file diff --git a/app/syter_boot/main.c b/board/tinyvision/syter_boot/main.c similarity index 94% rename from app/syter_boot/main.c rename to board/tinyvision/syter_boot/main.c index f8e5f6a5..7ad476f5 100644 --- a/app/syter_boot/main.c +++ b/board/tinyvision/syter_boot/main.c @@ -5,10 +5,11 @@ #include #include +#include #include #include -#include +#include #include #include #include @@ -24,7 +25,6 @@ #include "sys-sdcard.h" #include "sys-sid.h" #include "sys-spi.h" -#include "sys-timer.h" #include "fdt_wrapper.h" #include "ff.h" @@ -83,40 +83,13 @@ typedef struct { uint32_t end; } linux_zimage_header_t; -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; -sunxi_spi_t sunxi_spi0 = { - .base = 0x04025000, - .id = 0, - .clk_rate = 75 * 1000 * 1000, - .gpio_cs = {GPIO_PIN(PORTC, 1), GPIO_PERIPH_MUX4}, - .gpio_sck = {GPIO_PIN(PORTC, 0), GPIO_PERIPH_MUX4}, - .gpio_mosi = {GPIO_PIN(PORTC, 2), GPIO_PERIPH_MUX4}, - .gpio_miso = {GPIO_PIN(PORTC, 3), GPIO_PERIPH_MUX4}, - .gpio_wp = {GPIO_PIN(PORTC, 4), GPIO_PERIPH_MUX4}, - .gpio_hold = {GPIO_PIN(PORTC, 5), GPIO_PERIPH_MUX4}, -}; +extern sunxi_spi_t sunxi_spi0; -sdhci_t sdhci0 = { - .name = "sdhci0", - .reg = (sdhci_reg_t *) 0x04020000, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .removable = 0, - .isspi = FALSE, - .gpio_clk = {GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2}, -}; +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; image_info_t image; @@ -634,7 +607,7 @@ int main(void) { } /* Initialize the DRAM and enable memory management unit (MMU). */ - uint64_t dram_size = sunxi_dram_init(); + uint64_t dram_size = sunxi_dram_init(&dram_para); arm32_mmu_enable(SDRAM_BASE, dram_size); /* Debug message to indicate that MMU is enabled. */ diff --git a/app/syter_boot_spi/CMakeLists.txt b/board/tinyvision/syter_boot_spi/CMakeLists.txt similarity index 100% rename from app/syter_boot_spi/CMakeLists.txt rename to board/tinyvision/syter_boot_spi/CMakeLists.txt diff --git a/app/syter_boot_spi/main.c b/board/tinyvision/syter_boot_spi/main.c similarity index 87% rename from app/syter_boot_spi/main.c rename to board/tinyvision/syter_boot_spi/main.c index 0f0c4285..be53047a 100644 --- a/app/syter_boot_spi/main.c +++ b/board/tinyvision/syter_boot_spi/main.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -56,40 +56,13 @@ typedef struct { unsigned int end; } linux_zimage_header_t; -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; - -sunxi_spi_t sunxi_spi0 = { - .base = 0x04025000, - .id = 0, - .clk_rate = 75 * 1000 * 1000, - .gpio_cs = {GPIO_PIN(PORTC, 1), GPIO_PERIPH_MUX4}, - .gpio_sck = {GPIO_PIN(PORTC, 0), GPIO_PERIPH_MUX4}, - .gpio_mosi = {GPIO_PIN(PORTC, 2), GPIO_PERIPH_MUX4}, - .gpio_miso = {GPIO_PIN(PORTC, 3), GPIO_PERIPH_MUX4}, - .gpio_wp = {GPIO_PIN(PORTC, 4), GPIO_PERIPH_MUX4}, - .gpio_hold = {GPIO_PIN(PORTC, 5), GPIO_PERIPH_MUX4}, -}; - -sdhci_t sdhci0 = { - .name = "sdhci0", - .reg = (sdhci_reg_t *) 0x04020000, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .removable = 0, - .isspi = FALSE, - .gpio_clk = {GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2}, -}; +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; + +extern sunxi_spi_t sunxi_spi0; + +extern sdhci_t sdhci0; image_info_t image; @@ -281,7 +254,7 @@ int main(void) { sunxi_clk_init(); - sunxi_dram_init(); + sunxi_dram_init(&dram_para); unsigned int entry_point = 0; void (*kernel_entry)(int zero, int arch, unsigned int params); diff --git a/app/syter_bootargs/CMakeLists.txt b/board/tinyvision/syter_bootargs/CMakeLists.txt similarity index 100% rename from app/syter_bootargs/CMakeLists.txt rename to board/tinyvision/syter_bootargs/CMakeLists.txt diff --git a/app/syter_bootargs/main.c b/board/tinyvision/syter_bootargs/main.c similarity index 90% rename from app/syter_bootargs/main.c rename to board/tinyvision/syter_bootargs/main.c index 44925f26..d151c003 100644 --- a/app/syter_bootargs/main.c +++ b/board/tinyvision/syter_bootargs/main.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include @@ -58,40 +58,13 @@ typedef struct { unsigned int end; } linux_zimage_header_t; -sunxi_serial_t uart_dbg = { - .base = 0x02500000, - .id = 0, - .gpio_tx = {GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5}, - .gpio_rx = {GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5}, -}; +extern sunxi_serial_t uart_dbg; -sunxi_spi_t sunxi_spi0 = { - .base = 0x04025000, - .id = 0, - .clk_rate = 75 * 1000 * 1000, - .gpio_cs = {GPIO_PIN(PORTC, 1), GPIO_PERIPH_MUX4}, - .gpio_sck = {GPIO_PIN(PORTC, 0), GPIO_PERIPH_MUX4}, - .gpio_mosi = {GPIO_PIN(PORTC, 2), GPIO_PERIPH_MUX4}, - .gpio_miso = {GPIO_PIN(PORTC, 3), GPIO_PERIPH_MUX4}, - .gpio_wp = {GPIO_PIN(PORTC, 4), GPIO_PERIPH_MUX4}, - .gpio_hold = {GPIO_PIN(PORTC, 5), GPIO_PERIPH_MUX4}, -}; +extern sunxi_spi_t sunxi_spi0; -sdhci_t sdhci0 = { - .name = "sdhci0", - .reg = (sdhci_reg_t *) 0x04020000, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .removable = 0, - .isspi = FALSE, - .gpio_clk = {GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2}, -}; +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; image_info_t image; @@ -412,7 +385,7 @@ int main(void) { sunxi_clk_init(); - sunxi_dram_init(); + sunxi_dram_init(&dram_para); sunxi_clk_dump(); diff --git a/board/yuzukilizard/CMakeLists.txt b/board/yuzukilizard/CMakeLists.txt new file mode 100644 index 00000000..d589023a --- /dev/null +++ b/board/yuzukilizard/CMakeLists.txt @@ -0,0 +1,35 @@ +set(APP_COMMON_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/start.S + ${CMAKE_CURRENT_SOURCE_DIR}/board.c + ${CMAKE_CURRENT_SOURCE_DIR}/eabi_compat.c +) + +add_subdirectory(hello_world) + +add_subdirectory(read_chipsid) + +add_subdirectory(init_dram) + +add_subdirectory(read_chip_efuse) + +add_subdirectory(syter_boot) + +add_subdirectory(syter_bootargs) + +add_subdirectory(load_e907) + +add_subdirectory(syter_amp) + +add_subdirectory(fdt_parser) + +add_subdirectory(cli_test) + +add_subdirectory(fdt_cli) + +add_subdirectory(syter_boot_spi) + +add_subdirectory(i2c_test) + +add_subdirectory(i2c_oled) + +add_subdirectory(spi_lcd) diff --git a/board/yuzukilizard/README.md b/board/yuzukilizard/README.md new file mode 100644 index 00000000..fc121158 --- /dev/null +++ b/board/yuzukilizard/README.md @@ -0,0 +1,29 @@ +# SyterKit Common + +## start.S + +This code snippet is an ARM assembly language program that includes initialization settings and exception handlers. Here's a breakdown of its functionalities: + +1. Initialization Settings: It sets registers and writes specific values to configure the processor's working mode, interrupt enable, etc. + +2. Set Vector Table: It writes the address of the vector table to the Vector Base Address Register, which is used for handling exceptions and interrupts. + +3. Enable NEON/VFP Unit: It configures the processor to enable the NEON (Advanced SIMD) and VFP (Floating-Point) units. + +4. Clear BSS Section: It zeroes out variables in the BSS section. + +5. Disable Interrupts: It disables FIQ and IRQ interrupts and switches the processor to SVC32 mode. + +6. Set Timer Frequency: It sets the timer frequency to 24M. + +7. Call the main Function: It jumps to the main function to execute the main logic. + +## eabi_compat.c + +This code snippet appears to be providing implementations for the functions `abort`, `raise`, and `__aeabi_unwind_cpp_pr0`. Here's a breakdown of their functionalities: + +1. `void abort(void)`: This function creates an infinite loop, causing the program to hang indefinitely. It is typically used to indicate a critical error or unrecoverable condition in a program. + +2. `int raise(int signum)`: This function is a placeholder and always returns 0. In standard C, this function is used to raise a signal and initiate the corresponding signal handler. However, in this implementation, it does nothing and simply returns 0. + +3. `void __aeabi_unwind_cpp_pr0(void)`: This is a dummy function that serves as a placeholder to avoid linker complaints. Its purpose is to satisfy the linker when using C++ exceptions and unwinding, but it does not contain any actual functionality. diff --git a/board/yuzukilizard/board.c b/board/yuzukilizard/board.c new file mode 100644 index 00000000..027b3f6b --- /dev/null +++ b/board/yuzukilizard/board.c @@ -0,0 +1,149 @@ +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +sunxi_serial_t uart_dbg = { + .base = 0x02500000, + .id = 0, + .gpio_tx = {GPIO_PIN(GPIO_PORTH, 9), GPIO_PERIPH_MUX5}, + .gpio_rx = {GPIO_PIN(GPIO_PORTH, 10), GPIO_PERIPH_MUX5}, +}; + +sunxi_spi_t sunxi_spi0 = { + .base = 0x04025000, + .id = 0, + .clk_rate = 75 * 1000 * 1000, + .gpio_cs = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX4}, + .gpio_sck = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX4}, + .gpio_mosi = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX4}, + .gpio_miso = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX4}, + .gpio_wp = {GPIO_PIN(GPIO_PORTC, 4), GPIO_PERIPH_MUX4}, + .gpio_hold = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX4}, +}; + +sdhci_t sdhci0 = { + .name = "sdhci0", + .reg = (sdhci_reg_t *) 0x04020000, + .voltage = MMC_VDD_27_36, + .width = MMC_BUS_WIDTH_4, + .clock = MMC_CLK_50M, + .removable = 0, + .isspi = FALSE, + .gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2}, + .gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2}, + .gpio_d0 = {GPIO_PIN(GPIO_PORTF, 1), GPIO_PERIPH_MUX2}, + .gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2}, + .gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2}, + .gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2}, +}; + +dram_para_t dram_para = { + .dram_clk = 528, + .dram_type = 2, + .dram_zq = 0x7b7bf9, + .dram_odt_en = 0x0, + .dram_para1 = 0x00d2, + .dram_para2 = 0x0, + .dram_mr0 = 0xe73, + .dram_mr1 = 0x02, + .dram_mr2 = 0x0, + .dram_mr3 = 0x0, + .dram_tpr0 = 0x00471992, + .dram_tpr1 = 0x0131a10c, + .dram_tpr2 = 0x00057041, + .dram_tpr3 = 0xb4787896, + .dram_tpr4 = 0x0, + .dram_tpr5 = 0x48484848, + .dram_tpr6 = 0x48, + .dram_tpr7 = 0x1621121e, + .dram_tpr8 = 0x0, + .dram_tpr9 = 0x0, + .dram_tpr10 = 0x00000000, + .dram_tpr11 = 0x00000022, + .dram_tpr12 = 0x00000077, + .dram_tpr13 = 0x34000100, +}; + +void clean_syterkit_data(void) { + /* Disable MMU, data cache, instruction cache, interrupts */ + arm32_mmu_disable(); + printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); + arm32_dcache_disable(); + printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); + arm32_icache_disable(); + printk(LOG_LEVEL_INFO, "disable icache ok...\n"); + arm32_interrupt_disable(); + printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); +} + +void rtc_set_vccio_det_spare(void) { + u32 val = 0; + val = readl(SUNXI_RTC_BASE + 0x1f4); + val &= ~(0xff << 4); + val |= (VCCIO_THRESHOLD_VOLTAGE_2_9 | FORCE_DETECTER_OUTPUT); + val &= ~VCCIO_DET_BYPASS_EN; + writel(val, SUNXI_RTC_BASE + 0x1f4); +} + +void sys_ldo_check(void) { + uint32_t reg_val = 0; + uint32_t roughtrim_val = 0, finetrim_val = 0; + + /* reset */ + reg_val = readl(CCU_AUDIO_CODEC_BGR_REG); + reg_val &= ~(1 << 16); + writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); + + sdelay(2); + + reg_val |= (1 << 16); + writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); + + /* enable AUDIO gating */ + reg_val = readl(CCU_AUDIO_CODEC_BGR_REG); + reg_val |= (1 << 0); + writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); + + /* enable pcrm CTRL */ + reg_val = readl(ANA_PWR_RST_REG); + reg_val &= ~(1 << 0); + writel(reg_val, ANA_PWR_RST_REG); + + /* read efuse */ + printk(LOG_LEVEL_DEBUG, "Audio: avcc calibration\n"); + reg_val = readl(SUNXI_SID_SRAM_BASE + 0x28); + roughtrim_val = (reg_val >> 0) & 0xF; + reg_val = readl(SUNXI_SID_SRAM_BASE + 0x24); + finetrim_val = (reg_val >> 16) & 0xFF; + + if (roughtrim_val == 0 && finetrim_val == 0) { + reg_val = readl(SUNXI_VER_REG); + reg_val = (reg_val >> 0) & 0x7; + if (reg_val) { + printk(LOG_LEVEL_DEBUG, "Audio: chip not version A\n"); + } else { + roughtrim_val = 0x5; + finetrim_val = 0x19; + printk(LOG_LEVEL_DEBUG, "Audio: chip version A\n"); + } + } + reg_val = readl(AUDIO_POWER_REG); + reg_val &= ~(0xF << 8 | 0xFF); + reg_val |= roughtrim_val << 8 | finetrim_val; + writel(reg_val, AUDIO_POWER_REG); +} \ No newline at end of file diff --git a/board/yuzukilizard/cli_test/CMakeLists.txt b/board/yuzukilizard/cli_test/CMakeLists.txt new file mode 100644 index 00000000..e2505e8e --- /dev/null +++ b/board/yuzukilizard/cli_test/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(cli_test + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/cli_test/main.c b/board/yuzukilizard/cli_test/main.c new file mode 100644 index 00000000..4410288f --- /dev/null +++ b/board/yuzukilizard/cli_test/main.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +extern sunxi_serial_t uart_dbg; + +msh_declare_command(helloworld); + +msh_define_help(helloworld, "display helloworld", "Usage: helloworld\n"); +int cmd_helloworld(int argc, const char **argv) { + printk(LOG_LEVEL_MUTE, "Hello World!\n"); + return 0; +} + +const msh_command_entry commands[] = { + msh_define_command(helloworld), + msh_command_end, +}; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + printk(LOG_LEVEL_INFO, "Hello World!\n"); + + syterkit_shell_attach(commands); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/eabi_compat.c b/board/yuzukilizard/eabi_compat.c new file mode 100644 index 00000000..93303d89 --- /dev/null +++ b/board/yuzukilizard/eabi_compat.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +void abort(void) { + while (1) + ; +} + +int raise(int signum) { + return 0; +} + +/* Dummy function to avoid linker complaints */ +void __aeabi_unwind_cpp_pr0(void) { +} \ No newline at end of file diff --git a/board/yuzukilizard/fdt_cli/CMakeLists.txt b/board/yuzukilizard/fdt_cli/CMakeLists.txt new file mode 100644 index 00000000..20c9a649 --- /dev/null +++ b/board/yuzukilizard/fdt_cli/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(fdt_cli + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/fdt_cli/main.c b/board/yuzukilizard/fdt_cli/main.c new file mode 100644 index 00000000..583292f6 --- /dev/null +++ b/board/yuzukilizard/fdt_cli/main.c @@ -0,0 +1,468 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-sdcard.h" +#include "sys-sid.h" + +#include "fdt_wrapper.h" +#include "ff.h" +#include "libfdt.h" + +#define CONFIG_DTB_FILENAME "sunxi.dtb" +#define CONFIG_DTB_LOADADDR (0x41008000) + +#define MAX_LEVEL 32 /* how deeply nested we will go */ +#define SCRATCHPAD 1024 /* bytes of scratchpad memory */ +#define CMD_FDT_MAX_DUMP 64 + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; + +extern sdhci_t sdhci0; + +#define FILENAME_MAX_LEN 64 +typedef struct { + unsigned int offset; + unsigned int length; + unsigned char *dest; + + char filename[FILENAME_MAX_LEN]; +} image_info_t; + +image_info_t image; + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: open, filename: [%s]: error %d\n", filename, fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, + CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, + (unsigned int) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + + + +msh_declare_command(fdt); +msh_define_help(fdt, "flattened device tree utility commands", + "fdt print [] - Recursive print starting at \n" + "fdt list [] - Print one level starting at \n" + "fdt set [] - Set [to ]\n" + "fdt mknode - Create a new node after \n" + "fdt rm [] - Delete the node or \n" + "fdt header - Display header info\n" + "fdt rsvmem print - Show current mem reserves\n" + "fdt rsvmem add - Add a mem reserve\n" + "fdt rsvmem delete - Delete a mem reserves\n" + "NOTE: Dereference aliases by omitting the leading '/', " + "e.g. fdt print ethernet0.\n\n"); +int cmd_fdt(int argc, const char **argv) { + if (argc < 2) { + uart_puts(cmd_fdt_usage); + return 0; + } + if (strncmp(argv[1], "mk", 2) == 0) { + char *pathp; /* path */ + char *nodep; /* new node to add */ + int nodeoffset; /* node offset from libfdt */ + int err; + + /* + * Parameters: Node path, new node to be appended to the path. + */ + if (argc < 4) { + uart_puts(cmd_fdt_usage); + return 0; + } + + pathp = argv[2]; + nodep = argv[3]; + + nodeoffset = fdt_path_offset(image.dest, pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printk(LOG_LEVEL_MUTE, "libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); + return 1; + } + err = fdt_add_subnode(image.dest, nodeoffset, nodep); + if (err < 0) { + printk(LOG_LEVEL_MUTE, "libfdt fdt_add_subnode(): %s\n", fdt_strerror(err)); + return 1; + } + } else if (strncmp(argv[1], "set", 3) == 0) { + char *pathp; /* path */ + char *prop; /* property */ + int nodeoffset; /* node offset from libfdt */ + static char data[SCRATCHPAD] __aligned(4); /* property storage */ + const void *ptmp; + int len; /* new length of the property */ + int ret; /* return value */ + + /* + * Parameters: Node path, property, optional value. + */ + if (argc < 4) { + uart_puts(cmd_fdt_usage); + return 0; + } + + pathp = argv[2]; + prop = argv[3]; + + nodeoffset = fdt_path_offset(image.dest, pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printk(LOG_LEVEL_MUTE, "libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); + return 1; + } + + if (argc == 4) { + len = 0; + } else { + ptmp = fdt_getprop(image.dest, nodeoffset, prop, &len); + if (len > SCRATCHPAD) { + printk(LOG_LEVEL_MUTE, "prop (%d) doesn't fit in scratchpad!\n", len); + return 1; + } + if (ptmp != NULL) + memcpy(data, ptmp, len); + + ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); + if (ret != 0) + return ret; + } + + ret = fdt_setprop(image.dest, nodeoffset, prop, data, len); + if (ret < 0) { + printk(LOG_LEVEL_MUTE, "libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); + return 1; + } + } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { + int depth = MAX_LEVEL; /* how deep to print */ + char *pathp; /* path */ + char *prop; /* property */ + int ret; /* return value */ + static char root[2] = "/"; + + /* + * list is an alias for print, but limited to 1 level + */ + if (argv[1][0] == 'l') { + depth = 1; + } + + /* + * Get the starting path. The root node is an oddball, + * the offset is zero and has no name. + */ + if (argc == 2) + pathp = root; + else + pathp = argv[2]; + if (argc > 3) + prop = argv[3]; + else + prop = NULL; + + fdt_print(image.dest, pathp, prop, depth); + } else if (strncmp(argv[1], "rm", 2) == 0) { + int nodeoffset; /* node offset from libfdt */ + int err; + + /* + * Get the path. The root node is an oddball, the offset + * is zero and has no name. + */ + nodeoffset = fdt_path_offset(image.dest, argv[2]); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printk(LOG_LEVEL_MUTE, "libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); + return 1; + } + /* + * Do the delete. A fourth parameter means delete a property, + * otherwise delete the node. + */ + if (argc > 3) { + err = fdt_delprop(image.dest, nodeoffset, argv[3]); + if (err < 0) { + printk(LOG_LEVEL_MUTE, "libfdt fdt_delprop(): %s\n", fdt_strerror(err)); + return 0; + } + } else { + err = fdt_del_node(image.dest, nodeoffset); + if (err < 0) { + printk(LOG_LEVEL_MUTE, "libfdt fdt_del_node(): %s\n", fdt_strerror(err)); + return 0; + } + } + } else if (argv[1][0] == 'h') { + u32 version = fdt_version(image.dest); + printk(LOG_LEVEL_MUTE, "magic:\t\t\t0x%x\n", fdt_magic(image.dest)); + printk(LOG_LEVEL_MUTE, "totalsize:\t\t0x%x (%d)\n", fdt_totalsize(image.dest), + fdt_totalsize(image.dest)); + printk(LOG_LEVEL_MUTE, "off_dt_struct:\t\t0x%x\n", + fdt_off_dt_struct(image.dest)); + printk(LOG_LEVEL_MUTE, "off_dt_strings:\t\t0x%x\n", + fdt_off_dt_strings(image.dest)); + printk(LOG_LEVEL_MUTE, "off_mem_rsvmap:\t\t0x%x\n", + fdt_off_mem_rsvmap(image.dest)); + printk(LOG_LEVEL_MUTE, "version:\t\t%d\n", version); + printk(LOG_LEVEL_MUTE, "last_comp_version:\t%d\n", + fdt_last_comp_version(image.dest)); + if (version >= 2) + printk(LOG_LEVEL_MUTE, "boot_cpuid_phys:\t0x%x\n", + fdt_boot_cpuid_phys(image.dest)); + if (version >= 3) + printk(LOG_LEVEL_MUTE, "size_dt_strings:\t0x%x\n", + fdt_size_dt_strings(image.dest)); + if (version >= 17) + printk(LOG_LEVEL_MUTE, "size_dt_struct:\t\t0x%x\n", + fdt_size_dt_struct(image.dest)); + printk(LOG_LEVEL_MUTE, "number mem_rsv:\t\t0x%x\n", + fdt_num_mem_rsv(image.dest)); + printk(LOG_LEVEL_MUTE, "\n"); + } else if (strncmp(argv[1], "rs", 2) == 0) { + if (argv[2][0] == 'p') { + uint64_t addr, size; + int total = fdt_num_mem_rsv(image.dest); + int j, err; + printk(LOG_LEVEL_MUTE, "index\t\t start\t\t size\n"); + printk(LOG_LEVEL_MUTE, "-------------------------------" + "-----------------\n"); + for (j = 0; j < total; j++) { + err = fdt_get_mem_rsv(image.dest, j, &addr, &size); + if (err < 0) { + printk(LOG_LEVEL_MUTE, "libfdt fdt_get_mem_rsv(): %s\n", fdt_strerror(err)); + return 0; + } + printk(LOG_LEVEL_MUTE, " %x\t%08x%08x\t%08x%08x\n", j, + (u32) (addr >> 32), + (u32) (addr & 0xffffffff), + (u32) (size >> 32), + (u32) (size & 0xffffffff)); + } + } else if (argv[2][0] == 'a') { + uint64_t addr, size; + int err; + addr = simple_strtoull(argv[3], NULL, 16); + size = simple_strtoull(argv[4], NULL, 16); + err = fdt_add_mem_rsv(image.dest, addr, size); + + if (err < 0) { + printk(LOG_LEVEL_MUTE, "libfdt fdt_add_mem_rsv(): %s\n", fdt_strerror(err)); + return 0; + } + } else if (argv[2][0] == 'd') { + unsigned long idx = simple_strtoul(argv[3], NULL, 16); + int err = fdt_del_mem_rsv(image.dest, idx); + + if (err < 0) { + printk(LOG_LEVEL_MUTE, "libfdt fdt_del_mem_rsv(): %s\n", fdt_strerror(err)); + return 0; + } + } else { + uart_puts(cmd_fdt_usage); + return 0; + } + } else { + uart_puts(cmd_fdt_usage); + return 0; + } + return 0; +} + +msh_declare_command(reload); +msh_define_help(reload, "rescan TF Card and reload DTB", + "Usage: reload\n"); +int cmd_reload(int argc, const char **argv) { + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + return 0; + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + return 0; + } + return 0; +} + +const msh_command_entry commands[] = { + msh_define_command(fdt), + msh_define_command(reload), + msh_command_end, +}; + +int main(void) { + /* Initialize UART debug interface */ + sunxi_serial_init(&uart_dbg); + + /* Print boot screen */ + show_banner(); + + /* Initialize clock */ + sunxi_clk_init(); + + /* Initialize DRAM */ + sunxi_dram_init(&dram_para); + + /* Print clock information */ + sunxi_clk_dump(); + + /* Clear image structure */ + memset(&image, 0, sizeof(image_info_t)); + + /* Set the target address of image to DTB load address */ + image.dest = (uint8_t *) CONFIG_DTB_LOADADDR; + + /* Copy the DTB filename to the image structure */ + strcpy(image.filename, CONFIG_DTB_FILENAME); + + /* Initialize SD card controller */ + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + goto _shell; + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + + /* Initialize SD card */ + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + goto _shell; + } + + /* Load DTB file from SD card */ + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + goto _shell; + } + + /* Force image.dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.dest; + + int err = 0; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + goto _shell; + } + + /* Get the total size of DTB */ + uint32_t size = fdt_totalsize(image.dest); + printk(LOG_LEVEL_INFO, "DTB FDT Size = 0x%x\n", size); + +_shell: + syterkit_shell_attach(commands); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/fdt_parser/CMakeLists.txt b/board/yuzukilizard/fdt_parser/CMakeLists.txt new file mode 100644 index 00000000..8014f0ea --- /dev/null +++ b/board/yuzukilizard/fdt_parser/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(fdtparser + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/fdt_parser/main.c b/board/yuzukilizard/fdt_parser/main.c new file mode 100644 index 00000000..3441fd4c --- /dev/null +++ b/board/yuzukilizard/fdt_parser/main.c @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" + +#include "ff.h" +#include "libfdt.h" +#include "fdt_wrapper.h" + +#define CONFIG_DTB_FILENAME "sunxi.dtb" +#define CONFIG_DTB_LOADADDR (0x41008000) + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; + +sunxi_serial_t uart_e907 = { + .base = 0x02500C00, + .id = 3, + .gpio_tx = {GPIO_PIN(GPIO_PORTE, 0), GPIO_PERIPH_MUX7}, + .gpio_rx = {GPIO_PIN(GPIO_PORTE, 1), GPIO_PERIPH_MUX7}, +}; + +extern sdhci_t sdhci0; + +#define FILENAME_MAX_LEN 64 +typedef struct { + unsigned int offset; + unsigned int length; + unsigned char *dest; + + char filename[FILENAME_MAX_LEN]; +} image_info_t; + +image_info_t image; + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: open, filename: [%s]: error %d\n", filename, fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, + CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, + (unsigned int) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + + + +int main(void) { + /* Initialize UART debug interface */ + sunxi_serial_init(&uart_dbg); + + /* Print boot screen */ + show_banner(); + + /* Initialize clock */ + sunxi_clk_init(); + + /* Initialize DRAM */ + sunxi_dram_init(&dram_para); + + /* Print clock information */ + sunxi_clk_dump(); + + /* Clear image structure */ + memset(&image, 0, sizeof(image_info_t)); + + /* Set the target address of image to DTB load address */ + image.dest = (uint8_t *) CONFIG_DTB_LOADADDR; + + /* Copy the DTB filename to the image structure */ + strcpy(image.filename, CONFIG_DTB_FILENAME); + + /* Initialize SD card controller */ + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + return 0; + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + + /* Initialize SD card */ + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + return 0; + } + + /* Load DTB file from SD card */ + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + return 0; + } + + /* Force image.dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.dest; + + int err = 0; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + return -1; + } + + /* Get the total size of DTB */ + uint32_t size = fdt_totalsize(image.dest); + printk(LOG_LEVEL_INFO, "DTB FDT Size = 0x%x\n", size); + + /* Print all device tree nodes */ + fdt_print(image.dest, "/", NULL, MAX_LEVEL); + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_INFO, "DTB OLD bootargs = \"%s\"\n", bootargs_str); + + /* New bootargs string */ + char *new_bootargs_str = "earlyprintk=sunxi-uart,0x02500C00 root=/dev/mmcblk0p3 rootwait loglevel=8 initcall_debug=0 console=ttyS0 init=/init"; + printk(LOG_LEVEL_INFO, "Now set bootargs to \"%s\"\n", new_bootargs_str); + + /* Modify bootargs string */ + err = fdt_setprop(image.dest, bootargs_node, "bootargs", new_bootargs_str, strlen(new_bootargs_str) + 1); + + if (err < 0) { + printk(LOG_LEVEL_ERROR, "libfdt fdt_setprop() error: %s\n", fdt_strerror(err)); + abort(); + } + + /* Get updated bootargs string */ + char *updated_bootargs_str = (void *) fdt_getprop(image.dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_INFO, "DTB NEW bootargs = \"%s\"\n", updated_bootargs_str); + + /* Terminate program execution */ + abort(); + + /* Jump to FEL mode execution */ + jmp_to_fel(); + + return 0; +} diff --git a/board/yuzukilizard/hello_world/CMakeLists.txt b/board/yuzukilizard/hello_world/CMakeLists.txt new file mode 100644 index 00000000..b5ce1ea5 --- /dev/null +++ b/board/yuzukilizard/hello_world/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(helloworld + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/hello_world/main.c b/board/yuzukilizard/hello_world/main.c new file mode 100644 index 00000000..b588126a --- /dev/null +++ b/board/yuzukilizard/hello_world/main.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +extern sunxi_serial_t uart_dbg; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + printk(LOG_LEVEL_INFO, "Hello World!\n"); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/i2c_oled/CMakeLists.txt b/board/yuzukilizard/i2c_oled/CMakeLists.txt new file mode 100644 index 00000000..c0ae01a5 --- /dev/null +++ b/board/yuzukilizard/i2c_oled/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(i2c_oled + main.c + oled.c +) \ No newline at end of file diff --git a/board/yuzukilizard/i2c_oled/main.c b/board/yuzukilizard/i2c_oled/main.c new file mode 100644 index 00000000..0a9d11ac --- /dev/null +++ b/board/yuzukilizard/i2c_oled/main.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include + +#include "sys-uart.h" + +#include "oled.h" + +extern sunxi_serial_t uart_dbg; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + printk(LOG_LEVEL_INFO, "Hello World\n"); + + OLED_Init(); + + OLED_ShowString(12, 16, "SyterKit", 16, 1); + OLED_ShowString(20, 32, "I2C OLED", 16, 1); + + OLED_Refresh(); + + abort(); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/i2c_oled/oled.c b/board/yuzukilizard/i2c_oled/oled.c new file mode 100644 index 00000000..d853dc03 --- /dev/null +++ b/board/yuzukilizard/i2c_oled/oled.c @@ -0,0 +1,272 @@ +#include +#include +#include +#include + +#include + +#include + +#include "sys-i2c.h" + +#include "oledfont.h" + +#define OLED_IIC_ADDR 0x3c +#define OLED_IIC_GPIO_PORT 0 + +#define OLED_CMD 0 /*写命令 */ +#define OLED_DATA 1 /* 写数据 */ + +uint8_t OLED_GRAM[144][8]; /* 显存 */ + +sunxi_i2c_t i2c_0 = { + .base = 0x02502000, + .id = 0, + .speed = 4000000, + .gpio_scl = {GPIO_PIN(GPIO_PORTE, 4), GPIO_PERIPH_MUX8}, + .gpio_sda = {GPIO_PIN(GPIO_PORTE, 5), GPIO_PERIPH_MUX8}, +}; + +void OLED_WR_Byte(uint8_t dat, uint8_t mode) { + if (mode) + sunxi_i2c_write(&i2c_0, OLED_IIC_ADDR, 0x40, dat); + else + sunxi_i2c_write(&i2c_0, OLED_IIC_ADDR, 0x00, dat); +} + +uint32_t OLED_Pow(uint8_t m, uint8_t n) { + uint32_t result = 1; + while (n--) + result *= m; + return result; +} + +void OLED_ColorTurn(uint8_t i) { + if (i == 0) { + OLED_WR_Byte(0xA6, OLED_CMD); /* 正常显示 */ + } + if (i == 1) { + OLED_WR_Byte(0xA7, OLED_CMD); /* 反色显示 */ + } +} + +void OLED_DisplayTurn(uint8_t i) { + if (i == 0) { + OLED_WR_Byte(0xC8, OLED_CMD); /* 正常显示 */ + OLED_WR_Byte(0xA1, OLED_CMD); + } + if (i == 1) { + OLED_WR_Byte(0xC0, OLED_CMD); /* 反转显示 */ + OLED_WR_Byte(0xA0, OLED_CMD); + } +} + +void OLED_Refresh(void) { + for (int i = 0; i < 8; i++) { + OLED_WR_Byte(0xb0 + i, OLED_CMD);//设置行起始地址 + OLED_WR_Byte(0x00, OLED_CMD); //设置低列起始地址 + OLED_WR_Byte(0x10, OLED_CMD); //设置高列起始地址 + OLED_WR_Byte(0x78, OLED_DATA); + OLED_WR_Byte(0x40, OLED_DATA); + for (int n = 0; n < 128; n++) { + OLED_WR_Byte(OLED_GRAM[n][i], OLED_DATA); + } + } +} + +void OLED_Clear(void) { + for (int i = 0; i < 8; i++) { + OLED_WR_Byte(0xb0 + i, OLED_CMD);//设置页地址(0~7) + OLED_WR_Byte(0x00, OLED_CMD); //设置显示位置—列低地址 + OLED_WR_Byte(0x10, OLED_CMD); //设置显示位置—列高地址 + for (int n = 0; n < 128; n++) + OLED_GRAM[n][i] = 0; + OLED_Refresh();//刷新GRAM内容 + } +} + +void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t) { + uint8_t i, m, n; + i = y / 8; + m = y % 8; + n = 1 << m; + if (t) { + OLED_GRAM[x][i] |= n; + } else { + OLED_GRAM[x][i] = ~OLED_GRAM[x][i]; + OLED_GRAM[x][i] |= n; + OLED_GRAM[x][i] = ~OLED_GRAM[x][i]; + } +} + +void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode) { + int xerr = 0, yerr = 0, delta_x, delta_y, distance; + int incx, incy, uRow, uCol; + delta_x = x2 - x1;//计算坐标增量 + delta_y = y2 - y1; + uRow = x1;//画线起点坐标 + uCol = y1; + if (delta_x > 0) + incx = 1;//设置单步方向 + else if (delta_x == 0) + incx = 0;//垂直线 + else { + incx = -1; + delta_x = -delta_x; + } + if (delta_y > 0) + incy = 1; + else if (delta_y == 0) + incy = 0;//水平线 + else { + incy = -1; + delta_y = -delta_x; + } + if (delta_x > delta_y) + distance = delta_x;//选取基本增量坐标轴 + else + distance = delta_y; + for (uint16_t t = 0; t < distance + 1; t++) { + OLED_DrawPoint(uRow, uCol, mode);//画点 + xerr += delta_x; + yerr += delta_y; + if (xerr > distance) { + xerr -= distance; + uRow += incx; + } + if (yerr > distance) { + yerr -= distance; + uCol += incy; + } + } +} + +void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r) { + int a, b, num; + a = 0; + b = r; + while (2 * b * b >= r * r) { + OLED_DrawPoint(x + a, y - b, 1); + OLED_DrawPoint(x - a, y - b, 1); + OLED_DrawPoint(x - a, y + b, 1); + OLED_DrawPoint(x + a, y + b, 1); + + OLED_DrawPoint(x + b, y + a, 1); + OLED_DrawPoint(x + b, y - a, 1); + OLED_DrawPoint(x - b, y - a, 1); + OLED_DrawPoint(x - b, y + a, 1); + + a++; + num = (a * a + b * b) - r * r;//计算画的点离圆心的距离 + if (num > 0) { + b--; + a--; + } + } +} + +void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode) { + uint8_t temp, size2, chr1; + uint8_t x0 = x, y0 = y; + if (size1 == 8) + size2 = 6; + else + size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2);//得到字体一个字符对应点阵集所占的字节数 + chr1 = chr - ' '; //计算偏移后的值 + for (uint8_t i = 0; i < size2; i++) { + if (size1 == 8) { + temp = asc2_0806[chr1][i]; + }//调用0806字体 + else if (size1 == 12) { + temp = asc2_1206[chr1][i]; + }//调用1206字体 + else if (size1 == 16) { + temp = asc2_1608[chr1][i]; + }//调用1608字体 + else if (size1 == 24) { + temp = asc2_2412[chr1][i]; + }//调用2412字体 + else + return; + for (uint8_t m = 0; m < 8; m++) { + if (temp & 0x01) + OLED_DrawPoint(x, y, mode); + else + OLED_DrawPoint(x, y, !mode); + temp >>= 1; + y++; + } + x++; + if ((size1 != 8) && ((x - x0) == size1 / 2)) { + x = x0; + y0 = y0 + 8; + } + y = y0; + } +} + +void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size1, uint8_t mode) { + while ((*chr >= ' ') && (*chr <= '~'))//判断是不是非法字符! + { + OLED_ShowChar(x, y, *chr, size1, mode); + if (size1 == 8) + x += 6; + else + x += size1 / 2; + chr++; + } +} + +void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode) { + uint8_t temp, m = 0; + if (size1 == 8) + m = 2; + for (uint8_t t = 0; t < len; t++) { + temp = (num / OLED_Pow(10, len - t - 1)) % 10; + if (temp == 0) { + OLED_ShowChar(x + (size1 / 2 + m) * t, y, '0', size1, mode); + } else { + OLED_ShowChar(x + (size1 / 2 + m) * t, y, temp + '0', size1, mode); + } + } +} + +void OLED_Set_Pos(uint8_t x, uint8_t y) { + OLED_WR_Byte(0xb0 + y, OLED_CMD); + OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD); + OLED_WR_Byte((x & 0x0f), OLED_CMD); +} + +void OLED_Init(void) { + sunxi_i2c_init(&i2c_0); // Init I2C + + OLED_WR_Byte(0xAE, OLED_CMD);//--turn off oled panel + OLED_WR_Byte(0x00, OLED_CMD);//---set low column address + OLED_WR_Byte(0x10, OLED_CMD);//---set high column address + OLED_WR_Byte(0x40, OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) + OLED_WR_Byte(0x81, OLED_CMD);//--set contrast control register + OLED_WR_Byte(0xCF, OLED_CMD);// Set SEG Output Current Brightness + OLED_WR_Byte(0xA1, OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 + OLED_WR_Byte(0xC8, OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 + OLED_WR_Byte(0xA6, OLED_CMD);//--set normal display + OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64) + OLED_WR_Byte(0x3f, OLED_CMD);//--1/64 duty + OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) + OLED_WR_Byte(0x00, OLED_CMD);//-not offset + OLED_WR_Byte(0xd5, OLED_CMD);//--set display clock divide ratio/oscillator frequency + OLED_WR_Byte(0x80, OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec + OLED_WR_Byte(0xD9, OLED_CMD);//--set pre-charge period + OLED_WR_Byte(0xF1, OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock + OLED_WR_Byte(0xDA, OLED_CMD);//--set com pins hardware configuration + OLED_WR_Byte(0x12, OLED_CMD); + OLED_WR_Byte(0xDB, OLED_CMD);//--set vcomh + OLED_WR_Byte(0x40, OLED_CMD);//Set VCOM Deselect Level + OLED_WR_Byte(0x20, OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02) + OLED_WR_Byte(0x02, OLED_CMD);// + OLED_WR_Byte(0x8D, OLED_CMD);//--set Charge Pump enable/disable + OLED_WR_Byte(0x14, OLED_CMD);//--set(0x10) disable + OLED_WR_Byte(0xA4, OLED_CMD);// Disable Entire Display On (0xa4/0xa5) + OLED_WR_Byte(0xA6, OLED_CMD);// Disable Inverse Display On (0xa6/a7) + OLED_Clear(); + OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/ +} \ No newline at end of file diff --git a/board/yuzukilizard/i2c_oled/oled.h b/board/yuzukilizard/i2c_oled/oled.h new file mode 100644 index 00000000..5b7f8456 --- /dev/null +++ b/board/yuzukilizard/i2c_oled/oled.h @@ -0,0 +1,74 @@ +#ifndef __OLED_H +#define __OLED_H + +/* 发送一个字节 + * mode:数据/命令标志 0,表示命令;1,表示数据; + */ +void OLED_WR_Byte(uint8_t dat, uint8_t mode); + +/* Pow 函数 */ +uint32_t OLED_Pow(uint8_t m, uint8_t n); + +/* 反显函数 */ +void OLED_ColorTurn(uint8_t i); + +/* 屏幕旋转180度 */ +void OLED_DisplayTurn(uint8_t i); + +/* 更新显存到OLED */ +void OLED_Refresh(void); + +/* OLED 清屏 */ +void OLED_Clear(void); + +/* 画点 + * x: 0~127 + * y: 0~63 + * t: 1 填充 0,清空 + */ +void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t); + +/* 画线 + * x1, y1: 起点坐标 + * x2, y2: 结束坐标 + */ +void OLED_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode); + +/* 画圆 + * x, y: 圆心坐标 + * r: 圆的半径 + */ + +void OLED_DrawCircle(uint8_t x, uint8_t y, uint8_t r); + +/* 在指定位置显示一个字符,包括部分字符 + * x: 0 ~ 127 + * y: 0 ~ 63 + * size1: 选择字体 6x8/6x12/8x16/12x24 + * mode: 0,反色显示; 1,正常显示 + */ +void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode); + +/* 显示字符串 + * x: 0 ~ 127 + * y: 0 ~ 63 + * *chr: 字符串起始地址 + * size1: 选择字体 6x8/6x12/8x16/12x24 + * mode: 0,反色显示; 1,正常显示 + */ +void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size1, uint8_t mode); + +/* 显示数字 + * x: 0 ~ 127 + * y: 0 ~ 63 + * num: 要显示的数字 + * len: 数字的位数 + * size1: 选择字体 6x8/6x12/8x16/12x24 + * mode: 0,反色显示; 1,正常显示 + */ +void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode); + +/* 初始化 OLED */ +void OLED_Init(void); + +#endif \ No newline at end of file diff --git a/board/yuzukilizard/i2c_oled/oledfont.h b/board/yuzukilizard/i2c_oled/oledfont.h new file mode 100644 index 00000000..64547cc6 --- /dev/null +++ b/board/yuzukilizard/i2c_oled/oledfont.h @@ -0,0 +1,392 @@ +#ifndef __OLEDFONT_H +#define __OLEDFONT_H +const unsigned char asc2_0806[][6] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp + { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! + { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // " + { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # + { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ + { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // % + { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // & + { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( + { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) + { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * + { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // , + { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // - + { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // . + { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // / + { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 + { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 + { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 + { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 + { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 + { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 + { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 + { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 + { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 + { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 + { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; + { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // < + { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // = + { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // > + { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? + { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ + { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C + { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F + { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G + { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H + { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I + { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J + { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K + { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L + { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M + { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P + { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q + { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R + { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S + { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T + { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U + { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V + { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W + { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X + { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y + { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z + { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ + { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55 + { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] + { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ + { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ + { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' + { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a + { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c + { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d + { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e + { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f + { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g + { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h + { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i + { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j + { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k + { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l + { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o + { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p + { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r + { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s + { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t + { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u + { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v + { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w + { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x + { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y + { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z + { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }, // horiz lines +}; +//12*12 ASCII字符集点阵 +const unsigned char asc2_1206[95][12] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*" ",0*/ + { 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, /*"!",1*/ + { 0x00, 0x0C, 0x02, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*""",2*/ + { 0x90, 0xD0, 0xBC, 0xD0, 0xBC, 0x90, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00 }, /*"#",3*/ + { 0x18, 0x24, 0xFE, 0x44, 0x8C, 0x00, 0x03, 0x02, 0x07, 0x02, 0x01, 0x00 }, /*"$",4*/ + { 0x18, 0x24, 0xD8, 0xB0, 0x4C, 0x80, 0x00, 0x03, 0x00, 0x01, 0x02, 0x01 }, /*"%",5*/ + { 0xC0, 0x38, 0xE4, 0x38, 0xE0, 0x00, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02 }, /*"&",6*/ + { 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"'",7*/ + { 0x00, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04 }, /*"(",8*/ + { 0x00, 0x02, 0x04, 0xF8, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00 }, /*")",9*/ + { 0x90, 0x60, 0xF8, 0x60, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }, /*"*",10*/ + { 0x20, 0x20, 0xFC, 0x20, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }, /*"+",11*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00 }, /*",",12*/ + { 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"-",13*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, /*".",14*/ + { 0x00, 0x80, 0x60, 0x1C, 0x02, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00 }, /*"/",15*/ + { 0xF8, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"0",16*/ + { 0x00, 0x08, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x00, 0x00 }, /*"1",17*/ + { 0x18, 0x84, 0x44, 0x24, 0x18, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x00 }, /*"2",18*/ + { 0x08, 0x04, 0x24, 0x24, 0xD8, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"3",19*/ + { 0x40, 0xB0, 0x88, 0xFC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00 }, /*"4",20*/ + { 0x3C, 0x24, 0x24, 0x24, 0xC4, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"5",21*/ + { 0xF8, 0x24, 0x24, 0x2C, 0xC0, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"6",22*/ + { 0x0C, 0x04, 0xE4, 0x1C, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 }, /*"7",23*/ + { 0xD8, 0x24, 0x24, 0x24, 0xD8, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"8",24*/ + { 0x38, 0x44, 0x44, 0x44, 0xF8, 0x00, 0x00, 0x03, 0x02, 0x02, 0x01, 0x00 }, /*"9",25*/ + { 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, /*":",26*/ + { 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 }, /*";",27*/ + { 0x00, 0x20, 0x50, 0x88, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02 }, /*"<",28*/ + { 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"=",29*/ + { 0x00, 0x02, 0x04, 0x88, 0x50, 0x20, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00 }, /*">",30*/ + { 0x18, 0x04, 0xC4, 0x24, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, /*"?",31*/ + { 0xF8, 0x04, 0xE4, 0x94, 0xF8, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 }, /*"@",32*/ + { 0x00, 0xE0, 0x9C, 0xF0, 0x80, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02 }, /*"A",33*/ + { 0x04, 0xFC, 0x24, 0x24, 0xD8, 0x00, 0x02, 0x03, 0x02, 0x02, 0x01, 0x00 }, /*"B",34*/ + { 0xF8, 0x04, 0x04, 0x04, 0x0C, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"C",35*/ + { 0x04, 0xFC, 0x04, 0x04, 0xF8, 0x00, 0x02, 0x03, 0x02, 0x02, 0x01, 0x00 }, /*"D",36*/ + { 0x04, 0xFC, 0x24, 0x74, 0x0C, 0x00, 0x02, 0x03, 0x02, 0x02, 0x03, 0x00 }, /*"E",37*/ + { 0x04, 0xFC, 0x24, 0x74, 0x0C, 0x00, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00 }, /*"F",38*/ + { 0xF0, 0x08, 0x04, 0x44, 0xCC, 0x40, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00 }, /*"G",39*/ + { 0x04, 0xFC, 0x20, 0x20, 0xFC, 0x04, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02 }, /*"H",40*/ + { 0x04, 0x04, 0xFC, 0x04, 0x04, 0x00, 0x02, 0x02, 0x03, 0x02, 0x02, 0x00 }, /*"I",41*/ + { 0x00, 0x04, 0x04, 0xFC, 0x04, 0x04, 0x06, 0x04, 0x04, 0x03, 0x00, 0x00 }, /*"J",42*/ + { 0x04, 0xFC, 0x24, 0xD0, 0x0C, 0x04, 0x02, 0x03, 0x02, 0x00, 0x03, 0x02 }, /*"K",43*/ + { 0x04, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03 }, /*"L",44*/ + { 0xFC, 0x3C, 0xC0, 0x3C, 0xFC, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00 }, /*"M",45*/ + { 0x04, 0xFC, 0x30, 0xC4, 0xFC, 0x04, 0x02, 0x03, 0x02, 0x00, 0x03, 0x00 }, /*"N",46*/ + { 0xF8, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"O",47*/ + { 0x04, 0xFC, 0x24, 0x24, 0x18, 0x00, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00 }, /*"P",48*/ + { 0xF8, 0x84, 0x84, 0x04, 0xF8, 0x00, 0x01, 0x02, 0x02, 0x07, 0x05, 0x00 }, /*"Q",49*/ + { 0x04, 0xFC, 0x24, 0x64, 0x98, 0x00, 0x02, 0x03, 0x02, 0x00, 0x03, 0x02 }, /*"R",50*/ + { 0x18, 0x24, 0x24, 0x44, 0x8C, 0x00, 0x03, 0x02, 0x02, 0x02, 0x01, 0x00 }, /*"S",51*/ + { 0x0C, 0x04, 0xFC, 0x04, 0x0C, 0x00, 0x00, 0x02, 0x03, 0x02, 0x00, 0x00 }, /*"T",52*/ + { 0x04, 0xFC, 0x00, 0x00, 0xFC, 0x04, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00 }, /*"U",53*/ + { 0x04, 0x7C, 0x80, 0xE0, 0x1C, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 }, /*"V",54*/ + { 0x1C, 0xE0, 0x3C, 0xE0, 0x1C, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00 }, /*"W",55*/ + { 0x04, 0x9C, 0x60, 0x9C, 0x04, 0x00, 0x02, 0x03, 0x00, 0x03, 0x02, 0x00 }, /*"X",56*/ + { 0x04, 0x1C, 0xE0, 0x1C, 0x04, 0x00, 0x00, 0x02, 0x03, 0x02, 0x00, 0x00 }, /*"Y",57*/ + { 0x0C, 0x84, 0x64, 0x1C, 0x04, 0x00, 0x02, 0x03, 0x02, 0x02, 0x03, 0x00 }, /*"Z",58*/ + { 0x00, 0x00, 0xFE, 0x02, 0x02, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00 }, /*"[",59*/ + { 0x00, 0x0E, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00 }, /*"\",60*/ + { 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x00, 0x00 }, /*"]",61*/ + { 0x00, 0x04, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"^",62*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, /*"_",63*/ + { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"`",64*/ + { 0x00, 0x40, 0xA0, 0xA0, 0xC0, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x02 }, /*"a",65*/ + { 0x04, 0xFC, 0x20, 0x20, 0xC0, 0x00, 0x00, 0x03, 0x02, 0x02, 0x01, 0x00 }, /*"b",66*/ + { 0x00, 0xC0, 0x20, 0x20, 0x60, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00 }, /*"c",67*/ + { 0x00, 0xC0, 0x20, 0x24, 0xFC, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x02 }, /*"d",68*/ + { 0x00, 0xC0, 0xA0, 0xA0, 0xC0, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00 }, /*"e",69*/ + { 0x00, 0x20, 0xF8, 0x24, 0x24, 0x04, 0x00, 0x02, 0x03, 0x02, 0x02, 0x00 }, /*"f",70*/ + { 0x00, 0x40, 0xA0, 0xA0, 0x60, 0x20, 0x00, 0x07, 0x0A, 0x0A, 0x0A, 0x04 }, /*"g",71*/ + { 0x04, 0xFC, 0x20, 0x20, 0xC0, 0x00, 0x02, 0x03, 0x02, 0x00, 0x03, 0x02 }, /*"h",72*/ + { 0x00, 0x20, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x00, 0x00 }, /*"i",73*/ + { 0x00, 0x00, 0x20, 0xE4, 0x00, 0x00, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00 }, /*"j",74*/ + { 0x04, 0xFC, 0x80, 0xE0, 0x20, 0x20, 0x02, 0x03, 0x02, 0x00, 0x03, 0x02 }, /*"k",75*/ + { 0x04, 0x04, 0xFC, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x02, 0x02, 0x00 }, /*"l",76*/ + { 0xE0, 0x20, 0xE0, 0x20, 0xC0, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00 }, /*"m",77*/ + { 0x20, 0xE0, 0x20, 0x20, 0xC0, 0x00, 0x02, 0x03, 0x02, 0x00, 0x03, 0x02 }, /*"n",78*/ + { 0x00, 0xC0, 0x20, 0x20, 0xC0, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00 }, /*"o",79*/ + { 0x20, 0xE0, 0x20, 0x20, 0xC0, 0x00, 0x08, 0x0F, 0x0A, 0x02, 0x01, 0x00 }, /*"p",80*/ + { 0x00, 0xC0, 0x20, 0x20, 0xE0, 0x00, 0x00, 0x01, 0x02, 0x0A, 0x0F, 0x08 }, /*"q",81*/ + { 0x20, 0xE0, 0x40, 0x20, 0x20, 0x00, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00 }, /*"r",82*/ + { 0x00, 0x60, 0xA0, 0xA0, 0x20, 0x00, 0x00, 0x02, 0x02, 0x02, 0x03, 0x00 }, /*"s",83*/ + { 0x00, 0x20, 0xF8, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00 }, /*"t",84*/ + { 0x20, 0xE0, 0x00, 0x20, 0xE0, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x02 }, /*"u",85*/ + { 0x20, 0xE0, 0x20, 0x80, 0x60, 0x20, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00 }, /*"v",86*/ + { 0x60, 0x80, 0xE0, 0x80, 0x60, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00 }, /*"w",87*/ + { 0x20, 0x60, 0x80, 0x60, 0x20, 0x00, 0x02, 0x03, 0x00, 0x03, 0x02, 0x00 }, /*"x",88*/ + { 0x20, 0xE0, 0x20, 0x80, 0x60, 0x20, 0x08, 0x08, 0x07, 0x01, 0x00, 0x00 }, /*"y",89*/ + { 0x00, 0x20, 0xA0, 0x60, 0x20, 0x00, 0x00, 0x02, 0x03, 0x02, 0x02, 0x00 }, /*"z",90*/ + { 0x00, 0x00, 0x20, 0xDE, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x00 }, /*"{",91*/ + { 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00 }, /*"|",92*/ + { 0x00, 0x02, 0xDE, 0x20, 0x00, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00 }, /*"}",93*/ + { 0x02, 0x01, 0x02, 0x04, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"~",94*/ +}; +//16*16 ASCII字符集点阵 +const unsigned char asc2_1608[][16] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*" ",0*/ + { 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00 }, /*"!",1*/ + { 0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*""",2*/ + { 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00 }, /*"#",3*/ + { 0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00 }, /*"$",4*/ + { 0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00 }, /*"%",5*/ + { 0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10 }, /*"&",6*/ + { 0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"'",7*/ + { 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00 }, /*"(",8*/ + { 0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00 }, /*")",9*/ + { 0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00 }, /*"*",10*/ + { 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00 }, /*"+",11*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*",",12*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, /*"-",13*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*".",14*/ + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00 }, /*"/",15*/ + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00 }, /*"0",16*/ + { 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, /*"1",17*/ + { 0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00 }, /*"2",18*/ + { 0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, /*"3",19*/ + { 0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00 }, /*"4",20*/ + { 0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00 }, /*"5",21*/ + { 0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, /*"6",22*/ + { 0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00 }, /*"7",23*/ + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00 }, /*"8",24*/ + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00 }, /*"9",25*/ + { 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00 }, /*":",26*/ + { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00 }, /*";",27*/ + { 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 }, /*"<",28*/ + { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00 }, /*"=",29*/ + { 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 }, /*">",30*/ + { 0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00 }, /*"?",31*/ + { 0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00 }, /*"@",32*/ + { 0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20 }, /*"A",33*/ + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, /*"B",34*/ + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00 }, /*"C",35*/ + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, /*"D",36*/ + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00 }, /*"E",37*/ + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00 }, /*"F",38*/ + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00 }, /*"G",39*/ + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20 }, /*"H",40*/ + { 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, /*"I",41*/ + { 0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00 }, /*"J",42*/ + { 0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00 }, /*"K",43*/ + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00 }, /*"L",44*/ + { 0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00 }, /*"M",45*/ + { 0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00 }, /*"N",46*/ + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, /*"O",47*/ + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00 }, /*"P",48*/ + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00 }, /*"Q",49*/ + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20 }, /*"R",50*/ + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00 }, /*"S",51*/ + { 0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, /*"T",52*/ + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, /*"U",53*/ + { 0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00 }, /*"V",54*/ + { 0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00 }, /*"W",55*/ + { 0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20 }, /*"X",56*/ + { 0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, /*"Y",57*/ + { 0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00 }, /*"Z",58*/ + { 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00 }, /*"[",59*/ + { 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00 }, /*"\",60*/ + { 0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00 }, /*"]",61*/ + { 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"^",62*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, /*"_",63*/ + { 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"`",64*/ + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20 }, /*"a",65*/ + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, /*"b",66*/ + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00 }, /*"c",67*/ + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20 }, /*"d",68*/ + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00 }, /*"e",69*/ + { 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, /*"f",70*/ + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00 }, /*"g",71*/ + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, /*"h",72*/ + { 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, /*"i",73*/ + { 0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00 }, /*"j",74*/ + { 0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00 }, /*"k",75*/ + { 0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, /*"l",76*/ + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F }, /*"m",77*/ + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, /*"n",78*/ + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, /*"o",79*/ + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00 }, /*"p",80*/ + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80 }, /*"q",81*/ + { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00 }, /*"r",82*/ + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00 }, /*"s",83*/ + { 0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00 }, /*"t",84*/ + { 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20 }, /*"u",85*/ + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00 }, /*"v",86*/ + { 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00 }, /*"w",87*/ + { 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00 }, /*"x",88*/ + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00 }, /*"y",89*/ + { 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00 }, /*"z",90*/ + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40 }, /*"{",91*/ + { 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, /*"|",92*/ + { 0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00 }, /*"}",93*/ + { 0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"~",94*/ +}; +//24*24 ASICII字符集点阵 +const unsigned char asc2_2412[][36] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*" ",0*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00 }, /*"!",1*/ + { 0x00, 0x00, 0x80, 0x60, 0x30, 0x1C, 0x8C, 0x60, 0x30, 0x1C, 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 }, /*""",2*/ + { 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x86, 0xE6, 0x9F, 0x86, 0x86, 0x86, 0x86, 0xE6, 0x9F, 0x86, 0x00, 0x00, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x00 }, /*"#",3*/ + { 0x00, 0x00, 0x80, 0xC0, 0x60, 0x20, 0xF8, 0x20, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0C, 0x18, 0xFF, 0x70, 0xE1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x10, 0x10, 0x7F, 0x10, 0x0F, 0x07, 0x00, 0x00 }, /*"$",4*/ + { 0x80, 0x60, 0x20, 0x60, 0x80, 0x00, 0x00, 0x00, 0xE0, 0x20, 0x00, 0x00, 0x0F, 0x30, 0x20, 0x30, 0x9F, 0x70, 0xDC, 0x37, 0x10, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x03, 0x00, 0x07, 0x18, 0x10, 0x18, 0x07, 0x00 }, /*"%",5*/ + { 0x00, 0x00, 0xC0, 0x20, 0x20, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x1F, 0x38, 0xE8, 0x87, 0x03, 0xC4, 0x3C, 0x04, 0x00, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x10, 0x0B, 0x07, 0x0D, 0x10, 0x10, 0x08, 0x00 }, /*"&",6*/ + { 0x00, 0x80, 0x8C, 0x4C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"'",7*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x30, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x18, 0x20, 0x40, 0x00 }, /*"(",8*/ + { 0x00, 0x04, 0x08, 0x30, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*")",9*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x66, 0x66, 0x3C, 0x18, 0xFF, 0x18, 0x3C, 0x66, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"*",10*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"+",11*/ + { 0x00, 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, 0x8C, 0x4C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*",",12*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"-",13*/ + { 0x00, 0x00, 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, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*".",14*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x38, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x70, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x38, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"/",15*/ + { 0x00, 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0x07, 0x0E, 0x18, 0x10, 0x10, 0x18, 0x0E, 0x07, 0x01, 0x00 }, /*"0",16*/ + { 0x00, 0x00, 0x80, 0x80, 0x80, 0xC0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, 0x00 }, /*"1",17*/ + { 0x00, 0x80, 0x40, 0x20, 0x20, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x80, 0x40, 0x20, 0x38, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x1C, 0x1A, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00 }, /*"2",18*/ + { 0x00, 0x80, 0xC0, 0x20, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x10, 0x10, 0x18, 0x2F, 0xE7, 0x80, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07, 0x00, 0x00 }, /*"3",19*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xB0, 0x88, 0x86, 0x81, 0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x00 }, /*"4",20*/ + { 0x00, 0x00, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x10, 0x08, 0x08, 0x08, 0x18, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x07, 0x0B, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x0F, 0x03, 0x00, 0x00 }, /*"5",21*/ + { 0x00, 0x00, 0x80, 0xC0, 0x40, 0x20, 0x20, 0x20, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x21, 0x10, 0x08, 0x08, 0x08, 0x18, 0xF0, 0xE0, 0x00, 0x00, 0x01, 0x07, 0x0C, 0x18, 0x10, 0x10, 0x10, 0x08, 0x0F, 0x03, 0x00 }, /*"6",22*/ + { 0x00, 0x00, 0xC0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xE0, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"7",23*/ + { 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x87, 0xEF, 0x2C, 0x18, 0x18, 0x30, 0x30, 0x68, 0xCF, 0x83, 0x00, 0x00, 0x07, 0x0F, 0x08, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07, 0x00 }, /*"8",24*/ + { 0x00, 0x00, 0xC0, 0xC0, 0x20, 0x20, 0x20, 0x20, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x60, 0x40, 0x40, 0x40, 0x20, 0x10, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x0C, 0x1C, 0x10, 0x10, 0x10, 0x08, 0x0F, 0x03, 0x00, 0x00 }, /*"9",25*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00 }, /*":",26*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*";",27*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00 }, /*"<",28*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"=",29*/ + { 0x00, 0x00, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*">",30*/ + { 0x00, 0xC0, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x30, 0xE0, 0xC0, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0xF0, 0x10, 0x08, 0x0C, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"?",31*/ + { 0x00, 0x00, 0x00, 0xC0, 0x40, 0x60, 0x20, 0x20, 0x20, 0x40, 0xC0, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0xF0, 0x0E, 0x03, 0xC1, 0xFE, 0x03, 0x80, 0x7F, 0x00, 0x01, 0x07, 0x0E, 0x08, 0x11, 0x11, 0x10, 0x11, 0x09, 0x04, 0x02 }, /*"@",32*/ + { 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x43, 0x40, 0x47, 0x7F, 0xF8, 0x80, 0x00, 0x00, 0x10, 0x18, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0x1F, 0x1C, 0x10 }, /*"A",33*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x18, 0x2F, 0xE7, 0x80, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07, 0x00 }, /*"B",34*/ + { 0x00, 0x00, 0x80, 0xC0, 0x40, 0x20, 0x20, 0x20, 0x20, 0x60, 0xE0, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x07, 0x0E, 0x18, 0x10, 0x10, 0x10, 0x08, 0x04, 0x03, 0x00 }, /*"C",35*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x18, 0x08, 0x0E, 0x07, 0x01, 0x00 }, /*"D",36*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x06, 0x00 }, /*"E",37*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x60, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, 0x01, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"F",38*/ + { 0x00, 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x20, 0x40, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x01, 0x00, 0x00, 0x40, 0x40, 0xC0, 0xC1, 0x40, 0x40, 0x00, 0x01, 0x07, 0x0E, 0x18, 0x10, 0x10, 0x10, 0x0F, 0x0F, 0x00, 0x00 }, /*"G",39*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0xE0, 0xE0, 0x20, 0x00, 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0xFF, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10 }, /*"H",40*/ + { 0x00, 0x00, 0x20, 0x20, 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, 0x00 }, /*"I",41*/ + { 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x60, 0xE0, 0x80, 0x80, 0x80, 0xC0, 0x7F, 0x3F, 0x00, 0x00, 0x00 }, /*"J",42*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x20, 0xA0, 0x60, 0x20, 0x20, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x18, 0x7C, 0xE3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x01, 0x13, 0x1F, 0x1C, 0x18, 0x10 }, /*"K",43*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x06, 0x00 }, /*"L",44*/ + { 0x20, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0x20, 0x00, 0xFF, 0x01, 0x3F, 0xFE, 0xC0, 0xE0, 0x1E, 0x01, 0xFF, 0xFF, 0x00, 0x10, 0x1F, 0x10, 0x00, 0x03, 0x1F, 0x03, 0x00, 0x10, 0x1F, 0x1F, 0x10 }, /*"M",45*/ + { 0x20, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xE0, 0x20, 0x00, 0xFF, 0x00, 0x03, 0x07, 0x1C, 0x78, 0xE0, 0x80, 0x00, 0xFF, 0x00, 0x10, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x00 }, /*"N",46*/ + { 0x00, 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0x07, 0x0E, 0x18, 0x10, 0x10, 0x18, 0x0C, 0x07, 0x01, 0x00 }, /*"O",47*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x1F, 0x0F, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"P",48*/ + { 0x00, 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0x07, 0x0E, 0x11, 0x11, 0x13, 0x3C, 0x7C, 0x67, 0x21, 0x00 }, /*"Q",49*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0xC0, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x10, 0x30, 0xF0, 0xD0, 0x08, 0x0F, 0x07, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1C, 0x10, 0x10 }, /*"R",50*/ + { 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0xE0, 0x00, 0x00, 0x07, 0x0F, 0x0C, 0x18, 0x18, 0x30, 0x30, 0x60, 0xE0, 0x81, 0x00, 0x00, 0x1F, 0x0C, 0x08, 0x10, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07, 0x00 }, /*"S",51*/ + { 0x80, 0x60, 0x20, 0x20, 0x20, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00 }, /*"T",52*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xE0, 0x20, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x07, 0x00 }, /*"U",53*/ + { 0x20, 0x60, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x20, 0xE0, 0x60, 0x20, 0x00, 0x00, 0x07, 0x7F, 0xF8, 0x80, 0x00, 0x80, 0x7C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1F, 0x1C, 0x07, 0x00, 0x00, 0x00, 0x00 }, /*"V",54*/ + { 0x20, 0xE0, 0xE0, 0x20, 0x00, 0xE0, 0xE0, 0x20, 0x00, 0x20, 0xE0, 0x20, 0x00, 0x07, 0xFF, 0xF8, 0xE0, 0x1F, 0xFF, 0xFC, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0x03, 0x00, 0x01, 0x1F, 0x03, 0x00, 0x00, 0x00 }, /*"W",55*/ + { 0x00, 0x20, 0x60, 0xE0, 0xA0, 0x00, 0x00, 0x20, 0xE0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8F, 0x7C, 0xF8, 0xC6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x1E, 0x13, 0x00, 0x01, 0x17, 0x1F, 0x18, 0x10, 0x00 }, /*"X",56*/ + { 0x20, 0x60, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x20, 0xE0, 0x60, 0x20, 0x00, 0x00, 0x01, 0x07, 0x3E, 0xF8, 0xE0, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x00, 0x00, 0x00 }, /*"Y",57*/ + { 0x00, 0x80, 0x60, 0x20, 0x20, 0x20, 0x20, 0xA0, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0x3E, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x1F, 0x17, 0x10, 0x10, 0x10, 0x10, 0x18, 0x06, 0x00 }, /*"Z",58*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00 }, /*"[",59*/ + { 0x00, 0x00, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1C, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x70, 0x80, 0x00 }, /*"\",60*/ + { 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, 0x00 }, /*"]",61*/ + { 0x00, 0x00, 0x00, 0x10, 0x08, 0x0C, 0x04, 0x0C, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"^",62*/ + { 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, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, /*"_",63*/ + { 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 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 }, /*"`",64*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD8, 0x44, 0x64, 0x24, 0x24, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x18, 0x10, 0x10, 0x10, 0x08, 0x1F, 0x1F, 0x10, 0x18 }, /*"a",65*/ + { 0x00, 0x20, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x08, 0x04, 0x04, 0x0C, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0x0F, 0x18, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x03, 0x00 }, /*"b",66*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x18, 0x04, 0x04, 0x04, 0x3C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x08, 0x06, 0x00, 0x00 }, /*"c",67*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x1C, 0x04, 0x04, 0x04, 0x08, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x18, 0x10, 0x10, 0x10, 0x08, 0x1F, 0x0F, 0x08, 0x00 }, /*"d",68*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x48, 0x44, 0x44, 0x44, 0x4C, 0x78, 0x70, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0C, 0x18, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00 }, /*"e",69*/ + { 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0xE0, 0xC0, 0x00, 0x00, 0x04, 0x04, 0x04, 0xFF, 0xFF, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00 }, /*"f",70*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xF8, 0x8C, 0x04, 0x04, 0x8C, 0xF8, 0x74, 0x04, 0x0C, 0x00, 0x70, 0x76, 0xCF, 0x8D, 0x8D, 0x8D, 0x89, 0xC8, 0x78, 0x70, 0x00 }, /*"g",71*/ + { 0x00, 0x20, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x08, 0x04, 0x04, 0x04, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00 }, /*"h",72*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, 0x00 }, /*"i",73*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x80, 0x80, 0xC0, 0x7F, 0x3F, 0x00, 0x00, 0x00 }, /*"j",74*/ + { 0x00, 0x20, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0xC0, 0xF4, 0x1C, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x11, 0x00, 0x03, 0x1F, 0x1C, 0x10, 0x10, 0x00 }, /*"k",75*/ + { 0x00, 0x00, 0x20, 0x20, 0x20, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, 0x00 }, /*"l",76*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0xFC, 0x08, 0x04, 0xFC, 0xFC, 0x08, 0x04, 0xFC, 0xFC, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x1F, 0x1F, 0x10, 0x00, 0x1F, 0x1F, 0x10 }, /*"m",77*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0xFC, 0x08, 0x08, 0x04, 0x04, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00 }, /*"n",78*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0, 0x18, 0x0C, 0x04, 0x04, 0x0C, 0x18, 0xF0, 0xE0, 0x00, 0x00, 0x03, 0x0F, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x0F, 0x03, 0x00 }, /*"o",79*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0xFC, 0x08, 0x04, 0x04, 0x04, 0x0C, 0xF8, 0xF0, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x88, 0x90, 0x10, 0x10, 0x1C, 0x0F, 0x03, 0x00 }, /*"p",80*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x1C, 0x04, 0x04, 0x04, 0x08, 0xF8, 0xFC, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x18, 0x10, 0x10, 0x90, 0x88, 0xFF, 0xFF, 0x80, 0x00 }, /*"q",81*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0xFC, 0xFC, 0x10, 0x08, 0x04, 0x04, 0x0C, 0x0C, 0x00, 0x10, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00 }, /*"r",82*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0xCC, 0xC4, 0x84, 0x84, 0x84, 0x0C, 0x1C, 0x00, 0x00, 0x00, 0x1E, 0x18, 0x10, 0x10, 0x10, 0x11, 0x19, 0x0F, 0x06, 0x00 }, /*"s",83*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0xFF, 0xFF, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x0C, 0x00, 0x00 }, /*"t",84*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0xFE, 0x00, 0x00, 0x00, 0x04, 0xFC, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x18, 0x10, 0x10, 0x08, 0x1F, 0x0F, 0x08, 0x00 }, /*"u",85*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x3C, 0xFC, 0xC4, 0x00, 0x00, 0xC4, 0x3C, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x1E, 0x0E, 0x01, 0x00, 0x00, 0x00 }, /*"v",86*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3C, 0xFC, 0xC4, 0x00, 0xE4, 0x7C, 0xFC, 0x84, 0x80, 0x7C, 0x04, 0x00, 0x00, 0x07, 0x1F, 0x07, 0x00, 0x00, 0x07, 0x1F, 0x07, 0x00, 0x00 }, /*"w",87*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x1C, 0x7C, 0xE4, 0xC0, 0x34, 0x1C, 0x04, 0x04, 0x00, 0x00, 0x10, 0x10, 0x1C, 0x16, 0x01, 0x13, 0x1F, 0x1C, 0x18, 0x10, 0x00 }, /*"x",88*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x3C, 0xFC, 0xC4, 0x00, 0xC4, 0x3C, 0x04, 0x04, 0x00, 0x00, 0x00, 0xC0, 0x80, 0xC1, 0x37, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00 }, /*"y",89*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x04, 0x04, 0xC4, 0xF4, 0x7C, 0x1C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x1F, 0x17, 0x11, 0x10, 0x10, 0x18, 0x0E, 0x00 }, /*"z",90*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x60, 0x40, 0x00, 0x00 }, /*"{",91*/ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"|",92*/ + { 0x00, 0x00, 0x04, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*"}",93*/ + { 0x00, 0x18, 0x06, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x30, 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 }, /*"~",94*/ +}; + +#endif diff --git a/board/yuzukilizard/i2c_test/CMakeLists.txt b/board/yuzukilizard/i2c_test/CMakeLists.txt new file mode 100644 index 00000000..03fa1627 --- /dev/null +++ b/board/yuzukilizard/i2c_test/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(i2c_test + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/i2c_test/main.c b/board/yuzukilizard/i2c_test/main.c new file mode 100644 index 00000000..01a8f131 --- /dev/null +++ b/board/yuzukilizard/i2c_test/main.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include + +#include "sys-i2c.h" +#include "sys-uart.h" + +extern sunxi_serial_t uart_dbg; + +sunxi_i2c_t i2c_0 = { + .base = 0x02502000, + .id = 0, + .speed = 4000000, + .gpio_scl = {GPIO_PIN(GPIO_PORTE, 4), GPIO_PERIPH_MUX8}, + .gpio_sda = {GPIO_PIN(GPIO_PORTE, 5), GPIO_PERIPH_MUX8}, +}; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + sunxi_i2c_init(&i2c_0); + + printk(LOG_LEVEL_INFO, "Hello World\n"); + + int ret = 0; + + while (1) { + printk(LOG_LEVEL_INFO, "sunxi_i2c_write\n"); + ret = sunxi_i2c_write(&i2c_0, 0x32, 0x11, 0x11); + mdelay(100); + printk(LOG_LEVEL_INFO, "sunxi_i2c_write done, ret = %08x\n", ret); + } + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/init_dram/CMakeLists.txt b/board/yuzukilizard/init_dram/CMakeLists.txt new file mode 100644 index 00000000..c02c6d1e --- /dev/null +++ b/board/yuzukilizard/init_dram/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(initdram + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/init_dram/main.c b/board/yuzukilizard/init_dram/main.c new file mode 100644 index 00000000..aa251a43 --- /dev/null +++ b/board/yuzukilizard/init_dram/main.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include + +#include + +extern sunxi_serial_t uart_dbg; + + + +int main(void) { + sunxi_serial_init(&uart_dbg); + + show_banner(); + + sunxi_clk_init(); + + sunxi_dram_init(); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/load_e907/CMakeLists.txt b/board/yuzukilizard/load_e907/CMakeLists.txt new file mode 100644 index 00000000..457b306a --- /dev/null +++ b/board/yuzukilizard/load_e907/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(loade907 + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/load_e907/main.c b/board/yuzukilizard/load_e907/main.c new file mode 100644 index 00000000..0aae797b --- /dev/null +++ b/board/yuzukilizard/load_e907/main.c @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" + +#include "elf_loader.h" +#include "ff.h" + +#define CONFIG_RISCV_ELF_FILENAME "e907.elf" +#define CONFIG_RISCV_ELF_LOADADDR (0x41008000) + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +extern sunxi_serial_t uart_dbg; + +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; + +#define FILENAME_MAX_LEN 64 +typedef struct { + unsigned int offset; + unsigned int length; + unsigned char *dest; + + char filename[FILENAME_MAX_LEN]; +} image_info_t; + +image_info_t image; + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, + "FATFS: open, filename: [%s]: error %d\n", filename, + fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, + CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, + (unsigned int) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + +int main(void) { + sunxi_serial_init(&uart_dbg); + + show_banner(); + + sunxi_clk_init(); + + sunxi_dram_init(&dram_para); + + sunxi_clk_dump(); + + memset(&image, 0, sizeof(image_info_t)); + + image.dest = (uint8_t *) CONFIG_RISCV_ELF_LOADADDR; + + strcpy(image.filename, CONFIG_RISCV_ELF_FILENAME); + + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + return 0; + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + return 0; + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + return 0; + } + + sunxi_e907_clock_reset(); + + uint32_t elf_run_addr = elf32_get_entry_addr((phys_addr_t) image.dest); + printk(LOG_LEVEL_INFO, "RISC-V ELF run addr: 0x%08x\n", elf_run_addr); + + if (load_elf32_image((phys_addr_t) image.dest)) { + printk(LOG_LEVEL_ERROR, "RISC-V ELF load FAIL\n"); + } + + sunxi_e907_clock_init(elf_run_addr); + + dump_e907_clock(); + + printk(LOG_LEVEL_INFO, "RISC-V E907 Core now Running... \n"); + + abort(); + + jmp_to_fel(); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/read_chip_efuse/CMakeLists.txt b/board/yuzukilizard/read_chip_efuse/CMakeLists.txt new file mode 100644 index 00000000..b515d278 --- /dev/null +++ b/board/yuzukilizard/read_chip_efuse/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(read_chipsid + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/read_chip_efuse/main.c b/board/yuzukilizard/read_chip_efuse/main.c new file mode 100644 index 00000000..13130e33 --- /dev/null +++ b/board/yuzukilizard/read_chip_efuse/main.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include + +extern sunxi_serial_t uart_dbg; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + uint32_t id[4]; + + id[0] = read32(0x03006200 + 0x0); + id[1] = read32(0x03006200 + 0x4); + id[2] = read32(0x03006200 + 0x8); + id[3] = read32(0x03006200 + 0xc); + + printk(LOG_LEVEL_INFO, "Chip ID is: %08x%08x%08x%08x\n", id[0], id[1], + id[2], id[3]); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/read_chipsid/CMakeLists.txt b/board/yuzukilizard/read_chipsid/CMakeLists.txt new file mode 100644 index 00000000..7f1611a3 --- /dev/null +++ b/board/yuzukilizard/read_chipsid/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(read_chip_efuse + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/read_chipsid/main.c b/board/yuzukilizard/read_chipsid/main.c new file mode 100644 index 00000000..965ef55d --- /dev/null +++ b/board/yuzukilizard/read_chipsid/main.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include + +#include + +extern sunxi_serial_t uart_dbg; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + dump_efuse(); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/spi_lcd/CMakeLists.txt b/board/yuzukilizard/spi_lcd/CMakeLists.txt new file mode 100644 index 00000000..d82093cf --- /dev/null +++ b/board/yuzukilizard/spi_lcd/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(spi_lcd + main.c + lcd.c +) \ No newline at end of file diff --git a/board/yuzukilizard/spi_lcd/lcd.c b/board/yuzukilizard/spi_lcd/lcd.c new file mode 100644 index 00000000..20280433 --- /dev/null +++ b/board/yuzukilizard/spi_lcd/lcd.c @@ -0,0 +1,261 @@ +#include +#include +#include +#include +#include +#include + +#include "lcd.h" +#include "lcd_font.h" +#include "lcd_init.h" + +/****************************************************************************** +函数说明:填充颜色 +入口数据:color 要填充的颜色 +返回值: 无 +******************************************************************************/ +void LCD_Fill_All(uint16_t color) { + uint16_t i, j; + LCD_Address_Set(0, 0, LCD_W - 1, LCD_H - 1);// 设置显示范围 + uint16_t *video_mem = smalloc(LCD_W * LCD_H); + + for (uint32_t i = 0; i < LCD_W * LCD_H; i++) { + video_mem[i] = color; + } + + LCD_Write_Data_Bus(video_mem, LCD_W * LCD_H * (sizeof(uint16_t) / sizeof(uint8_t))); + + sfree(video_mem); +} + +/****************************************************************************** +函数说明:在指定区域填充颜色 +入口数据:xsta,ysta 起始坐标 + xend,yend 终止坐标 + color 要填充的颜色 +返回值: 无 +******************************************************************************/ +void LCD_Fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color) { + uint16_t i, j; + LCD_Address_Set(xsta, ysta, xend - 1, yend - 1);//设置显示范围 + for (i = ysta; i < yend; i++) { + for (j = xsta; j < xend; j++) { + LCD_WR_DATA(color); + } + } +} + +/****************************************************************************** + 函数说明:在指定位置画点 + 入口数据:x,y 画点坐标 + color 点的颜色 + 返回值: 无 +******************************************************************************/ +void LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color) { + LCD_Address_Set(x, y, x, y);//设置光标位置 + LCD_WR_DATA(color); +} + + +/****************************************************************************** + 函数说明:画线 + 入口数据:x1,y1 起始坐标 + x2,y2 终止坐标 + color 线的颜色 + 返回值: 无 +******************************************************************************/ +void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + uint16_t t; + int xerr = 0, yerr = 0, delta_x, delta_y, distance; + int incx, incy, uRow, uCol; + delta_x = x2 - x1;//计算坐标增量 + delta_y = y2 - y1; + uRow = x1;//画线起点坐标 + uCol = y1; + if (delta_x > 0) incx = 1;//设置单步方向 + else if (delta_x == 0) + incx = 0;//垂直线 + else { + incx = -1; + delta_x = -delta_x; + } + if (delta_y > 0) incy = 1; + else if (delta_y == 0) + incy = 0;//水平线 + else { + incy = -1; + delta_y = -delta_y; + } + if (delta_x > delta_y) distance = delta_x;//选取基本增量坐标轴 + else + distance = delta_y; + for (t = 0; t < distance + 1; t++) { + LCD_DrawPoint(uRow, uCol, color);//画点 + xerr += delta_x; + yerr += delta_y; + if (xerr > distance) { + xerr -= distance; + uRow += incx; + } + if (yerr > distance) { + yerr -= distance; + uCol += incy; + } + } +} + + +/****************************************************************************** + 函数说明:画矩形 + 入口数据:x1,y1 起始坐标 + x2,y2 终止坐标 + color 矩形的颜色 + 返回值: 无 +******************************************************************************/ +void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + LCD_DrawLine(x1, y1, x2, y1, color); + LCD_DrawLine(x1, y1, x1, y2, color); + LCD_DrawLine(x1, y2, x2, y2, color); + LCD_DrawLine(x2, y1, x2, y2, color); +} + + +/****************************************************************************** + 函数说明:画圆 + 入口数据:x0,y0 圆心坐标 + r 半径 + color 圆的颜色 + 返回值: 无 +******************************************************************************/ +void Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color) { + int a, b; + a = 0; + b = r; + while (a <= b) { + LCD_DrawPoint(x0 - b, y0 - a, color);//3 + LCD_DrawPoint(x0 + b, y0 - a, color);//0 + LCD_DrawPoint(x0 - a, y0 + b, color);//1 + LCD_DrawPoint(x0 - a, y0 - b, color);//2 + LCD_DrawPoint(x0 + b, y0 + a, color);//4 + LCD_DrawPoint(x0 + a, y0 - b, color);//5 + LCD_DrawPoint(x0 + a, y0 + b, color);//6 + LCD_DrawPoint(x0 - b, y0 + a, color);//7 + a++; + if ((a * a + b * b) > (r * r))//判断要画的点是否过远 + { + b--; + } + } +} + +/****************************************************************************** + 函数说明:显示单个字符 + 入口数据:x,y显示坐标 + num 要显示的字符 + fc 字的颜色 + bc 字的背景色 + sizey 字号 + mode: 0非叠加模式 1叠加模式 + 返回值: 无 +******************************************************************************/ +void LCD_ShowChar(uint16_t x, uint16_t y, uint8_t num, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode) { + uint8_t temp, sizex, t, m = 0; + uint16_t i, TypefaceNum;//一个字符所占字节大小 + uint16_t x0 = x; + sizex = sizey / 2; + TypefaceNum = (sizex / 8 + ((sizex % 8) ? 1 : 0)) * sizey; + num = num - ' '; //得到偏移后的值 + LCD_Address_Set(x, y, x + sizex - 1, y + sizey - 1);//设置光标位置 + for (i = 0; i < TypefaceNum; i++) { + if (sizey == 12) temp = ascii_1206[num][i];//调用6x12字体 + else if (sizey == 16) + temp = ascii_1608[num][i];//调用8x16字体 + else if (sizey == 24) + temp = ascii_2412[num][i];//调用12x24字体 + else if (sizey == 32) + temp = ascii_3216[num][i];//调用16x32字体 + else + return; + for (t = 0; t < 8; t++) { + if (!mode)//非叠加模式 + { + if (temp & (0x01 << t)) LCD_WR_DATA(fc); + else + LCD_WR_DATA(bc); + m++; + if (m % sizex == 0) { + m = 0; + break; + } + } else//叠加模式 + { + if (temp & (0x01 << t)) LCD_DrawPoint(x, y, fc);//画一个点 + x++; + if ((x - x0) == sizex) { + x = x0; + y++; + break; + } + } + } + } +} + +/****************************************************************************** + 函数说明:显示字符串 + 入口数据:x,y显示坐标 + *p 要显示的字符串 + fc 字的颜色 + bc 字的背景色 + sizey 字号 + mode: 0非叠加模式 1叠加模式 + 返回值: 无 +******************************************************************************/ +void LCD_ShowString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode) { + printk(LOG_LEVEL_INFO, "LCD: Show String: \"%s\"\n", p); + while (*p != '\0') { + LCD_ShowChar(x, y, *p, fc, bc, sizey, mode); + x += sizey / 2; + p++; + } +} + +/****************************************************************************** + 函数说明:显示数字 + 入口数据:m底数,n指数 + 返回值: 无 +******************************************************************************/ +u32 mypow(uint8_t m, uint8_t n) { + u32 result = 1; + while (n--) result *= m; + return result; +} + + +/****************************************************************************** + 函数说明:显示整数变量 + 入口数据:x,y显示坐标 + num 要显示整数变量 + len 要显示的位数 + fc 字的颜色 + bc 字的背景色 + sizey 字号 + 返回值: 无 +******************************************************************************/ +void LCD_ShowIntNum(uint16_t x, uint16_t y, uint16_t num, uint8_t len, uint16_t fc, uint16_t bc, uint8_t sizey) { + printk(LOG_LEVEL_INFO, "LCD: Show Number: \"%d\"\n", num); + uint8_t t, temp; + uint8_t enshow = 0; + uint8_t sizex = sizey / 2; + for (t = 0; t < len; t++) { + temp = (num / mypow(10, len - t - 1)) % 10; + if (enshow == 0 && t < (len - 1)) { + if (temp == 0) { + LCD_ShowChar(x + t * sizex, y, ' ', fc, bc, sizey, 0); + continue; + } else + enshow = 1; + } + LCD_ShowChar(x + t * sizex, y, temp + 48, fc, bc, sizey, 0); + } +} \ No newline at end of file diff --git a/board/yuzukilizard/spi_lcd/lcd.h b/board/yuzukilizard/spi_lcd/lcd.h new file mode 100644 index 00000000..33530145 --- /dev/null +++ b/board/yuzukilizard/spi_lcd/lcd.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __LCD_H__ +#define __LCD_H__ + +#include +#include +#include +#include + +#define LCD_W 240 +#define LCD_H 240 + +void LCD_Fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color);//指定区域填充颜色 + +void LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color);//在指定位置画一个点 + +void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);//在指定位置画一条线 + +void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);//在指定位置画一个矩形 + +void Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color);//在指定位置画一个圆 + +void LCD_ShowChar(uint16_t x, uint16_t y, uint8_t num, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode);//显示一个字符 + +void LCD_ShowString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode);//显示字符串 + +u32 mypow(uint8_t m, uint8_t n);//求幂 + +void LCD_ShowIntNum(uint16_t x, uint16_t y, uint16_t num, uint8_t len, uint16_t fc, uint16_t bc, uint8_t sizey);//显示整数变量 + +void LCD_ShowPicture(uint16_t x, uint16_t y, uint16_t length, uint16_t width, const uint8_t pic[]);//显示图片 + +//画笔颜色 +#define WHITE 0xFFFF +#define BLACK 0x0000 +#define BLUE 0x001F +#define BRED 0XF81F +#define GRED 0XFFE0 +#define GBLUE 0X07FF +#define RED 0xF800 +#define MAGENTA 0xF81F +#define GREEN 0x07E0 +#define CYAN 0x7FFF +#define YELLOW 0xFFE0 +#define BROWN 0XBC40 //棕色 +#define BRRED 0XFC07 //棕红色 +#define GRAY 0X8430 //灰色 +#define DARKBLUE 0X01CF //深蓝色 +#define LIGHTBLUE 0X7D7C //浅蓝色 +#define GRAYBLUE 0X5458 //灰蓝色 +#define LIGHTGREEN 0X841F//浅绿色 +#define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色 +#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色) +#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色) + +#endif//__LCD_H__ \ No newline at end of file diff --git a/board/yuzukilizard/spi_lcd/lcd_font.h b/board/yuzukilizard/spi_lcd/lcd_font.h new file mode 100644 index 00000000..0f628b4a --- /dev/null +++ b/board/yuzukilizard/spi_lcd/lcd_font.h @@ -0,0 +1,397 @@ +#ifndef __LCDFONT_H +#define __LCDFONT_H + +const unsigned char ascii_1206[][12] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*" ",0*/ + {0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00}, /*"!",1*/ + {0x14, 0x14, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*""",2*/ + {0x00, 0x00, 0x0A, 0x0A, 0x1F, 0x0A, 0x0A, 0x1F, 0x0A, 0x0A, 0x00, 0x00}, /*"#",3*/ + {0x00, 0x04, 0x0E, 0x15, 0x05, 0x06, 0x0C, 0x14, 0x15, 0x0E, 0x04, 0x00}, /*"$",4*/ + {0x00, 0x00, 0x12, 0x15, 0x0D, 0x15, 0x2E, 0x2C, 0x2A, 0x12, 0x00, 0x00}, /*"%",5*/ + {0x00, 0x00, 0x04, 0x0A, 0x0A, 0x36, 0x15, 0x15, 0x29, 0x16, 0x00, 0x00}, /*"&",6*/ + {0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"'",7*/ + {0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x00}, /*"(",8*/ + {0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00}, /*")",9*/ + {0x00, 0x00, 0x00, 0x04, 0x15, 0x0E, 0x0E, 0x15, 0x04, 0x00, 0x00, 0x00}, /*"*",10*/ + {0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}, /*"+",11*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x00}, /*",",12*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"-",13*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, /*".",14*/ + {0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00}, /*"/",15*/ + {0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00}, /*"0",16*/ + {0x00, 0x00, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, 0x00}, /*"1",17*/ + {0x00, 0x00, 0x0E, 0x11, 0x11, 0x08, 0x04, 0x02, 0x01, 0x1F, 0x00, 0x00}, /*"2",18*/ + {0x00, 0x00, 0x0E, 0x11, 0x10, 0x0C, 0x10, 0x10, 0x11, 0x0E, 0x00, 0x00}, /*"3",19*/ + {0x00, 0x00, 0x08, 0x0C, 0x0C, 0x0A, 0x09, 0x1F, 0x08, 0x1C, 0x00, 0x00}, /*"4",20*/ + {0x00, 0x00, 0x1F, 0x01, 0x01, 0x0F, 0x11, 0x10, 0x11, 0x0E, 0x00, 0x00}, /*"5",21*/ + {0x00, 0x00, 0x0C, 0x12, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x0E, 0x00, 0x00}, /*"6",22*/ + {0x00, 0x00, 0x1E, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00}, /*"7",23*/ + {0x00, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00}, /*"8",24*/ + {0x00, 0x00, 0x0E, 0x11, 0x11, 0x19, 0x16, 0x10, 0x09, 0x06, 0x00, 0x00}, /*"9",25*/ + {0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}, /*":",26*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00}, /*";",27*/ + {0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00}, /*"<",28*/ + {0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"=",29*/ + {0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, /*">",30*/ + {0x00, 0x00, 0x0E, 0x11, 0x11, 0x08, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00}, /*"?",31*/ + {0x00, 0x00, 0x1C, 0x22, 0x29, 0x2D, 0x2D, 0x1D, 0x22, 0x1C, 0x00, 0x00}, /*"@",32*/ + {0x00, 0x00, 0x04, 0x04, 0x0C, 0x0A, 0x0A, 0x1E, 0x12, 0x33, 0x00, 0x00}, /*"A",33*/ + {0x00, 0x00, 0x0F, 0x12, 0x12, 0x0E, 0x12, 0x12, 0x12, 0x0F, 0x00, 0x00}, /*"B",34*/ + {0x00, 0x00, 0x1E, 0x11, 0x01, 0x01, 0x01, 0x01, 0x11, 0x0E, 0x00, 0x00}, /*"C",35*/ + {0x00, 0x00, 0x0F, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x0F, 0x00, 0x00}, /*"D",36*/ + {0x00, 0x00, 0x1F, 0x12, 0x0A, 0x0E, 0x0A, 0x02, 0x12, 0x1F, 0x00, 0x00}, /*"E",37*/ + {0x00, 0x00, 0x1F, 0x12, 0x0A, 0x0E, 0x0A, 0x02, 0x02, 0x07, 0x00, 0x00}, /*"F",38*/ + {0x00, 0x00, 0x1C, 0x12, 0x01, 0x01, 0x39, 0x11, 0x12, 0x0C, 0x00, 0x00}, /*"G",39*/ + {0x00, 0x00, 0x33, 0x12, 0x12, 0x1E, 0x12, 0x12, 0x12, 0x33, 0x00, 0x00}, /*"H",40*/ + {0x00, 0x00, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x00, 0x00}, /*"I",41*/ + {0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x07}, /*"J",42*/ + {0x00, 0x00, 0x37, 0x12, 0x0A, 0x06, 0x0A, 0x12, 0x12, 0x37, 0x00, 0x00}, /*"K",43*/ + {0x00, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x22, 0x3F, 0x00, 0x00}, /*"L",44*/ + {0x00, 0x00, 0x3B, 0x1B, 0x1B, 0x1B, 0x15, 0x15, 0x15, 0x35, 0x00, 0x00}, /*"M",45*/ + {0x00, 0x00, 0x3B, 0x12, 0x16, 0x16, 0x1A, 0x1A, 0x12, 0x17, 0x00, 0x00}, /*"N",46*/ + {0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00}, /*"O",47*/ + {0x00, 0x00, 0x0F, 0x12, 0x12, 0x0E, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00}, /*"P",48*/ + {0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x17, 0x19, 0x0E, 0x18, 0x00}, /*"Q",49*/ + {0x00, 0x00, 0x0F, 0x12, 0x12, 0x0E, 0x0A, 0x12, 0x12, 0x37, 0x00, 0x00}, /*"R",50*/ + {0x00, 0x00, 0x1E, 0x11, 0x01, 0x06, 0x08, 0x10, 0x11, 0x0F, 0x00, 0x00}, /*"S",51*/ + {0x00, 0x00, 0x1F, 0x15, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, 0x00}, /*"T",52*/ + {0x00, 0x00, 0x33, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x0C, 0x00, 0x00}, /*"U",53*/ + {0x00, 0x00, 0x33, 0x12, 0x12, 0x0A, 0x0A, 0x0C, 0x04, 0x04, 0x00, 0x00}, /*"V",54*/ + {0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x0E, 0x0A, 0x0A, 0x0A, 0x00, 0x00}, /*"W",55*/ + {0x00, 0x00, 0x1B, 0x0A, 0x0A, 0x04, 0x04, 0x0A, 0x0A, 0x1B, 0x00, 0x00}, /*"X",56*/ + {0x00, 0x00, 0x1B, 0x0A, 0x0A, 0x0A, 0x04, 0x04, 0x04, 0x0E, 0x00, 0x00}, /*"Y",57*/ + {0x00, 0x00, 0x1F, 0x09, 0x08, 0x04, 0x04, 0x02, 0x12, 0x1F, 0x00, 0x00}, /*"Z",58*/ + {0x1C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1C, 0x00}, /*"[",59*/ + {0x00, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x00}, /*"\",60*/ + {0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0E, 0x00}, /*"]",61*/ + {0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"^",62*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F}, /*"_",63*/ + {0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"`",64*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x12, 0x1C, 0x12, 0x3C, 0x00, 0x00}, /*"a",65*/ + {0x00, 0x03, 0x02, 0x02, 0x02, 0x0E, 0x12, 0x12, 0x12, 0x0E, 0x00, 0x00}, /*"b",66*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x12, 0x02, 0x12, 0x0C, 0x00, 0x00}, /*"c",67*/ + {0x00, 0x18, 0x10, 0x10, 0x10, 0x1C, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00}, /*"d",68*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x12, 0x1E, 0x02, 0x1C, 0x00, 0x00}, /*"e",69*/ + {0x00, 0x18, 0x24, 0x04, 0x04, 0x1E, 0x04, 0x04, 0x04, 0x1E, 0x00, 0x00}, /*"f",70*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x12, 0x0C, 0x02, 0x1C, 0x22, 0x1C}, /*"g",71*/ + {0x00, 0x03, 0x02, 0x02, 0x02, 0x0E, 0x12, 0x12, 0x12, 0x37, 0x00, 0x00}, /*"h",72*/ + {0x00, 0x04, 0x04, 0x00, 0x00, 0x06, 0x04, 0x04, 0x04, 0x0E, 0x00, 0x00}, /*"i",73*/ + {0x00, 0x08, 0x08, 0x00, 0x00, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07}, /*"j",74*/ + {0x00, 0x03, 0x02, 0x02, 0x02, 0x1A, 0x0A, 0x06, 0x0A, 0x13, 0x00, 0x00}, /*"k",75*/ + {0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x00, 0x00}, /*"l",76*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00}, /*"m",77*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x12, 0x12, 0x12, 0x37, 0x00, 0x00}, /*"n",78*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x12, 0x12, 0x12, 0x0C, 0x00, 0x00}, /*"o",79*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x12, 0x12, 0x12, 0x0E, 0x02, 0x07}, /*"p",80*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x12, 0x12, 0x12, 0x1C, 0x10, 0x38}, /*"q",81*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x06, 0x02, 0x02, 0x07, 0x00, 0x00}, /*"r",82*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x02, 0x0C, 0x10, 0x1E, 0x00, 0x00}, /*"s",83*/ + {0x00, 0x00, 0x00, 0x04, 0x04, 0x1E, 0x04, 0x04, 0x04, 0x1C, 0x00, 0x00}, /*"t",84*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00}, /*"u",85*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x0A, 0x0A, 0x04, 0x04, 0x00, 0x00}, /*"v",86*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x0E, 0x0A, 0x0A, 0x00, 0x00}, /*"w",87*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x0A, 0x04, 0x0A, 0x1B, 0x00, 0x00}, /*"x",88*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x12, 0x12, 0x0C, 0x08, 0x04, 0x03}, /*"y",89*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x08, 0x04, 0x04, 0x1E, 0x00, 0x00}, /*"z",90*/ + {0x18, 0x08, 0x08, 0x08, 0x08, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00}, /*"{",91*/ + {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, /*"|",92*/ + {0x06, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x06, 0x00}, /*"}",93*/ + {0x16, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"~",94*/ +}; + +unsigned char ascii_1608[][16] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*" ",0*/ + {0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, /*"!",1*/ + {0x00, 0x48, 0x6C, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*""",2*/ + {0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x7F, 0x12, 0x12, 0x12, 0x7F, 0x12, 0x12, 0x12, 0x00, 0x00}, /*"#",3*/ + {0x00, 0x00, 0x08, 0x1C, 0x2A, 0x2A, 0x0A, 0x0C, 0x18, 0x28, 0x28, 0x2A, 0x2A, 0x1C, 0x08, 0x08}, /*"$",4*/ + {0x00, 0x00, 0x00, 0x22, 0x25, 0x15, 0x15, 0x15, 0x2A, 0x58, 0x54, 0x54, 0x54, 0x22, 0x00, 0x00}, /*"%",5*/ + {0x00, 0x00, 0x00, 0x0C, 0x12, 0x12, 0x12, 0x0A, 0x76, 0x25, 0x29, 0x11, 0x91, 0x6E, 0x00, 0x00}, /*"&",6*/ + {0x00, 0x06, 0x06, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"'",7*/ + {0x00, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x00}, /*"(",8*/ + {0x00, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00}, /*")",9*/ + {0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x1C, 0x1C, 0x6B, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}, /*"*",10*/ + {0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x7F, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00}, /*"+",11*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x03}, /*",",12*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"-",13*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00}, /*".",14*/ + {0x00, 0x00, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00}, /*"/",15*/ + {0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00}, /*"0",16*/ + {0x00, 0x00, 0x00, 0x08, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"1",17*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x20, 0x20, 0x10, 0x08, 0x04, 0x42, 0x7E, 0x00, 0x00}, /*"2",18*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x20, 0x18, 0x20, 0x40, 0x40, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"3",19*/ + {0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x24, 0x22, 0x22, 0x7E, 0x20, 0x20, 0x78, 0x00, 0x00}, /*"4",20*/ + {0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x02, 0x1A, 0x26, 0x40, 0x40, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"5",21*/ + {0x00, 0x00, 0x00, 0x38, 0x24, 0x02, 0x02, 0x1A, 0x26, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00}, /*"6",22*/ + {0x00, 0x00, 0x00, 0x7E, 0x22, 0x22, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /*"7",23*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00}, /*"8",24*/ + {0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0x40, 0x24, 0x1C, 0x00, 0x00}, /*"9",25*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, /*":",26*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04}, /*";",27*/ + {0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00}, /*"<",28*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"=",29*/ + {0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, /*">",30*/ + {0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x46, 0x40, 0x20, 0x10, 0x10, 0x00, 0x18, 0x18, 0x00, 0x00}, /*"?",31*/ + {0x00, 0x00, 0x00, 0x1C, 0x22, 0x5A, 0x55, 0x55, 0x55, 0x55, 0x2D, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"@",32*/ + {0x00, 0x00, 0x00, 0x08, 0x08, 0x18, 0x14, 0x14, 0x24, 0x3C, 0x22, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"A",33*/ + {0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x1E, 0x22, 0x42, 0x42, 0x42, 0x22, 0x1F, 0x00, 0x00}, /*"B",34*/ + {0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x22, 0x1C, 0x00, 0x00}, /*"C",35*/ + {0x00, 0x00, 0x00, 0x1F, 0x22, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1F, 0x00, 0x00}, /*"D",36*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x12, 0x12, 0x1E, 0x12, 0x12, 0x02, 0x42, 0x42, 0x3F, 0x00, 0x00}, /*"E",37*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x12, 0x12, 0x1E, 0x12, 0x12, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00}, /*"F",38*/ + {0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x01, 0x01, 0x01, 0x71, 0x21, 0x22, 0x22, 0x1C, 0x00, 0x00}, /*"G",39*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"H",40*/ + {0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"I",41*/ + {0x00, 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x0F}, /*"J",42*/ + {0x00, 0x00, 0x00, 0x77, 0x22, 0x12, 0x0A, 0x0E, 0x0A, 0x12, 0x12, 0x22, 0x22, 0x77, 0x00, 0x00}, /*"K",43*/ + {0x00, 0x00, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x7F, 0x00, 0x00}, /*"L",44*/ + {0x00, 0x00, 0x00, 0x77, 0x36, 0x36, 0x36, 0x36, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x6B, 0x00, 0x00}, /*"M",45*/ + {0x00, 0x00, 0x00, 0xE3, 0x46, 0x46, 0x4A, 0x4A, 0x52, 0x52, 0x52, 0x62, 0x62, 0x47, 0x00, 0x00}, /*"N",46*/ + {0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1C, 0x00, 0x00}, /*"O",47*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00}, /*"P",48*/ + {0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x4D, 0x53, 0x32, 0x1C, 0x60, 0x00}, /*"Q",49*/ + {0x00, 0x00, 0x00, 0x3F, 0x42, 0x42, 0x42, 0x3E, 0x12, 0x12, 0x22, 0x22, 0x42, 0xC7, 0x00, 0x00}, /*"R",50*/ + {0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x02, 0x04, 0x18, 0x20, 0x40, 0x42, 0x42, 0x3E, 0x00, 0x00}, /*"S",51*/ + {0x00, 0x00, 0x00, 0x7F, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /*"T",52*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00}, /*"U",53*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x42, 0x22, 0x24, 0x24, 0x14, 0x14, 0x18, 0x08, 0x08, 0x00, 0x00}, /*"V",54*/ + {0x00, 0x00, 0x00, 0x6B, 0x49, 0x49, 0x49, 0x49, 0x55, 0x55, 0x36, 0x22, 0x22, 0x22, 0x00, 0x00}, /*"W",55*/ + {0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0xE7, 0x00, 0x00}, /*"X",56*/ + {0x00, 0x00, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /*"Y",57*/ + {0x00, 0x00, 0x00, 0x7E, 0x21, 0x20, 0x10, 0x10, 0x08, 0x04, 0x04, 0x42, 0x42, 0x3F, 0x00, 0x00}, /*"Z",58*/ + {0x00, 0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00}, /*"[",59*/ + {0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x40}, /*"\",60*/ + {0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00}, /*"]",61*/ + {0x00, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"^",62*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, /*"_",63*/ + {0x00, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"`",64*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x78, 0x44, 0x42, 0x42, 0xFC, 0x00, 0x00}, /*"a",65*/ + {0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x1A, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1A, 0x00, 0x00}, /*"b",66*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x44, 0x38, 0x00, 0x00}, /*"c",67*/ + {0x00, 0x00, 0x00, 0x60, 0x40, 0x40, 0x40, 0x78, 0x44, 0x42, 0x42, 0x42, 0x64, 0xD8, 0x00, 0x00}, /*"d",68*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00}, /*"e",69*/ + {0x00, 0x00, 0x00, 0xF0, 0x88, 0x08, 0x08, 0x7E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"f",70*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x22, 0x22, 0x1C, 0x02, 0x3C, 0x42, 0x42, 0x3C}, /*"g",71*/ + {0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"h",72*/ + {0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"i",73*/ + {0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1E}, /*"j",74*/ + {0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x72, 0x12, 0x0A, 0x16, 0x12, 0x22, 0x77, 0x00, 0x00}, /*"k",75*/ + {0x00, 0x00, 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /*"l",76*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x92, 0x92, 0x92, 0x92, 0x92, 0xB7, 0x00, 0x00}, /*"m",77*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x46, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00}, /*"n",78*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00}, /*"o",79*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x26, 0x42, 0x42, 0x42, 0x22, 0x1E, 0x02, 0x07}, /*"p",80*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0x78, 0x40, 0xE0}, /*"q",81*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x4C, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x00, 0x00}, /*"r",82*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x02, 0x3C, 0x40, 0x42, 0x3E, 0x00, 0x00}, /*"s",83*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00}, /*"t",84*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xDC, 0x00, 0x00}, /*"u",85*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x14, 0x08, 0x08, 0x00, 0x00}, /*"v",86*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x49, 0x49, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00}, /*"w",87*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x24, 0x18, 0x18, 0x18, 0x24, 0x6E, 0x00, 0x00}, /*"x",88*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x14, 0x18, 0x08, 0x08, 0x07}, /*"y",89*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x22, 0x10, 0x08, 0x08, 0x44, 0x7E, 0x00, 0x00}, /*"z",90*/ + {0x00, 0xC0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xC0, 0x00}, /*"{",91*/ + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /*"|",92*/ + {0x00, 0x06, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x06, 0x00}, /*"}",93*/ + {0x0C, 0x32, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"~",94*/ +}; + +const unsigned char ascii_2412[][48] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*" ",0*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"!",1*/ + {0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x60, 0x06, 0x30, 0x03, 0x98, 0x01, 0x88, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*""",2*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0xFE, 0x07, 0xFE, 0x07, 0x08, 0x02, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0xFE, 0x07, 0xFE, 0x07, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"#",3*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF0, 0x01, 0x58, 0x03, 0x4C, 0x03, 0xCC, 0x03, 0x4C, 0x00, 0x58, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x40, 0x03, 0x4C, 0x03, 0x5C, 0x03, 0x4C, 0x03, 0x48, 0x01, 0xF0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00}, /*"$",4*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x01, 0x0A, 0x01, 0x91, 0x00, 0x91, 0x00, 0x91, 0x00, 0x51, 0x00, 0x51, 0x00, 0x3A, 0x00, 0xAE, 0x03, 0xA0, 0x02, 0x50, 0x04, 0x50, 0x04, 0x48, 0x04, 0x48, 0x04, 0x48, 0x04, 0x84, 0x02, 0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"%",5*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x2C, 0x00, 0x98, 0x07, 0x1C, 0x01, 0x1A, 0x01, 0x33, 0x01, 0x33, 0x01, 0x63, 0x01, 0xE3, 0x00, 0xC3, 0x08, 0xC6, 0x09, 0x3C, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"&",6*/ + {0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x1C, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 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}, /*"'",7*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00}, /*"(",8*/ + {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00}, /*")",9*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x40, 0x00, 0x46, 0x0C, 0x4E, 0x0F, 0xD0, 0x01, 0xF0, 0x01, 0x5E, 0x0F, 0x46, 0x0C, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"*",10*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xFE, 0x0F, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"+",11*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1C, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00}, /*",",12*/ + {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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"-",13*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*".",14*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00}, /*"/",15*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x0C, 0x03, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"0",16*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x7C, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"1",17*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x01, 0x02, 0x03, 0x06, 0x03, 0x06, 0x03, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0xC0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x02, 0x04, 0x02, 0x06, 0x02, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"2",18*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xC6, 0x00, 0x86, 0x01, 0x86, 0x01, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"3",19*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x01, 0xA0, 0x01, 0xA0, 0x01, 0x90, 0x01, 0x88, 0x01, 0x88, 0x01, 0x84, 0x01, 0x82, 0x01, 0xFE, 0x0F, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"4",20*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0xF4, 0x00, 0x8C, 0x01, 0x04, 0x03, 0x00, 0x03, 0x00, 0x03, 0x06, 0x03, 0x06, 0x03, 0x82, 0x01, 0x84, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"5",21*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x18, 0x03, 0x0C, 0x03, 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0xE6, 0x01, 0x16, 0x03, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x04, 0x06, 0x0C, 0x02, 0x18, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"6",22*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x0C, 0x06, 0x04, 0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"7",23*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x02, 0x1C, 0x03, 0xF0, 0x00, 0xC8, 0x01, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"8",24*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x0C, 0x01, 0x0C, 0x03, 0x06, 0x02, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x8C, 0x06, 0x78, 0x06, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x0C, 0x01, 0x8C, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"9",25*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*":",26*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00}, /*";",27*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"<",28*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"=",29*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*">",30*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x18, 0x06, 0x04, 0x0C, 0x04, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x07, 0x80, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"?",31*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x18, 0x03, 0x0C, 0x02, 0xCC, 0x05, 0x64, 0x05, 0x66, 0x05, 0xA6, 0x05, 0xB6, 0x04, 0xB6, 0x04, 0xB6, 0x04, 0xB6, 0x04, 0xB6, 0x02, 0xE4, 0x01, 0x0C, 0x04, 0x0C, 0x02, 0x18, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"@",32*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x50, 0x00, 0xD0, 0x00, 0x90, 0x00, 0x90, 0x00, 0x88, 0x00, 0x88, 0x01, 0x08, 0x01, 0xF8, 0x01, 0x04, 0x03, 0x04, 0x03, 0x04, 0x02, 0x02, 0x02, 0x02, 0x06, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"A",33*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x8C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x8C, 0x01, 0xFC, 0x00, 0x0C, 0x03, 0x0C, 0x02, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x03, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"B",34*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x18, 0x03, 0x0C, 0x06, 0x0C, 0x04, 0x04, 0x04, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x04, 0x0C, 0x04, 0x0C, 0x02, 0x18, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"C",35*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x8C, 0x01, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0x8C, 0x01, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"D",36*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x06, 0x03, 0x06, 0x04, 0x06, 0x04, 0x06, 0x00, 0x86, 0x00, 0x86, 0x00, 0xFE, 0x00, 0x86, 0x00, 0x86, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x04, 0x06, 0x04, 0x06, 0x02, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"E",37*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x06, 0x03, 0x06, 0x04, 0x06, 0x04, 0x06, 0x00, 0x86, 0x00, 0x86, 0x00, 0xFE, 0x00, 0x86, 0x00, 0x86, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"F",38*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x18, 0x01, 0x0C, 0x02, 0x0C, 0x02, 0x04, 0x02, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xC6, 0x0F, 0x06, 0x03, 0x06, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x18, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"G",39*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"H",40*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"I",41*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC6, 0x00, 0x66, 0x00, 0x3C, 0x00}, /*"J",42*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0x03, 0x86, 0x01, 0xC6, 0x00, 0x46, 0x00, 0x26, 0x00, 0x16, 0x00, 0x36, 0x00, 0x2E, 0x00, 0x6E, 0x00, 0x46, 0x00, 0xC6, 0x00, 0x86, 0x00, 0x86, 0x01, 0x06, 0x01, 0x06, 0x03, 0x8F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"K",43*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x04, 0x06, 0x04, 0x06, 0x02, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"L",44*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x86, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x8E, 0x03, 0x4E, 0x03, 0x4E, 0x03, 0x4A, 0x03, 0x5A, 0x03, 0x5A, 0x03, 0x3A, 0x03, 0x32, 0x03, 0x32, 0x03, 0x32, 0x03, 0x12, 0x03, 0x87, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"M",45*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x0F, 0x0C, 0x02, 0x1C, 0x02, 0x1C, 0x02, 0x34, 0x02, 0x34, 0x02, 0x64, 0x02, 0x64, 0x02, 0x44, 0x02, 0xC4, 0x02, 0x84, 0x02, 0x84, 0x03, 0x84, 0x03, 0x04, 0x03, 0x04, 0x03, 0x1F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"N",46*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x0C, 0x03, 0x0C, 0x02, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x02, 0x0C, 0x03, 0x98, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"O",47*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x06, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0x03, 0xFE, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"P",48*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x0C, 0x03, 0x0C, 0x02, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x76, 0x06, 0x4C, 0x02, 0xCC, 0x03, 0x98, 0x01, 0xF0, 0x00, 0x80, 0x07, 0x00, 0x03, 0x00, 0x00}, /*"Q",49*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x06, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0xFE, 0x00, 0x46, 0x00, 0xC6, 0x00, 0x86, 0x00, 0x86, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x0F, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"R",50*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x02, 0x0C, 0x03, 0x06, 0x02, 0x06, 0x02, 0x06, 0x00, 0x0E, 0x00, 0x3C, 0x00, 0xF8, 0x00, 0xE0, 0x03, 0x80, 0x03, 0x00, 0x07, 0x02, 0x06, 0x02, 0x06, 0x06, 0x06, 0x0C, 0x03, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"S",51*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x62, 0x04, 0x61, 0x08, 0x61, 0x08, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"T",52*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x07, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x18, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"U",53*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x07, 0x06, 0x02, 0x04, 0x01, 0x04, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x88, 0x00, 0x88, 0x00, 0x98, 0x00, 0x98, 0x00, 0x50, 0x00, 0x50, 0x00, 0x70, 0x00, 0x30, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"V",54*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x0E, 0x62, 0x04, 0x42, 0x04, 0x46, 0x04, 0x46, 0x04, 0x64, 0x02, 0x64, 0x02, 0xE4, 0x02, 0xE4, 0x02, 0x9C, 0x02, 0x9C, 0x01, 0x98, 0x01, 0x98, 0x01, 0x88, 0x01, 0x88, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"W",55*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x07, 0x0C, 0x01, 0x08, 0x01, 0x18, 0x01, 0x90, 0x00, 0xB0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x60, 0x00, 0xD0, 0x00, 0x90, 0x00, 0x88, 0x01, 0x08, 0x01, 0x04, 0x03, 0x8E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"X",56*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x06, 0x04, 0x04, 0x02, 0x0C, 0x02, 0x08, 0x01, 0x18, 0x01, 0xB8, 0x00, 0xB0, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"Y",57*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x07, 0x0C, 0x02, 0x06, 0x03, 0x02, 0x01, 0x80, 0x01, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x18, 0x00, 0x08, 0x04, 0x0C, 0x04, 0x04, 0x02, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"Z",58*/ + {0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x00, 0x00}, /*"[",59*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04}, /*"\",60*/ + {0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x7C, 0x00, 0x00, 0x00}, /*"]",61*/ + {0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 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}, /*"^",62*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x0F}, /*"_",63*/ + {0x00, 0x00, 0x00, 0x00, 0x18, 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}, /*"`",64*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x0C, 0x03, 0x0C, 0x03, 0x00, 0x03, 0xE0, 0x03, 0x1C, 0x03, 0x0E, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8E, 0x0B, 0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"a",65*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xCC, 0x01, 0x3C, 0x03, 0x1C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x02, 0x1C, 0x03, 0xE4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"b",66*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x8C, 0x01, 0x8C, 0x01, 0x86, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x02, 0x0C, 0x02, 0x0C, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"c",67*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x78, 0x03, 0x8C, 0x03, 0x0C, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x04, 0x03, 0x8C, 0x07, 0x78, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"d",68*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x18, 0x03, 0x08, 0x02, 0x0C, 0x06, 0x0C, 0x06, 0xFC, 0x07, 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x04, 0x18, 0x02, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"e",69*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x60, 0x06, 0x30, 0x06, 0x30, 0x00, 0x30, 0x00, 0xFE, 0x01, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"f",70*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0xD8, 0x06, 0x8C, 0x01, 0x8C, 0x01, 0x8C, 0x01, 0x98, 0x01, 0xF8, 0x00, 0x0C, 0x00, 0xFC, 0x00, 0xCC, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8E, 0x03, 0xF8, 0x00}, /*"g",71*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xEC, 0x01, 0x1C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x9E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"h",72*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x7C, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"i",73*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xCC, 0x00, 0x7C, 0x00}, /*"j",74*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x8C, 0x03, 0x8C, 0x00, 0x8C, 0x00, 0x4C, 0x00, 0x6C, 0x00, 0x5C, 0x00, 0x8C, 0x00, 0x8C, 0x01, 0x0C, 0x01, 0x0C, 0x03, 0x9E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"k",75*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x7C, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"l",76*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07, 0xEE, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"m",77*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x01, 0x1C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x9E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"n",78*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"o",79*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x01, 0x1C, 0x03, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x03, 0x1C, 0x03, 0xEC, 0x01, 0x0C, 0x00, 0x0C, 0x00, 0x3E, 0x00}, /*"p",80*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x02, 0x8C, 0x03, 0x0C, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x04, 0x03, 0x8C, 0x03, 0x78, 0x03, 0x00, 0x03, 0x00, 0x03, 0xC0, 0x07}, /*"q",81*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x03, 0x58, 0x06, 0x38, 0x06, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"r",82*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x1C, 0x03, 0x0C, 0x02, 0x0C, 0x02, 0x38, 0x00, 0xF0, 0x00, 0xC0, 0x03, 0x04, 0x03, 0x04, 0x03, 0x8C, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"s",83*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x30, 0x00, 0x30, 0x00, 0xFE, 0x01, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x02, 0x30, 0x02, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"t",84*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x8E, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x9C, 0x07, 0x78, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"u",85*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x07, 0x0C, 0x02, 0x08, 0x01, 0x08, 0x01, 0x18, 0x01, 0x90, 0x00, 0xB0, 0x00, 0xB0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"v",86*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x0E, 0x62, 0x04, 0x46, 0x04, 0x64, 0x02, 0x64, 0x02, 0xEC, 0x02, 0x9C, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"w",87*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x07, 0x18, 0x01, 0x10, 0x01, 0xB0, 0x00, 0x60, 0x00, 0x60, 0x00, 0xE0, 0x00, 0x90, 0x00, 0x08, 0x01, 0x08, 0x03, 0x9E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"x",88*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x07, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x90, 0x00, 0x90, 0x00, 0xB0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x24, 0x00, 0x1C, 0x00}, /*"y",89*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x01, 0x84, 0x01, 0xC4, 0x00, 0x44, 0x00, 0x60, 0x00, 0x20, 0x00, 0x30, 0x00, 0x18, 0x02, 0x08, 0x02, 0x0C, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"z",90*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00}, /*"{",91*/ + {0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00}, /*"|",92*/ + {0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, 0x00}, /*"}",93*/ + {0x00, 0x00, 0x1C, 0x00, 0x22, 0x04, 0xC2, 0x04, 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}, /*"~",94*/ + + +}; + +unsigned char ascii_3216[][64] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*" ",0*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"!",1*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1C, 0xE0, 0x1C, 0xF0, 0x1E, 0x70, 0x0E, 0x38, 0x07, 0x18, 0x03, 0x08, 0x01, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*""",2*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0xFE, 0x7F, 0xFE, 0x7F, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0xFE, 0x7F, 0xFE, 0x7F, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"#",3*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xC0, 0x07, 0x60, 0x19, 0x10, 0x31, 0x18, 0x31, 0x18, 0x39, 0x18, 0x39, 0x38, 0x01, 0x70, 0x01, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0F, 0x00, 0x1D, 0x00, 0x39, 0x00, 0x31, 0x1C, 0x31, 0x1C, 0x31, 0x0C, 0x31, 0x0C, 0x11, 0x18, 0x0D, 0xE0, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, /*"$",4*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x10, 0x36, 0x18, 0x63, 0x08, 0x63, 0x0C, 0x63, 0x04, 0x63, 0x04, 0x63, 0x02, 0x63, 0x02, 0x63, 0x01, 0x36, 0x1D, 0x9C, 0x37, 0x80, 0x22, 0x80, 0x63, 0x40, 0x63, 0x40, 0x63, 0x20, 0x63, 0x20, 0x63, 0x30, 0x63, 0x10, 0x22, 0x18, 0x36, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"%",5*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x8C, 0x01, 0x8C, 0x01, 0x8C, 0x01, 0x8C, 0x01, 0x8C, 0x00, 0xCC, 0x00, 0x78, 0x00, 0x18, 0x3E, 0x1C, 0x08, 0x36, 0x08, 0x32, 0x08, 0x63, 0x04, 0x63, 0x04, 0xC3, 0x04, 0xC3, 0x03, 0x83, 0x43, 0x06, 0x43, 0x8E, 0x26, 0x78, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"&",6*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x30, 0x00, 0x30, 0x00, 0x10, 0x00, 0x0C, 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}, /*"'",7*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00}, /*"(",8*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00}, /*")",9*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x80, 0x03, 0x00, 0x01, 0x1C, 0x71, 0x3C, 0x79, 0x78, 0x3D, 0xC0, 0x07, 0x00, 0x01, 0xC0, 0x07, 0x78, 0x3D, 0x3C, 0x79, 0x1C, 0x71, 0x00, 0x01, 0x80, 0x03, 0x80, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"*",10*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xFC, 0x7F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"+",11*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3C, 0x00, 0x3C, 0x00, 0x30, 0x00, 0x30, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x06, 0x00}, /*",",12*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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}, /*"-",13*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x3C, 0x00, 0x3C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*".",14*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x20, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x00, 0x40, 0x00, 0x60, 0x00, 0x20, 0x00, 0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"/",15*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x60, 0x0C, 0x30, 0x18, 0x18, 0x30, 0x18, 0x30, 0x18, 0x20, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x18, 0x20, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0x60, 0x0C, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"0",16*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x03, 0xF8, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"1",17*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x10, 0x1C, 0x08, 0x18, 0x04, 0x30, 0x04, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0x20, 0x20, 0x10, 0x20, 0x08, 0x20, 0x04, 0x30, 0xFC, 0x1F, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"2",18*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x18, 0x0E, 0x0C, 0x0C, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x06, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x10, 0x0C, 0x18, 0x18, 0x0C, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"3",19*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0F, 0x80, 0x0E, 0x80, 0x0E, 0x40, 0x0E, 0x60, 0x0E, 0x20, 0x0E, 0x10, 0x0E, 0x10, 0x0E, 0x08, 0x0E, 0x04, 0x0E, 0x04, 0x0E, 0xFE, 0x7F, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"4",20*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0xF0, 0x3F, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0xC8, 0x07, 0x28, 0x0C, 0x18, 0x18, 0x08, 0x10, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x04, 0x18, 0x04, 0x18, 0x08, 0x0C, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"5",21*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xC0, 0x10, 0x20, 0x30, 0x10, 0x30, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x8C, 0x0F, 0x6C, 0x18, 0x3C, 0x30, 0x1C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x18, 0x60, 0x18, 0x20, 0x30, 0x30, 0x60, 0x18, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"6",22*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xF8, 0x3F, 0x1C, 0x10, 0x0C, 0x08, 0x04, 0x08, 0x04, 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"7",23*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x30, 0x0C, 0x18, 0x18, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x1C, 0x30, 0x38, 0x18, 0x70, 0x08, 0xE0, 0x07, 0xB0, 0x07, 0x18, 0x0E, 0x0C, 0x1C, 0x06, 0x38, 0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x0C, 0x18, 0x18, 0x0C, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"8",24*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x18, 0x04, 0x0C, 0x08, 0x0C, 0x18, 0x06, 0x10, 0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x06, 0x38, 0x0C, 0x3C, 0x18, 0x36, 0xF0, 0x31, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x0C, 0x0C, 0x0C, 0x06, 0x0C, 0x03, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"9",25*/ + {0x00, 0x00, 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, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*":",26*/ + {0x00, 0x00, 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, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00}, /*";",27*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"<",28*/ + {0x00, 0x00, 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, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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}, /*"=",29*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*">",30*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x30, 0x18, 0x08, 0x30, 0x08, 0x60, 0x0C, 0x60, 0x1C, 0x60, 0x1C, 0x60, 0x1C, 0x60, 0x00, 0x30, 0x00, 0x1C, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"?",31*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x60, 0x18, 0x10, 0x30, 0x18, 0x20, 0x0C, 0x2F, 0x8C, 0x4D, 0x86, 0x4C, 0xC6, 0x4C, 0xC6, 0x4C, 0x66, 0x4C, 0x66, 0x44, 0x66, 0x44, 0x66, 0x26, 0x66, 0x26, 0x66, 0x15, 0xCC, 0x1C, 0x0C, 0x40, 0x08, 0x20, 0x18, 0x30, 0x30, 0x18, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"@",32*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x40, 0x01, 0x60, 0x03, 0x20, 0x03, 0x20, 0x03, 0x20, 0x03, 0x30, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0xF8, 0x0F, 0x08, 0x0C, 0x08, 0x0C, 0x08, 0x0C, 0x0C, 0x0C, 0x04, 0x18, 0x04, 0x18, 0x06, 0x18, 0x1F, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"A",33*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x18, 0x1C, 0x18, 0x38, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x18, 0x18, 0x0C, 0xF8, 0x07, 0x18, 0x18, 0x18, 0x30, 0x18, 0x20, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x18, 0x18, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"B",34*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x27, 0x60, 0x38, 0x10, 0x30, 0x18, 0x20, 0x0C, 0x40, 0x0C, 0x40, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0C, 0x40, 0x0C, 0x40, 0x0C, 0x20, 0x18, 0x30, 0x30, 0x18, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"C",35*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x03, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x18, 0x30, 0x18, 0x10, 0x18, 0x18, 0x18, 0x0E, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"D",36*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x18, 0x30, 0x18, 0x20, 0x18, 0x60, 0x18, 0x40, 0x18, 0x00, 0x18, 0x08, 0x18, 0x08, 0x18, 0x0C, 0xF8, 0x0F, 0x18, 0x0C, 0x18, 0x08, 0x18, 0x08, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x40, 0x18, 0x40, 0x18, 0x20, 0x18, 0x30, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"E",37*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x7F, 0x18, 0x70, 0x18, 0x40, 0x18, 0xC0, 0x18, 0x80, 0x18, 0x00, 0x18, 0x10, 0x18, 0x10, 0x18, 0x18, 0xF8, 0x1F, 0x18, 0x18, 0x18, 0x10, 0x18, 0x10, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"F",38*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x13, 0x70, 0x1C, 0x10, 0x10, 0x18, 0x10, 0x0C, 0x20, 0x0C, 0x20, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0xFC, 0x06, 0x30, 0x06, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x18, 0x30, 0x18, 0x30, 0x30, 0x08, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"G",39*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7E, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0xFC, 0x1F, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x3F, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"H",40*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1F, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"I",41*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x0E, 0x06, 0x0E, 0x03, 0x8E, 0x01, 0xFC, 0x00}, /*"J",42*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7C, 0x18, 0x18, 0x18, 0x08, 0x18, 0x04, 0x18, 0x06, 0x18, 0x02, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0xD8, 0x01, 0xB8, 0x03, 0x38, 0x03, 0x18, 0x07, 0x18, 0x06, 0x18, 0x0E, 0x18, 0x0C, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x30, 0x18, 0x30, 0x7E, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"K",43*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x40, 0x18, 0x40, 0x18, 0x20, 0x18, 0x30, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"L",44*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x3C, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x36, 0x74, 0x32, 0x64, 0x32, 0x64, 0x32, 0x64, 0x32, 0x64, 0x31, 0xC4, 0x31, 0xC4, 0x31, 0xC4, 0x31, 0xC4, 0x30, 0xC4, 0x30, 0x84, 0x30, 0x9F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"M",45*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x7C, 0x1C, 0x10, 0x3C, 0x10, 0x34, 0x10, 0x34, 0x10, 0x74, 0x10, 0x64, 0x10, 0xE4, 0x10, 0xC4, 0x10, 0xC4, 0x11, 0x84, 0x11, 0x84, 0x13, 0x04, 0x13, 0x04, 0x17, 0x04, 0x16, 0x04, 0x1E, 0x04, 0x1C, 0x04, 0x1C, 0x04, 0x1C, 0x04, 0x18, 0x1F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"N",46*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x30, 0x0C, 0x18, 0x18, 0x08, 0x10, 0x0C, 0x30, 0x0C, 0x30, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0C, 0x20, 0x0C, 0x30, 0x08, 0x10, 0x18, 0x18, 0x30, 0x0C, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"O",47*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0F, 0x18, 0x18, 0x18, 0x30, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x18, 0x18, 0xF8, 0x0F, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"P",48*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x30, 0x0C, 0x18, 0x18, 0x0C, 0x10, 0x0C, 0x30, 0x0C, 0x20, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0xE4, 0x61, 0x2C, 0x33, 0x1C, 0x32, 0x18, 0x16, 0x30, 0x0E, 0xC0, 0x07, 0x00, 0x4C, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00}, /*"Q",49*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x18, 0x1C, 0x18, 0x38, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x18, 0x18, 0x0C, 0xF8, 0x07, 0x98, 0x03, 0x18, 0x03, 0x18, 0x07, 0x18, 0x06, 0x18, 0x06, 0x18, 0x0E, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x1C, 0x18, 0x18, 0x7E, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"R",50*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x27, 0x30, 0x38, 0x18, 0x30, 0x0C, 0x20, 0x0C, 0x20, 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x78, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0x00, 0x1E, 0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x04, 0x60, 0x04, 0x60, 0x08, 0x60, 0x18, 0x30, 0x38, 0x18, 0xC8, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"S",51*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0x8C, 0x21, 0x84, 0x61, 0x82, 0x41, 0x82, 0x41, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"T",52*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7C, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x0C, 0x10, 0x08, 0x08, 0x38, 0x04, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"U",53*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xF8, 0x18, 0x20, 0x18, 0x20, 0x18, 0x20, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x30, 0x10, 0x60, 0x08, 0x60, 0x08, 0x60, 0x08, 0xE0, 0x0C, 0xC0, 0x04, 0xC0, 0x04, 0xC0, 0x04, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"V",54*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xF3, 0x86, 0x61, 0x86, 0x21, 0x86, 0x21, 0x8C, 0x21, 0x0C, 0x21, 0x8C, 0x23, 0x8C, 0x13, 0x8C, 0x13, 0x8C, 0x13, 0x4C, 0x13, 0x58, 0x12, 0x58, 0x16, 0x58, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x30, 0x0C, 0x10, 0x04, 0x10, 0x04, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"W",55*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x3E, 0x18, 0x08, 0x38, 0x08, 0x30, 0x04, 0x30, 0x04, 0x70, 0x02, 0x60, 0x02, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x03, 0x40, 0x03, 0x40, 0x07, 0x20, 0x06, 0x20, 0x06, 0x10, 0x0C, 0x10, 0x0C, 0x08, 0x18, 0x08, 0x18, 0x3E, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"X",56*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7C, 0x1C, 0x10, 0x18, 0x10, 0x18, 0x08, 0x30, 0x08, 0x30, 0x0C, 0x70, 0x04, 0x60, 0x04, 0x60, 0x02, 0xC0, 0x02, 0xC0, 0x02, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"Y",57*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x18, 0x18, 0x08, 0x18, 0x04, 0x0C, 0x04, 0x0E, 0x00, 0x06, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x70, 0x00, 0x30, 0x00, 0x38, 0x20, 0x18, 0x20, 0x1C, 0x10, 0x0C, 0x18, 0xFE, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"Z",58*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3F, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xC0, 0x3F, 0x00, 0x00, 0x00, 0x00}, /*"[",59*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0x60, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x18, 0x00, 0x18, 0x00, 0x10, 0x00, 0x30, 0x00, 0x20, 0x00, 0x00}, /*"\",60*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xFC, 0x03, 0x00, 0x00, 0x00, 0x00}, /*"]",61*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0xC0, 0x06, 0x20, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"^",62*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF}, /*"_",63*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xC0, 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}, /*"`",64*/ + {0x00, 0x00, 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, 0x18, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x0C, 0x80, 0x0F, 0x70, 0x0C, 0x1C, 0x0C, 0x0C, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x4C, 0x0C, 0x4F, 0xF8, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"a",65*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1E, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x0F, 0xD8, 0x18, 0x38, 0x30, 0x38, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x20, 0x38, 0x30, 0x78, 0x18, 0xC8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"b",66*/ + {0x00, 0x00, 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, 0x07, 0x70, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x18, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x20, 0x18, 0x20, 0x18, 0x10, 0x30, 0x08, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"c",67*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1E, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0xE0, 0x1B, 0x30, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x0C, 0x18, 0x08, 0x18, 0x18, 0x1C, 0x30, 0x7A, 0xE0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"d",68*/ + {0x00, 0x00, 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, 0x07, 0x30, 0x0C, 0x18, 0x18, 0x08, 0x10, 0x0C, 0x30, 0x0C, 0x30, 0xFC, 0x3F, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x20, 0x18, 0x10, 0x70, 0x18, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"e",69*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x80, 0xC3, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xFC, 0x1F, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"f",70*/ + {0x00, 0x00, 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, 0x77, 0x30, 0x6C, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x18, 0x30, 0x0C, 0xF0, 0x07, 0x18, 0x00, 0x18, 0x00, 0xF0, 0x0F, 0xF0, 0x3F, 0x08, 0x70, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x38, 0x38, 0xE0, 0x0F}, /*"g",71*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1E, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x98, 0x0F, 0xD8, 0x18, 0x38, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x7E, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"h",72*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"i",73*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x1F, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0C, 0x18, 0x06, 0xF0, 0x03}, /*"j",74*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1E, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x3E, 0x18, 0x0C, 0x18, 0x06, 0x18, 0x03, 0x18, 0x01, 0x98, 0x01, 0xD8, 0x01, 0x38, 0x03, 0x18, 0x07, 0x18, 0x06, 0x18, 0x0C, 0x18, 0x1C, 0x18, 0x18, 0x7E, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"k",75*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"l",76*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xEE, 0x1C, 0x9C, 0x33, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0xDE, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"m",77*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1E, 0x0F, 0xD8, 0x18, 0x38, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x7E, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"n",78*/ + {0x00, 0x00, 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, 0x07, 0x70, 0x1C, 0x10, 0x30, 0x18, 0x30, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x0C, 0x60, 0x18, 0x30, 0x18, 0x30, 0x30, 0x18, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"o",79*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x9E, 0x0F, 0x58, 0x18, 0x38, 0x30, 0x18, 0x20, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0x30, 0x38, 0x30, 0x78, 0x18, 0x98, 0x07, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x7E, 0x00}, /*"p",80*/ + {0x00, 0x00, 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, 0x23, 0x30, 0x3C, 0x18, 0x38, 0x18, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x08, 0x30, 0x18, 0x38, 0x30, 0x3C, 0xE0, 0x33, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xFC}, /*"q",81*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x7E, 0x3C, 0x60, 0x66, 0x60, 0x61, 0xE0, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"r",82*/ + {0x00, 0x00, 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, 0x27, 0x30, 0x38, 0x18, 0x30, 0x18, 0x20, 0x18, 0x00, 0x70, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0x00, 0x1C, 0x04, 0x30, 0x04, 0x30, 0x0C, 0x30, 0x1C, 0x18, 0xEC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"s",83*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0xFC, 0x1F, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x20, 0xC0, 0x20, 0x80, 0x11, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"t",84*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x1E, 0x3C, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x30, 0x18, 0x38, 0x30, 0xF4, 0xE0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"u",85*/ + {0x00, 0x00, 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, 0x3C, 0x18, 0x18, 0x18, 0x08, 0x38, 0x08, 0x30, 0x04, 0x30, 0x04, 0x70, 0x02, 0x60, 0x02, 0x60, 0x02, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"v",86*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xF7, 0x8E, 0x63, 0x0C, 0x23, 0x8C, 0x23, 0x8C, 0x23, 0x98, 0x13, 0x98, 0x13, 0x58, 0x16, 0x58, 0x16, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x20, 0x04, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"w",87*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3E, 0x70, 0x08, 0x70, 0x04, 0xE0, 0x04, 0xC0, 0x02, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x03, 0x40, 0x07, 0x60, 0x06, 0x20, 0x0C, 0x10, 0x0C, 0x18, 0x18, 0x3E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"x",88*/ + {0x00, 0x00, 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, 0x7C, 0x18, 0x18, 0x18, 0x08, 0x30, 0x08, 0x30, 0x08, 0x30, 0x04, 0x60, 0x04, 0x60, 0x04, 0xC0, 0x02, 0xC0, 0x02, 0xC0, 0x02, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x4C, 0x00, 0x3C, 0x00}, /*"y",89*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x0C, 0x0C, 0x04, 0x0E, 0x04, 0x06, 0x00, 0x03, 0x80, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x20, 0x30, 0x20, 0x38, 0x30, 0x1C, 0x18, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*"z",90*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x30, 0x00, 0x00}, /*"{",91*/ + {0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01}, /*"|",92*/ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, 0x00}, /*"}",93*/ + {0x00, 0x00, 0x38, 0x00, 0xC4, 0x00, 0x86, 0x40, 0x02, 0x61, 0x00, 0x22, 0x00, 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}, /*"~",94*/ +}; +#endif \ No newline at end of file diff --git a/board/yuzukilizard/spi_lcd/lcd_init.h b/board/yuzukilizard/spi_lcd/lcd_init.h new file mode 100644 index 00000000..2896f6da --- /dev/null +++ b/board/yuzukilizard/spi_lcd/lcd_init.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __LCD_INIT_H__ +#define __LCD_INIT_H__ + +#include +#include +#include +#include + +void LCD_Write_Data_Bus(void *dat, uint32_t len); + +void LCD_WR_DATA8(uint8_t dat); + +void LCD_WR_REG(uint8_t dat); + +void LCD_WR_DATA(uint16_t dat); + +void LCD_Address_Set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); + +#endif//__LCD_INIT_H__ \ No newline at end of file diff --git a/board/yuzukilizard/spi_lcd/main.c b/board/yuzukilizard/spi_lcd/main.c new file mode 100644 index 00000000..d7ba91b1 --- /dev/null +++ b/board/yuzukilizard/spi_lcd/main.c @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "sys-dram.h" +#include "sys-dma.h" +#include "sys-spi.h" + +#include "lcd.h" +#include "lcd_init.h" + +#define CONFIG_HEAP_BASE (0x40800000) +#define CONFIG_HEAP_SIZE (16 * 1024 * 1024) + +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; + +sunxi_spi_t sunxi_spi0_lcd = { + .base = 0x04025000, + .id = 0, + .clk_rate = 120 * 1000 * 1000, + .gpio_cs = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX4}, + .gpio_sck = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX4}, + .gpio_mosi = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX4}, + .gpio_miso = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX4}, +}; + +static gpio_mux_t lcd_dc_pins = { + .pin = GPIO_PIN(GPIO_PORTC, 4), + .mux = GPIO_OUTPUT, +}; + +static gpio_mux_t lcd_res_pins = { + .pin = GPIO_PIN(GPIO_PORTC, 5), + .mux = GPIO_OUTPUT, +}; + +static void LCD_Set_DC(uint8_t val) { + sunxi_gpio_set_value(lcd_dc_pins.pin, val); +} + +static void LCD_Set_RES(uint8_t val) { + sunxi_gpio_set_value(lcd_res_pins.pin, val); +} + +static void LCD_Write_Bus(uint8_t dat) { + uint8_t tx[1]; /* Transmit buffer */ + int r; /* Return value */ + + tx[0] = dat; + r = sunxi_spi_transfer(&sunxi_spi0_lcd, SPI_IO_SINGLE, tx, 1, 0, 0); /* Perform SPI transfer */ + if (r < 0) + printk(LOG_LEVEL_ERROR, "SPI: SPI Xfer error!\n"); +} + +void LCD_Write_Data_Bus(void *dat, uint32_t len) { + int r = sunxi_spi_transfer(&sunxi_spi0_lcd, SPI_IO_SINGLE, dat, len, 0, 0); /* Perform SPI transfer */ + if (r < 0) + printk(LOG_LEVEL_ERROR, "SPI: SPI Xfer error!\n"); +} + +void LCD_WR_DATA(uint16_t dat) { + LCD_Write_Bus(dat >> 8); + LCD_Write_Bus(dat); +} + +void LCD_Address_Set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + LCD_WR_REG(0x2a); + LCD_WR_DATA(x1); + LCD_WR_DATA(x2); + LCD_WR_REG(0x2b); + LCD_WR_DATA(y1); + LCD_WR_DATA(y2); + LCD_WR_REG(0x2c); +} + +void LCD_WR_DATA8(uint8_t dat) { + LCD_Write_Bus(dat); +} + +void LCD_WR_REG(uint8_t dat) { + LCD_Set_DC(0); + LCD_Write_Bus(dat); + LCD_Set_DC(1); +} + +static void LCD_Init(void) { + LCD_Set_RES(0);//复位 + mdelay(100); + LCD_Set_RES(1); + mdelay(100); + + LCD_WR_REG(0x11);//Sleep out + mdelay(120); //Delay 120ms + LCD_WR_REG(0x36); + LCD_WR_DATA8(0x00); + + LCD_WR_REG(0x3A); + LCD_WR_DATA8(0x05); + + LCD_WR_REG(0xB2); + LCD_WR_DATA8(0x1F); + LCD_WR_DATA8(0x1F); + LCD_WR_DATA8(0x00); + LCD_WR_DATA8(0x33); + LCD_WR_DATA8(0x33); + + LCD_WR_REG(0xB7); + LCD_WR_DATA8(0x35); + + LCD_WR_REG(0xBB); + LCD_WR_DATA8(0x20);//2b + + LCD_WR_REG(0xC0); + LCD_WR_DATA8(0x2C); + + LCD_WR_REG(0xC2); + LCD_WR_DATA8(0x01); + + LCD_WR_REG(0xC3); + LCD_WR_DATA8(0x01); + + LCD_WR_REG(0xC4); + LCD_WR_DATA8(0x18);//VDV, 0x20:0v + + LCD_WR_REG(0xC6); + LCD_WR_DATA8(0x13);//0x13:60Hz + + LCD_WR_REG(0xD0); + LCD_WR_DATA8(0xA4); + LCD_WR_DATA8(0xA1); + + LCD_WR_REG(0xD6); + LCD_WR_DATA8(0xA1);//sleep in后,gate输出为GND + + LCD_WR_REG(0xE0); + LCD_WR_DATA8(0xF0); + LCD_WR_DATA8(0x04); + LCD_WR_DATA8(0x07); + LCD_WR_DATA8(0x04); + LCD_WR_DATA8(0x04); + LCD_WR_DATA8(0x04); + LCD_WR_DATA8(0x25); + LCD_WR_DATA8(0x33); + LCD_WR_DATA8(0x3C); + LCD_WR_DATA8(0x36); + LCD_WR_DATA8(0x14); + LCD_WR_DATA8(0x12); + LCD_WR_DATA8(0x29); + LCD_WR_DATA8(0x30); + + LCD_WR_REG(0xE1); + LCD_WR_DATA8(0xF0); + LCD_WR_DATA8(0x02); + LCD_WR_DATA8(0x04); + LCD_WR_DATA8(0x05); + LCD_WR_DATA8(0x05); + LCD_WR_DATA8(0x21); + LCD_WR_DATA8(0x25); + LCD_WR_DATA8(0x32); + LCD_WR_DATA8(0x3B); + LCD_WR_DATA8(0x38); + LCD_WR_DATA8(0x12); + LCD_WR_DATA8(0x14); + LCD_WR_DATA8(0x27); + LCD_WR_DATA8(0x31); + + LCD_WR_REG(0xE4); + LCD_WR_DATA8(0x1D);//使用240根gate (N+1)*8 + LCD_WR_DATA8(0x00);//设定gate起点位置 + LCD_WR_DATA8(0x00);//当gate没有用完时,bit4(TMG)设为0 + + LCD_WR_REG(0x21); + + LCD_WR_REG(0x29); +} + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_clk_init(); + + uint64_t dram_size = sunxi_dram_init(&dram_para); + arm32_mmu_enable(SDRAM_BASE, dram_size); + + printk(LOG_LEVEL_DEBUG, "enable mmu ok\n"); + + smalloc_init(CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE); + + printk(LOG_LEVEL_INFO, "Hello World!\n"); + + sunxi_gpio_init(lcd_dc_pins.pin, lcd_dc_pins.mux); + sunxi_gpio_init(lcd_res_pins.pin, lcd_res_pins.mux); + + dma_init(); + + if (sunxi_spi_init(&sunxi_spi0_lcd) != 0) { + printk(LOG_LEVEL_ERROR, "SPI: init failed\n"); + } + + LCD_Init(); + + LCD_Fill_All(WHITE); + + LCD_ShowString(0, 40, "LCD_W:", RED, WHITE, 16, 0); + + LCD_ShowIntNum(48, 40, LCD_W, 3, RED, WHITE, 16); + + LCD_ShowString(80, 40, "LCD_H:", RED, WHITE, 16, 0); + + LCD_ShowIntNum(128, 40, LCD_H, 3, RED, WHITE, 16); + + LCD_ShowString(80, 40, "LCD_H:", RED, WHITE, 16, 0); + + LCD_ShowString(0, 80, "LCD ST7789V2", BLUE, WHITE, 32, 0); + + LCD_ShowString(0, 160, "SyterKit", BLACK, WHITE, 32, 0); + + LCD_ShowString(0, 240, "1.0.2", BLACK, WHITE, 32, 0); + + sunxi_spi_disable(&sunxi_spi0_lcd); + + arm32_mmu_disable(); + + clean_syterkit_data(); + + sunxi_clk_reset(); + + jmp_to_fel(); + + return 0; +} \ No newline at end of file diff --git a/board/yuzukilizard/start.S b/board/yuzukilizard/start.S new file mode 100644 index 00000000..b55ac933 --- /dev/null +++ b/board/yuzukilizard/start.S @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#define ARMV7_USR_MODE 0x10 +#define ARMV7_FIQ_MODE 0x11 +#define ARMV7_IRQ_MODE 0x12 +#define ARMV7_SVC_MODE 0x13 +#define ARMV7_MON_MODE 0x16 +#define ARMV7_ABT_MODE 0x17 +#define ARMV7_UND_MODE 0x1b +#define ARMV7_SYSTEM_MODE 0x1f +#define ARMV7_MODE_MASK 0x1f +#define ARMV7_FIQ_MASK 0x40 +#define ARMV7_IRQ_MASK 0x80 + +.arm +.globl reset +.text + +reset: + /* Boot head information for BROM */ + .long 0xea000016 + .byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0' + .long 0x12345678 /* checksum */ + .long __spl_size /* spl size */ + .long 0x30 /* boot header size */ + .long 0x30303033 /* boot header version */ + .long 0x00020000 /* return value */ + .long 0x00028000 /* run address */ + .long 0x0 /* eGON version */ + .byte 0x00, 0x00, 0x00, 0x00 /* platform information - 8byte */ + .byte 0x34, 0x2e, 0x30, 0x00 + + /* + * The actual reset code + */ + mrs r0, cpsr + bic r0, r0, #ARMV7_MODE_MASK + orr r0, r0, #ARMV7_SVC_MODE + orr r0, r0, #(ARMV7_IRQ_MASK | ARMV7_FIQ_MASK) + bic r0, r0, #(1<<9) @set little-endian + msr cpsr_c, r0 + + /* Set vector base address register */ + + ldr r0, =_vector + mcr p15, 0, r0, c12, c0, 0 + mrc p15, 0, r0, c1, c0, 0 + bic r0, #(1 << 13) + mcr p15, 0, r0, c1, c0, 0 + + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002000 @ clear bits 13 (--V-) + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache + mcr p15, 0, r0, c1, c0, 0 + + /* Enable neon/vfp unit */ + mrc p15, 0, r0, c1, c0, 2 + orr r0, r0, #(0xf << 20) + mcr p15, 0, r0, c1, c0, 2 + isb + mov r0, #0x40000000 + vmsr fpexc, r0 + + /* Set stack pointer */ + ldr sp, =__stack_srv_end + + bl clear_bss + + /* + * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, + * except if in HYP mode already + */ + mrs r0, cpsr + and r1, r0, #0x1f @ mask mode bits + teq r1, #0x1a @ test for HYP mode + bicne r0, r0, #0x1f @ clear all mode bits + orrne r0, r0, #0x13 @ set SVC mode + orr r0, r0, #0xc0 @ disable FIQ and IRQ + msr cpsr,r0 + + @set cntfrq to 24M + ldr r0, =24000000 + mcr p15, 0, r0, c14, c0, 0 + + bl set_timer_count + + bl main + + clear_bss: + ldr r0, =_sbss + ldr r1, =_ebss + mov r2, #0 + + clbss_1: + stmia r0!, {r2} + cmp r0, r1 + blt clbss_1 + + mov pc, lr + +_vector: + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq + +.macro save_regs + str lr, [sp, #-4] + mrs lr, spsr_all + str lr, [sp, #-8] + str r1, [sp, #-12] + str r0, [sp, #-16] + mov r0, sp + cps #0x13 + ldr r1, [r0, #-4] + str r1, [sp, #-4]! + ldr r1, [r0, #-8] + str r1, [sp, #-(4 * 16)] + ldr r1, [r0, #-12] + ldr r0, [r0, #-16] + stmdb sp, {r0 - r14}^ + sub sp, sp, #(4 * 16) + ldr r4, [sp] + and r0, r4, #0x1f + cmp r0, #0x10 + beq 10f + cmp r0, #0x13 + beq 11f + b . +11: add r1, sp, #(4 * 17) + str r1, [sp, #(4 * 14)] + str lr, [sp, #(4 * 15)] +10: add r1, sp, #(4 * 17) + str r1, [sp, #-4]! + mov r0, sp +.endm + +.macro restore_regs + mov r12, sp + ldr sp, [r12], #4 + ldr r1, [r12], #4 + msr spsr_cxsf, r1 + and r0, r1, #0x1f + cmp r0, #0x10 + beq 20f + cmp r0, #0x13 + beq 21f + b . +20: ldr lr, [r12, #(4 * 15)] + ldmia r12, {r0 - r14}^ + movs pc, lr +21: ldm r12, {r0 - r15}^ + mov r0, r0 +.endm + + /* + * Exception handlers + */ + .align 5 +undefined_instruction: + sub lr, lr, #4 + save_regs + bl arm32_do_undefined_instruction + restore_regs + + .align 5 +software_interrupt: + sub lr, lr, #4 + save_regs + bl arm32_do_software_interrupt + restore_regs + + .align 5 +prefetch_abort: + sub lr, lr, #4 + save_regs + bl arm32_do_prefetch_abort + restore_regs + + .align 5 +data_abort: + sub lr, lr, #8 + save_regs + bl arm32_do_data_abort + restore_regs + + .align 5 +not_used: + b . + + .align 5 +irq: + sub lr, lr, #4 + save_regs + bl arm32_do_irq + restore_regs + + .align 5 +fiq: + sub lr, lr, #4 + save_regs + bl arm32_do_fiq + restore_regs diff --git a/board/yuzukilizard/syter_amp/CMakeLists.txt b/board/yuzukilizard/syter_amp/CMakeLists.txt new file mode 100644 index 00000000..317a0987 --- /dev/null +++ b/board/yuzukilizard/syter_amp/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(syter_amp + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/syter_amp/main.c b/board/yuzukilizard/syter_amp/main.c new file mode 100644 index 00000000..a84259d3 --- /dev/null +++ b/board/yuzukilizard/syter_amp/main.c @@ -0,0 +1,289 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" + +#include "libfdt.h" +#include "ff.h" + +#define CONFIG_KERNEL_FILENAME "zImage" +#define CONFIG_DTB_FILENAME "sunxi.dtb" +#define CONFIG_RISCV_ELF_FILENAME "e907.elf" + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +#define CONFIG_RISCV_ELF_LOADADDR (0x40008000) +#define CONFIG_DTB_LOAD_ADDR (0x41008000) +#define CONFIG_KERNEL_LOAD_ADDR (0x41800000) + +// 128KB erase sectors, so place them starting from 2nd sector +#define CONFIG_SPINAND_DTB_ADDR (128 * 2048) +#define CONFIG_SPINAND_KERNEL_ADDR (256 * 2048) + +#define FILENAME_MAX_LEN 64 +typedef struct { + unsigned int offset; + unsigned char *dest; + + unsigned int of_offset; + unsigned char *of_dest; + + unsigned int elf_offset; + unsigned char *elf_dest; + + char filename[FILENAME_MAX_LEN]; + char of_filename[FILENAME_MAX_LEN]; + char elf_filename[FILENAME_MAX_LEN]; +} image_info_t; + +/* Linux zImage Header */ +#define LINUX_ZIMAGE_MAGIC 0x016f2818 +typedef struct { + unsigned int code[9]; + unsigned int magic; + unsigned int start; + unsigned int end; +} linux_zimage_header_t; + +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; + +sunxi_serial_t uart_e907 = { + .base = 0x02500C00, + .id = 3, + .gpio_tx = {GPIO_PIN(GPIO_PORTE, 0), GPIO_PERIPH_MUX7}, + .gpio_rx = {GPIO_PIN(GPIO_PORTE, 1), GPIO_PERIPH_MUX7}, +}; + +extern sunxi_spi_t sunxi_spi0; + +extern sdhci_t sdhci0; + +image_info_t image; + +unsigned int code[9]; +unsigned int magic; +unsigned int start; +unsigned int end; + +static int boot_image_setup(unsigned char *addr, unsigned int *entry) { + linux_zimage_header_t *zimage_header = (linux_zimage_header_t *) addr; + + printk(LOG_LEVEL_INFO, "Linux zImage->code = 0x"); + for (int i = 0; i < 9; i++) + printk(LOG_LEVEL_MUTE, "%x", code[i]); + + printk(LOG_LEVEL_MUTE, "\n"); + printk(LOG_LEVEL_DEBUG, "Linux zImage->magic = 0x%x\n", zimage_header->magic); + printk(LOG_LEVEL_DEBUG, "Linux zImage->start = 0x%x\n", (unsigned int) addr + zimage_header->start); + printk(LOG_LEVEL_DEBUG, "Linux zImage->end = 0x%x\n", (unsigned int) addr + zimage_header->end); + + if (zimage_header->magic == LINUX_ZIMAGE_MAGIC) { + *entry = ((unsigned int) addr + zimage_header->start); + return 0; + } + + printk(LOG_LEVEL_ERROR, "unsupported kernel image\n"); + + return -1; +} + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: open, filename: [%s]: error %d\n", filename, fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\n", time, (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, + CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->of_filename, (unsigned int) image->of_dest); + ret = fatfs_loadimage(image->of_filename, image->of_dest); + if (ret) + return ret; + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, (unsigned int) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->elf_filename, (unsigned int) image->elf_dest); + ret = fatfs_loadimage(image->elf_filename, image->elf_dest); + if (ret) + return ret; + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + + + +int main(void) { + sunxi_serial_init(&uart_dbg); + + sunxi_serial_init(&uart_e907); + + show_banner(); + + sunxi_clk_init(); + + sunxi_dram_init(&dram_para); + + unsigned int entry_point = 0; + void (*kernel_entry)(int zero, int arch, unsigned int params); + + sunxi_clk_dump(); + + memset(&image, 0, sizeof(image_info_t)); + + image.of_dest = (uint8_t *) CONFIG_DTB_LOAD_ADDR; + image.dest = (uint8_t *) CONFIG_KERNEL_LOAD_ADDR; + image.elf_dest = (uint8_t *) CONFIG_RISCV_ELF_LOADADDR; + + strcpy(image.filename, CONFIG_KERNEL_FILENAME); + strcpy(image.of_filename, CONFIG_DTB_FILENAME); + strcpy(image.elf_filename, CONFIG_RISCV_ELF_FILENAME); + + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: init failed, back to FEL\n"); + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: loading failed, back to FEL\n"); + goto _fel; + } + + sunxi_e907_clock_reset(); + + uint32_t elf_run_addr = elf32_get_entry_addr((phys_addr_t) image.dest); + printk(LOG_LEVEL_INFO, "RISC-V ELF run addr: 0x%08x\n", elf_run_addr); + + if (load_elf32_image((phys_addr_t) image.dest)) { + printk(LOG_LEVEL_ERROR, "RISC-V ELF load FAIL\n"); + } + + sunxi_e907_clock_init(elf_run_addr); + + dump_e907_clock(); + + printk(LOG_LEVEL_INFO, "RISC-V E907 Core now Running... \n"); + + if (boot_image_setup((unsigned char *) image.dest, &entry_point)) { + printk(LOG_LEVEL_ERROR, "boot setup failed\n"); + goto _fel; + } + + printk(LOG_LEVEL_INFO, "booting linux...\n"); + + arm32_mmu_disable(); + printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); + arm32_dcache_disable(); + printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); + arm32_icache_disable(); + printk(LOG_LEVEL_INFO, "disable icache ok...\n"); + arm32_interrupt_disable(); + printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); + enable_kernel_smp(); + printk(LOG_LEVEL_INFO, "enable kernel smp ok...\n"); + + printk(LOG_LEVEL_INFO, "jump to kernel address: 0x%x\n", image.dest); + + kernel_entry = (void (*)(int, int, unsigned int)) entry_point; + kernel_entry(0, ~0, (unsigned int) image.of_dest); + + // if kernel boot not success, jump to fel. +_fel: + jmp_to_fel(); + + return 0; +} diff --git a/board/yuzukilizard/syter_boot/CMakeLists.txt b/board/yuzukilizard/syter_boot/CMakeLists.txt new file mode 100644 index 00000000..5bfbb5f4 --- /dev/null +++ b/board/yuzukilizard/syter_boot/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(syter_boot + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/syter_boot/main.c b/board/yuzukilizard/syter_boot/main.c new file mode 100644 index 00000000..7ad476f5 --- /dev/null +++ b/board/yuzukilizard/syter_boot/main.c @@ -0,0 +1,698 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-rtc.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" + +#include "fdt_wrapper.h" +#include "ff.h" +#include "libfdt.h" +#include "uart.h" + +#define CONFIG_KERNEL_FILENAME "zImage" +#define CONFIG_DTB_FILENAME "sunxi.dtb" +#define CONFIG_CONFIG_FILENAME "config.txt" + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +#define CONFIG_DTB_LOAD_ADDR (0x41008000) +#define CONFIG_KERNEL_LOAD_ADDR (0x41800000) +#define CONFIG_CONFIG_LOAD_ADDR (0x40008000) +#define CONFIG_HEAP_BASE (0x40800000) +#define CONFIG_HEAP_SIZE (16 * 1024 * 1024) + +#define CONFIG_DEFAULT_BOOTDELAY 5 + +#define FILENAME_MAX_LEN 64 +typedef struct { + uint8_t *dest; + + uint8_t *of_dest; + + uint8_t *config_dest; + uint8_t is_config; + + char filename[FILENAME_MAX_LEN]; + + char of_filename[FILENAME_MAX_LEN]; + + char config_filename[FILENAME_MAX_LEN]; +} image_info_t; + +#define MAX_SECTION_LEN 16 +#define MAX_KEY_LEN 16 +#define MAX_VALUE_LEN 512 +#define CONFIG_MAX_ENTRY 3 + +typedef struct { + char section[MAX_SECTION_LEN]; + char key[MAX_KEY_LEN]; + char value[MAX_VALUE_LEN]; +} IniEntry; + +IniEntry entries[CONFIG_MAX_ENTRY]; + +/* Linux zImage Header */ +#define LINUX_ZIMAGE_MAGIC 0x016f2818 +typedef struct { + uint32_t code[9]; + uint32_t magic; + uint32_t start; + uint32_t end; +} linux_zimage_header_t; + +extern sunxi_serial_t uart_dbg; + +extern sunxi_spi_t sunxi_spi0; + +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; + +image_info_t image; + +uint32_t code[9]; +uint32_t magic; +uint32_t start; +uint32_t end; + +static int boot_image_setup(uint8_t *addr, uint32_t *entry) { + linux_zimage_header_t *zimage_header = (linux_zimage_header_t *) addr; + + printk(LOG_LEVEL_INFO, "Linux zImage->code = 0x"); + for (int i = 0; i < 9; i++) + printk(LOG_LEVEL_MUTE, "%x", code[i]); + + printk(LOG_LEVEL_MUTE, "\n"); + printk(LOG_LEVEL_DEBUG, "Linux zImage->magic = 0x%x\n", + zimage_header->magic); + printk(LOG_LEVEL_DEBUG, "Linux zImage->start = 0x%x\n", + (uint32_t) addr + zimage_header->start); + printk(LOG_LEVEL_DEBUG, "Linux zImage->end = 0x%x\n", + (uint32_t) addr + zimage_header->end); + + if (zimage_header->magic == LINUX_ZIMAGE_MAGIC) { + *entry = ((uint32_t) addr + zimage_header->start); + return 0; + } + + printk(LOG_LEVEL_ERROR, "unsupported kernel image\n"); + + return -1; +} + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret = 1; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: open, filename: [%s]: error %d\n", filename, fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_INFO, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + /* load DTB */ + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->of_filename, (uint32_t) image->of_dest); + ret = fatfs_loadimage(image->of_filename, image->of_dest); + if (ret) + return ret; + + /* load Kernel */ + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, (uint32_t) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + /* load config */ + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->config_filename, (uint32_t) image->config_dest); + ret = fatfs_loadimage(image->config_filename, image->config_dest); + if (ret) { + printk(LOG_LEVEL_INFO, "CONFIG: Cannot find config file, Using default config.\n"); + image->is_config = 0; + } else { + image->is_config = 1; + } + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_INFO, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + +static void trim(char *str) { + int len = strlen(str); + while (len > 0 && (str[len - 1] == ' ' || str[len - 1] == '\n' || str[len - 1] == '\r')) { + str[--len] = '\0'; + } + while (*str && (*str == ' ' || *str == '\n' || *str == '\r')) { + ++str; + --len; + } +} + +static int parse_ini_data(const char *data, size_t size, IniEntry *entries, int max_entries) { + char line[MAX_VALUE_LEN]; + char current_section[MAX_SECTION_LEN] = ""; + int entry_count = 0; + + const char *p = data; + const char *end = data + size; + + while (p < end) { + /* Read a line of data */ + size_t len = 0; + while (p + len < end && *(p + len) != '\n') { + ++len; + } + if (p + len < end && *(p + len) == '\n') { + ++len; + } + if (len > 0) { + strncpy(line, p, len); + line[len] = '\0'; + p += len; + + trim(line); + + /* Ignore empty lines and comments */ + if (line[0] == '\0' || line[0] == ';' || line[0] == '#') { + continue; + } + + /* Parse the section name */ + if (line[0] == '[' && line[strlen(line) - 1] == ']') { + strncpy(current_section, &line[1], strlen(line) - 2); + current_section[strlen(line) - 2] = '\0'; + continue; + } + + /* Parse key-value pairs */ + char *pos = strchr(line, '='); + if (pos != NULL) { + char *key_start = line; + char *value_start = pos + 1; + *pos = '\0'; + trim(key_start); + trim(value_start); + + if (strlen(current_section) > 0 && strlen(key_start) > 0 && strlen(value_start) > 0) { + if (entry_count >= max_entries) { + printk(LOG_LEVEL_ERROR, "INI: Too many entries!\n"); + break; + } + strncpy(entries[entry_count].section, current_section, MAX_SECTION_LEN - 1); + strncpy(entries[entry_count].key, key_start, MAX_KEY_LEN - 1); + strncpy(entries[entry_count].value, value_start, MAX_VALUE_LEN - 1); + ++entry_count; + } + } + } + } + + return entry_count; +} + +static const char *find_entry_value(const IniEntry *entries, int entry_count, const char *section, const char *key) { + for (int i = 0; i < entry_count; ++i) { + if (strcmp(entries[i].section, section) == 0 && strcmp(entries[i].key, key) == 0) { + return entries[i].value; + } + } + return NULL; +} + +static int update_bootargs_from_config(uint64_t dram_size) { + int ret = 0; + char *bootargs_str_config = NULL; + char *mac_addr = NULL; + + /* Check if using config file, get bootargs in the config file */ + if (image.is_config) { + size_t size_a = strlen(image.config_dest); + int entry_count = parse_ini_data(image.config_dest, size_a, entries, CONFIG_MAX_ENTRY); + for (int i = 0; i < entry_count; ++i) { + /* Print parsed INI entries */ + printk(LOG_LEVEL_DEBUG, "INI: [%s] %s = %s\n", entries[i].section, entries[i].key, entries[i].value); + } + bootargs_str_config = find_entry_value(entries, entry_count, "configs", "bootargs"); + mac_addr = find_entry_value(entries, entry_count, "configs", "mac_addr"); + } + + /* Force image.dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + /* Check if DTB header is valid */ + if ((ret = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(ret)); + return -1; + } + + /* Get the total size of DTB */ + uint32_t size = fdt_totalsize(image.of_dest); + printk(LOG_LEVEL_DEBUG, "%s: FDT Size = %d\n", image.of_filename, size); + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + + /* If config file read fail or not using */ + if (bootargs_str_config == NULL) { + printk(LOG_LEVEL_WARNING, "INI: Cannot parse bootargs, using default bootargs in DTB.\n"); + bootargs_str_config = bootargs_str; + } + + /* update mac address of board */ + if (mac_addr != NULL) { + strcat(bootargs_str_config, " mac_addr="); + strcat(bootargs_str_config, mac_addr); + } + + /* Add dram size to dtb */ + char dram_size_str[8]; + strcat(bootargs_str_config, " mem="); + strcat(bootargs_str_config, ltoa(dram_size, dram_size_str, 10)); + strcat(bootargs_str_config, "M"); + + /* Set bootargs based on the configuration file */ + printk(LOG_LEVEL_DEBUG, "INI: Set bootargs to %s\n", bootargs_str_config); + +_add_dts_size: + /* Modify bootargs string */ + ret = fdt_setprop(image.of_dest, bootargs_node, "bootargs", bootargs_str_config, strlen(bootargs_str_config) + 1); + if (ret == -FDT_ERR_NOSPACE) { + printk(LOG_LEVEL_DEBUG, "FDT: FDT_ERR_NOSPACE, Size = %d, Increase Size = %d\n", size, 512); + ret = fdt_increase_size(image.of_dest, 512); + if (!ret) + goto _add_dts_size; + else + goto _err_size; + } else if (ret < 0) { + printk(LOG_LEVEL_ERROR, "Can't change bootargs node: %s\n", fdt_strerror(ret)); + return -1; + } + + /* Get the total size of DTB */ + printk(LOG_LEVEL_DEBUG, "Modify FDT Size = %d\n", fdt_totalsize(image.of_dest)); + + if (ret < 0) { + printk(LOG_LEVEL_ERROR, "libfdt fdt_setprop() error: %s\n", fdt_strerror(ret)); + return -1; + } + + return 0; +_err_size: + printk(LOG_LEVEL_ERROR, "DTB: Can't increase blob size: %s\n", fdt_strerror(ret)); + return -1; +} + +static int abortboot_single_key(int bootdelay) { + int abort = 0; + unsigned long ts; + + printk(LOG_LEVEL_INFO, "Hit any key to stop autoboot: %2d ", bootdelay); + + /* Check if key already pressed */ + if (tstc()) { /* we got a key press */ + uart_getchar(); /* consume input */ + printk(LOG_LEVEL_MUTE, "\b\b\b%2d", bootdelay); + abort = 1; /* don't auto boot */ + } + + while ((bootdelay > 0) && (!abort)) { + --bootdelay; + /* delay 1000 ms */ + ts = time_ms(); + do { + if (tstc()) { /* we got a key press */ + abort = 1; /* don't auto boot */ + break; + } + udelay(10000); + } while (!abort && time_ms() - ts < 1000); + printk(LOG_LEVEL_MUTE, "\b\b\b%2d ", bootdelay); + } + uart_putchar('\n'); + return abort; +} + +msh_declare_command(bootargs); +msh_define_help(bootargs, "get/set bootargs for kernel", + "Usage: bootargs set \"bootargs\" - set new bootargs for zImage\n" + " bootargs get - get current bootargs\n"); +int cmd_bootargs(int argc, const char **argv) { + int err = 0; + + if (argc < 2) { + uart_puts(cmd_bootargs_usage); + return 0; + } + + if (strncmp(argv[1], "set", 3) == 0) { + if (argc != 3) { + uart_puts(cmd_bootargs_usage); + return 0; + } + /* Force image.of_dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + return 0; + } + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB OLD bootargs = \"%s\"\n", bootargs_str); + + /* New bootargs string */ + char *new_bootargs_str = argv[2]; + printk(LOG_LEVEL_MUTE, "Now set bootargs to \"%s\"\n", new_bootargs_str); + + _add_dts_size: + /* Modify bootargs string */ + err = fdt_setprop(image.of_dest, bootargs_node, "bootargs", new_bootargs_str, strlen(new_bootargs_str) + 1); + if (err == -FDT_ERR_NOSPACE) { + printk(LOG_LEVEL_DEBUG, "FDT: FDT_ERR_NOSPACE, Increase Size = %d\n", 512); + err = fdt_increase_size(image.of_dest, 512); + if (!err) + goto _add_dts_size; + else + goto _err_size; + } else if (err < 0) { + printk(LOG_LEVEL_ERROR, "Can't change bootargs node: %s\n", fdt_strerror(err)); + abort(); + } + + /* Get updated bootargs string */ + char *updated_bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB NEW bootargs = \"%s\"\n", updated_bootargs_str); + } else if (strncmp(argv[1], "get", 3) == 0) { + /* Force image.of_dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + int err = 0; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + return 0; + } + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB bootargs = \"%s\"\n", bootargs_str); + } else { + uart_puts(cmd_bootargs_usage); + } + return 0; + +_err_size: + printk(LOG_LEVEL_ERROR, "DTB: Can't increase blob size: %s\n", fdt_strerror(err)); + abort(); +} + +msh_declare_command(reload); +msh_define_help(reload, "rescan TF Card and reload DTB, Kernel zImage", "Usage: reload\n"); +int cmd_reload(int argc, const char **argv) { + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + return 0; + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + return 0; + } + return 0; +} + +msh_declare_command(print); +msh_define_help(print, "print out env config", "Usage: print\n"); +int cmd_print(int argc, const char **argv) { + if (image.is_config) { + size_t size_a = strlen(image.config_dest); + int entry_count = parse_ini_data(image.config_dest, size_a, entries, CONFIG_MAX_ENTRY); + for (int i = 0; i < entry_count; ++i) { + /* Print parsed INI entries */ + printk(LOG_LEVEL_MUTE, "ENV: [%s] %s = %s\n", entries[i].section, entries[i].key, entries[i].value); + } + } else { + printk(LOG_LEVEL_WARNING, "ENV: Can not find env file\n"); + } + return 0; +} + +msh_declare_command(boot); +msh_define_help(boot, "boot to linux", "Usage: boot\n"); +int cmd_boot(int argc, const char **argv) { + /* Initialize variables for kernel entry point and SD card access. */ + uint32_t entry_point = 0; + void (*kernel_entry)(int zero, int arch, uint32_t params); + + /* Set up boot parameters for the kernel. */ + if (boot_image_setup((uint8_t *) image.dest, &entry_point)) { + printk(LOG_LEVEL_ERROR, "boot setup failed\n"); + abort(); + } + + /* Disable MMU, data cache, instruction cache, interrupts */ + clean_syterkit_data(); + + enable_kernel_smp(); + printk(LOG_LEVEL_INFO, "enable kernel smp ok...\n"); + + /* Debug message to indicate the kernel address that the system is jumping to. */ + printk(LOG_LEVEL_INFO, "jump to kernel address: 0x%x\n\n", image.dest); + + /* Jump to the kernel entry point. */ + kernel_entry = (void (*)(int, int, uint32_t)) entry_point; + kernel_entry(0, ~0, (uint32_t) image.of_dest); + + // if kernel boot not success, jump to fel. + jmp_to_fel(); + return 0; +} + +const msh_command_entry commands[] = { + msh_define_command(bootargs), + msh_define_command(reload), + msh_define_command(boot), + msh_define_command(print), + msh_command_end, +}; + +/* + * main function for the bootloader. Initializes and sets up the system, loads the kernel and device tree binary from + * an SD card, sets boot arguments, and boots the kernel. If the kernel fails to boot, the function jumps to FEL mode. + */ +int main(void) { + /* Initialize the debug serial interface. */ + sunxi_serial_init(&uart_dbg); + + /* Display the bootloader banner. */ + show_banner(); + + /* Initialize the system clock. */ + sunxi_clk_init(); + + /* Check rtc fel flag. if set flag, goto fel */ + if (rtc_probe_fel_flag()) { + printk(LOG_LEVEL_INFO, "RTC: get fel flag, jump to fel mode.\n"); + clean_syterkit_data(); + rtc_clear_fel_flag(); + sunxi_clk_reset(); + mdelay(100); + goto _fel; + } + + /* Initialize the DRAM and enable memory management unit (MMU). */ + uint64_t dram_size = sunxi_dram_init(&dram_para); + arm32_mmu_enable(SDRAM_BASE, dram_size); + + /* Debug message to indicate that MMU is enabled. */ + printk(LOG_LEVEL_DEBUG, "enable mmu ok\n"); + + /* Initialize the small memory allocator. */ + smalloc_init(CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE); + + /* Set up Real-Time Clock (RTC) hardware. */ + rtc_set_vccio_det_spare(); + + /* Check if system voltage is within limits. */ + sys_ldo_check(); + + /* Dump information about the system clocks. */ + sunxi_clk_dump(); + + /* Clear the image_info_t struct. */ + memset(&image, 0, sizeof(image_info_t)); + + /* Set the destination address for the device tree binary (DTB), kernel image, and configuration data. */ + image.of_dest = (uint8_t *) CONFIG_DTB_LOAD_ADDR; + image.dest = (uint8_t *) CONFIG_KERNEL_LOAD_ADDR; + image.config_dest = (uint8_t *) CONFIG_CONFIG_LOAD_ADDR; + image.is_config = 0; + + /* Copy the filenames for the DTB, kernel image, and configuration data. */ + strcpy(image.filename, CONFIG_KERNEL_FILENAME); + strcpy(image.of_filename, CONFIG_DTB_FILENAME); + strcpy(image.config_filename, CONFIG_CONFIG_FILENAME); + + /* Initialize the SD host controller. */ + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + goto _shell; + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + + /* Initialize the SD card and check if initialization is successful. */ + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: init failed\n"); + goto _shell; + } + + /* Load the DTB, kernel image, and configuration data from the SD card. */ + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: loading failed\n"); + goto _shell; + } + + /* Update boot arguments based on configuration file. */ + if (update_bootargs_from_config(dram_size)) { + goto _shell; + } + + int bootdelay = CONFIG_DEFAULT_BOOTDELAY; + + if (image.is_config) { + size_t size_a = strlen(image.config_dest); + int entry_count = parse_ini_data(image.config_dest, size_a, entries, CONFIG_MAX_ENTRY); + for (int i = 0; i < entry_count; ++i) { + /* Print parsed INI entries */ + printk(LOG_LEVEL_DEBUG, "INI: [%s] %s = %s\n", entries[i].section, entries[i].key, entries[i].value); + } + char *bootdelay_str = find_entry_value(entries, entry_count, "configs", "bootdelay"); + if (bootdelay_str != NULL) { + bootdelay = simple_atoi(bootdelay_str); + } + } + + /* Showing boot delays */ + if (abortboot_single_key(bootdelay)) { + goto _shell; + } + + cmd_boot(0, NULL); + +_shell: + syterkit_shell_attach(commands); + +_fel: + /* If the kernel boot fails, jump to FEL mode. */ + jmp_to_fel(); + + /* Return 0 to indicate successful execution. */ + return 0; +} diff --git a/board/yuzukilizard/syter_boot_spi/CMakeLists.txt b/board/yuzukilizard/syter_boot_spi/CMakeLists.txt new file mode 100644 index 00000000..7ea44abd --- /dev/null +++ b/board/yuzukilizard/syter_boot_spi/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(syter_boot_spi + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/syter_boot_spi/main.c b/board/yuzukilizard/syter_boot_spi/main.c new file mode 100644 index 00000000..be53047a --- /dev/null +++ b/board/yuzukilizard/syter_boot_spi/main.c @@ -0,0 +1,336 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" +#include "sys-dma.h" +#include "sys-spi-nand.h" + +#include "libfdt.h" +#include "ff.h" + +#define CONFIG_KERNEL_FILENAME "zImage" +#define CONFIG_DTB_FILENAME "sunxi.dtb" + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +#define CONFIG_DTB_LOAD_ADDR (0x41008000) +#define CONFIG_KERNEL_LOAD_ADDR (0x41800000) + +// 128KB erase sectors, so place them starting from 2nd sector +#define CONFIG_SPINAND_DTB_ADDR (128 * 2048) +#define CONFIG_SPINAND_KERNEL_ADDR (256 * 2048) + +#define FILENAME_MAX_LEN 64 +typedef struct { + unsigned int offset; + unsigned int length; + unsigned char *dest; + + unsigned int of_offset; + unsigned char *of_dest; + + char filename[FILENAME_MAX_LEN]; + char of_filename[FILENAME_MAX_LEN]; +} image_info_t; + +/* Linux zImage Header */ +#define LINUX_ZIMAGE_MAGIC 0x016f2818 +typedef struct { + unsigned int code[9]; + unsigned int magic; + unsigned int start; + unsigned int end; +} linux_zimage_header_t; + +extern sunxi_serial_t uart_dbg; + +extern dram_para_t dram_para; + +extern sunxi_spi_t sunxi_spi0; + +extern sdhci_t sdhci0; + +image_info_t image; + +unsigned int code[9]; +unsigned int magic; +unsigned int start; +unsigned int end; + +static int boot_image_setup(unsigned char *addr, unsigned int *entry) { + linux_zimage_header_t *zimage_header = (linux_zimage_header_t *) addr; + + printk(LOG_LEVEL_INFO, "Linux zImage->code = 0x"); + for (int i = 0; i < 9; i++) + printk(LOG_LEVEL_MUTE, "%x", code[i]); + + printk(LOG_LEVEL_MUTE, "\n"); + printk(LOG_LEVEL_DEBUG, "Linux zImage->magic = 0x%x\n", + zimage_header->magic); + printk(LOG_LEVEL_DEBUG, "Linux zImage->start = 0x%x\n", + (unsigned int) addr + zimage_header->start); + printk(LOG_LEVEL_DEBUG, "Linux zImage->end = 0x%x\n", + (unsigned int) addr + zimage_header->end); + + if (zimage_header->magic == LINUX_ZIMAGE_MAGIC) { + *entry = ((unsigned int) addr + zimage_header->start); + return 0; + } + + printk(LOG_LEVEL_ERROR, "unsupported kernel image\n"); + + return -1; +} + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, + "FATFS: open, filename: [%s]: error %d\n", filename, + fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, + CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->of_filename, + (unsigned int) image->of_dest); + ret = fatfs_loadimage(image->of_filename, image->of_dest); + if (ret) + return ret; + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, + (unsigned int) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + +int load_spi_nand(sunxi_spi_t *spi, image_info_t *image) { + linux_zimage_header_t *hdr; + unsigned int size; + uint64_t start, time; + + if (spi_nand_detect(spi) != 0) + return -1; + + /* get dtb size and read */ + spi_nand_read(spi, image->of_dest, CONFIG_SPINAND_DTB_ADDR, (uint32_t) sizeof(struct fdt_header)); + if (fdt_check_header(image->of_dest)) { + printk(LOG_LEVEL_ERROR, "SPI-NAND: DTB verification failed\n"); + return -1; + } + + size = fdt_totalsize(image->of_dest); + printk(LOG_LEVEL_DEBUG, + "SPI-NAND: dt blob: Copy from 0x%08x to 0x%08lx size:0x%08x\n", + CONFIG_SPINAND_DTB_ADDR, (uint32_t) image->of_dest, size); + start = time_us(); + spi_nand_read(spi, image->of_dest, CONFIG_SPINAND_DTB_ADDR, + (uint32_t) size); + time = time_us() - start; + printk(LOG_LEVEL_INFO, + "SPI-NAND: read dt blob of size %u at %.2fMB/S\n", size, + (f32) (size / time)); + + /* get kernel size and read */ + spi_nand_read(spi, image->dest, CONFIG_SPINAND_KERNEL_ADDR, + (uint32_t) sizeof(linux_zimage_header_t)); + hdr = (linux_zimage_header_t *) image->dest; + if (hdr->magic != LINUX_ZIMAGE_MAGIC) { + printk(LOG_LEVEL_DEBUG, + "SPI-NAND: zImage verification failed\n"); + return -1; + } + size = hdr->end - hdr->start; + printk(LOG_LEVEL_DEBUG, + "SPI-NAND: Image: Copy from 0x%08x to 0x%08lx size:0x%08x\n", + CONFIG_SPINAND_KERNEL_ADDR, (uint32_t) image->dest, size); + start = time_us(); + spi_nand_read(spi, image->dest, CONFIG_SPINAND_KERNEL_ADDR, + (uint32_t) size); + time = time_us() - start; + printk(LOG_LEVEL_INFO, + "SPI-NAND: read Image of size %u at %.2fMB/S\n", size, + (f32) (size / time)); + + return 0; +} + + + +int main(void) { + sunxi_serial_init(&uart_dbg); + + show_banner(); + + sunxi_clk_init(); + + sunxi_dram_init(&dram_para); + + unsigned int entry_point = 0; + void (*kernel_entry)(int zero, int arch, unsigned int params); + + sunxi_clk_dump(); + + memset(&image, 0, sizeof(image_info_t)); + + image.of_dest = (uint8_t *) CONFIG_DTB_LOAD_ADDR; + image.dest = (uint8_t *) CONFIG_KERNEL_LOAD_ADDR; + + strcpy(image.filename, CONFIG_KERNEL_FILENAME); + strcpy(image.of_filename, CONFIG_DTB_FILENAME); + + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", + sdhci0.name); + } else { + printk(LOG_LEVEL_INFO, + "SMHC: %s controller v%x initialized\n", sdhci0.name, + sdhci0.reg->vers); + } + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: init failed, trying SPI\n"); + goto _spi; + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_WARNING, + "SMHC: loading failed, trying SPI\n"); + } else { + goto _boot; + } + +_spi: + dma_init(); + dma_test((uint32_t *) CONFIG_DTB_LOAD_ADDR, + (uint32_t *) CONFIG_KERNEL_LOAD_ADDR); + printk(LOG_LEVEL_DEBUG, "SPI: init\n"); + if (sunxi_spi_init(&sunxi_spi0) != 0) { + printk(LOG_LEVEL_ERROR, "SPI: init failed\n"); + } + + if (load_spi_nand(&sunxi_spi0, &image) != 0) { + printk(LOG_LEVEL_ERROR, "SPI-NAND: loading failed\n"); + } + + sunxi_spi_disable(&sunxi_spi0); + dma_exit(); + +_boot: + if (boot_image_setup((unsigned char *) image.dest, &entry_point)) { + printk(LOG_LEVEL_ERROR, "boot setup failed\n"); + abort(); + } + + printk(LOG_LEVEL_INFO, "booting linux...\n"); + + arm32_mmu_disable(); + printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); + arm32_dcache_disable(); + printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); + arm32_icache_disable(); + printk(LOG_LEVEL_INFO, "disable icache ok...\n"); + arm32_interrupt_disable(); + printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); + enable_kernel_smp(); + printk(LOG_LEVEL_INFO, "enable kernel smp ok...\n"); + + printk(LOG_LEVEL_INFO, "jump to kernel address: 0x%x\n\n", image.dest); + + kernel_entry = (void (*)(int, int, unsigned int)) entry_point; + kernel_entry(0, ~0, (unsigned int) image.of_dest); + + // if kernel boot not success, jump to fel. + jmp_to_fel(); + + return 0; +} diff --git a/board/yuzukilizard/syter_bootargs/CMakeLists.txt b/board/yuzukilizard/syter_bootargs/CMakeLists.txt new file mode 100644 index 00000000..ea16d422 --- /dev/null +++ b/board/yuzukilizard/syter_bootargs/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_syterkit_app(syter_bootargs + main.c +) \ No newline at end of file diff --git a/board/yuzukilizard/syter_bootargs/main.c b/board/yuzukilizard/syter_bootargs/main.c new file mode 100644 index 00000000..d151c003 --- /dev/null +++ b/board/yuzukilizard/syter_bootargs/main.c @@ -0,0 +1,420 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "sys-dram.h" +#include "sys-sdcard.h" +#include "sys-sid.h" +#include "sys-spi.h" + +#include +#include +#include + +#include "ff.h" +#include "libfdt.h" + +#define CONFIG_KERNEL_FILENAME "zImage" +#define CONFIG_DTB_FILENAME "sunxi.dtb" + +#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) + +#define CONFIG_DTB_LOAD_ADDR (0x41008000) +#define CONFIG_KERNEL_LOAD_ADDR (0x41800000) + +// 128KB erase sectors, so place them starting from 2nd sector +#define CONFIG_SPINAND_DTB_ADDR (128 * 2048) +#define CONFIG_SPINAND_KERNEL_ADDR (256 * 2048) + +#define FILENAME_MAX_LEN 64 +typedef struct { + unsigned int offset; + unsigned int length; + unsigned char *dest; + + unsigned int of_offset; + unsigned char *of_dest; + + char filename[FILENAME_MAX_LEN]; + char of_filename[FILENAME_MAX_LEN]; +} image_info_t; + +/* Linux zImage Header */ +#define LINUX_ZIMAGE_MAGIC 0x016f2818 +typedef struct { + unsigned int code[9]; + unsigned int magic; + unsigned int start; + unsigned int end; +} linux_zimage_header_t; + +extern sunxi_serial_t uart_dbg; + +extern sunxi_spi_t sunxi_spi0; + +extern sdhci_t sdhci0; + +extern dram_para_t dram_para; + +image_info_t image; + +unsigned int code[9]; +unsigned int magic; +unsigned int start; +unsigned int end; + +static int boot_image_setup(unsigned char *addr, unsigned int *entry) { + linux_zimage_header_t *zimage_header = (linux_zimage_header_t *) addr; + + printk(LOG_LEVEL_INFO, "Linux zImage->code = 0x"); + for (int i = 0; i < 9; i++) + printk(LOG_LEVEL_MUTE, "%x", code[i]); + + printk(LOG_LEVEL_MUTE, "\n"); + printk(LOG_LEVEL_DEBUG, "Linux zImage->magic = 0x%x\n", + zimage_header->magic); + printk(LOG_LEVEL_DEBUG, "Linux zImage->start = 0x%x\n", + (unsigned int) addr + zimage_header->start); + printk(LOG_LEVEL_DEBUG, "Linux zImage->end = 0x%x\n", + (unsigned int) addr + zimage_header->end); + + if (zimage_header->magic == LINUX_ZIMAGE_MAGIC) { + *entry = ((unsigned int) addr + zimage_header->start); + return 0; + } + + printk(LOG_LEVEL_ERROR, "unsupported kernel image\n"); + + return -1; +} + +#define CHUNK_SIZE 0x20000 + +static int fatfs_loadimage(char *filename, BYTE *dest) { + FIL file; + UINT byte_to_read = CHUNK_SIZE; + UINT byte_read; + UINT total_read = 0; + FRESULT fret; + int ret; + uint32_t start, time; + + fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, + "FATFS: open, filename: [%s]: error %d\n", filename, + fret); + ret = -1; + goto open_fail; + } + + start = time_ms(); + + do { + byte_read = 0; + fret = f_read(&file, (void *) (dest), byte_to_read, &byte_read); + dest += byte_to_read; + total_read += byte_read; + } while (byte_read >= byte_to_read && fret == FR_OK); + + time = time_ms() - start + 1; + + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\n", fret); + ret = -1; + goto read_fail; + } + ret = 0; + +read_fail: + fret = f_close(&file); + + printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\n", time, + (f32) (total_read / time) / 1024.0f); + +open_fail: + return ret; +} + +static int load_sdcard(image_info_t *image) { + FATFS fs; + FRESULT fret; + int ret; + uint32_t start; + + uint32_t test_time; + start = time_ms(); + sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, + CONFIG_SDMMC_SPEED_TEST_SIZE); + test_time = time_ms() - start; + printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + start = time_ms(); + + fret = f_mount(&fs, "", 1); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\n"); + } + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->of_filename, + (unsigned int) image->of_dest); + ret = fatfs_loadimage(image->of_filename, image->of_dest); + if (ret) + return ret; + + printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\n", image->filename, + (unsigned int) image->dest); + ret = fatfs_loadimage(image->filename, image->dest); + if (ret) + return ret; + + /* umount fs */ + fret = f_mount(0, "", 0); + if (fret != FR_OK) { + printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\n", fret); + return -1; + } else { + printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\n"); + } + printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\n", time_ms() - start); + + return 0; +} + +int load_spi_nand(sunxi_spi_t *spi, image_info_t *image) { + linux_zimage_header_t *hdr; + unsigned int size; + uint64_t start, time; + + if (spi_nand_detect(spi) != 0) + return -1; + + /* get dtb size and read */ + spi_nand_read(spi, image->of_dest, CONFIG_SPINAND_DTB_ADDR, (uint32_t) sizeof(struct fdt_header)); + if (fdt_check_header(image->of_dest)) { + printk(LOG_LEVEL_ERROR, "SPI-NAND: DTB verification failed\n"); + return -1; + } + + size = fdt_totalsize(image->of_dest); + printk(LOG_LEVEL_DEBUG, + "SPI-NAND: dt blob: Copy from 0x%08x to 0x%08lx size:0x%08x\n", + CONFIG_SPINAND_DTB_ADDR, (uint32_t) image->of_dest, size); + start = time_us(); + spi_nand_read(spi, image->of_dest, CONFIG_SPINAND_DTB_ADDR, + (uint32_t) size); + time = time_us() - start; + printk(LOG_LEVEL_INFO, + "SPI-NAND: read dt blob of size %u at %.2fMB/S\n", size, + (f32) (size / time)); + + /* get kernel size and read */ + spi_nand_read(spi, image->dest, CONFIG_SPINAND_KERNEL_ADDR, + (uint32_t) sizeof(linux_zimage_header_t)); + hdr = (linux_zimage_header_t *) image->dest; + if (hdr->magic != LINUX_ZIMAGE_MAGIC) { + printk(LOG_LEVEL_DEBUG, + "SPI-NAND: zImage verification failed\n"); + return -1; + } + size = hdr->end - hdr->start; + printk(LOG_LEVEL_DEBUG, + "SPI-NAND: Image: Copy from 0x%08x to 0x%08lx size:0x%08x\n", + CONFIG_SPINAND_KERNEL_ADDR, (uint32_t) image->dest, size); + start = time_us(); + spi_nand_read(spi, image->dest, CONFIG_SPINAND_KERNEL_ADDR, + (uint32_t) size); + time = time_us() - start; + printk(LOG_LEVEL_INFO, + "SPI-NAND: read Image of size %u at %.2fMB/S\n", size, + (f32) (size / time)); + + return 0; +} + +msh_declare_command(bootargs); +msh_define_help(bootargs, "get/set bootargs for kernel", + "Usage: bootargs set \"bootargs\" - set new bootargs for zImage\n" + " bootargs get - get current bootargs\n"); +int cmd_bootargs(int argc, const char **argv) { + if (argc < 2) { + uart_puts(cmd_bootargs_usage); + return 0; + } + + if (strncmp(argv[1], "set", 3) == 0) { + if (argc != 3) { + uart_puts(cmd_bootargs_usage); + return 0; + } + /* Force image.of_dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + int err = 0; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + return 0; + } + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB OLD bootargs = \"%s\"\n", bootargs_str); + + /* New bootargs string */ + char *new_bootargs_str = argv[2]; + printk(LOG_LEVEL_MUTE, "Now set bootargs to \"%s\"\n", new_bootargs_str); + + /* Modify bootargs string */ + err = fdt_setprop(image.of_dest, bootargs_node, "bootargs", new_bootargs_str, strlen(new_bootargs_str) + 1); + + if (err < 0) { + printk(LOG_LEVEL_ERROR, "libfdt fdt_setprop() error: %s\n", fdt_strerror(err)); + abort(); + } + + /* Get updated bootargs string */ + char *updated_bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB NEW bootargs = \"%s\"\n", updated_bootargs_str); + } else if (strncmp(argv[1], "get", 3) == 0) { + /* Force image.of_dest to be a pointer to fdt_header structure */ + struct fdt_header *dtb_header = (struct fdt_header *) image.of_dest; + + int err = 0; + + /* Check if DTB header is valid */ + if ((err = fdt_check_header(dtb_header)) != 0) { + printk(LOG_LEVEL_ERROR, "Invalid device tree blob: %s\n", fdt_strerror(err)); + return 0; + } + + int len = 0; + /* Get the offset of "/chosen" node */ + uint32_t bootargs_node = fdt_path_offset(image.of_dest, "/chosen"); + + /* Get bootargs string */ + char *bootargs_str = (void *) fdt_getprop(image.of_dest, bootargs_node, "bootargs", &len); + printk(LOG_LEVEL_MUTE, "DTB bootargs = \"%s\"\n", bootargs_str); + } else { + uart_puts(cmd_bootargs_usage); + } + + return 0; +} + +msh_declare_command(reload); +msh_define_help(reload, "rescan TF Card and reload DTB, Kernel zImage", "Usage: reload\n"); +int cmd_reload(int argc, const char **argv) { + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: init failed\n"); + return 0; + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: loading failed\n"); + return 0; + } + return 0; +} + +msh_declare_command(boot); +msh_define_help(boot, "boot to linux", "Usage: boot\n"); +int cmd_boot(int argc, const char **argv) { + unsigned int entry_point = 0; + void (*kernel_entry)(int zero, int arch, unsigned int params); + + if (boot_image_setup((unsigned char *) image.dest, &entry_point)) { + printk(LOG_LEVEL_ERROR, "boot setup failed\n"); + return 0; + } + + printk(LOG_LEVEL_INFO, "booting linux...\n"); + + arm32_mmu_disable(); + printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); + arm32_dcache_disable(); + printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); + arm32_icache_disable(); + printk(LOG_LEVEL_INFO, "disable icache ok...\n"); + arm32_interrupt_disable(); + printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); + enable_kernel_smp(); + printk(LOG_LEVEL_INFO, "enable kernel smp ok...\n"); + + printk(LOG_LEVEL_INFO, "jump to kernel address: 0x%x\n", image.dest); + + kernel_entry = (void (*)(int, int, unsigned int)) entry_point; + kernel_entry(0, ~0, (unsigned int) image.of_dest); + + // if kernel boot not success, jump to fel. + jmp_to_fel(); + return 0; +} + +const msh_command_entry commands[] = { + msh_define_command(bootargs), + msh_define_command(reload), + msh_define_command(boot), + msh_command_end, +}; + +int main(void) { + sunxi_serial_init(&uart_dbg); + + show_banner(); + + sunxi_clk_init(); + + sunxi_dram_init(&dram_para); + + sunxi_clk_dump(); + + memset(&image, 0, sizeof(image_info_t)); + + image.of_dest = (uint8_t *) CONFIG_DTB_LOAD_ADDR; + image.dest = (uint8_t *) CONFIG_KERNEL_LOAD_ADDR; + + strcpy(image.filename, CONFIG_KERNEL_FILENAME); + strcpy(image.of_filename, CONFIG_DTB_FILENAME); + + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\n", sdhci0.name); + goto _shell; + } else { + printk(LOG_LEVEL_INFO, "SMHC: %s controller v%x initialized\n", sdhci0.name, sdhci0.reg->vers); + } + if (sdmmc_init(&card0, &sdhci0) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: init failed\n"); + goto _shell; + } + + if (load_sdcard(&image) != 0) { + printk(LOG_LEVEL_WARNING, "SMHC: loading failed\n"); + goto _shell; + } + +_shell: + syterkit_shell_attach(commands); + + return 0; +} diff --git a/cmake/add_syterkit_app.cmake b/cmake/add_syterkit_app.cmake index aa82f026..76cf8a49 100644 --- a/cmake/add_syterkit_app.cmake +++ b/cmake/add_syterkit_app.cmake @@ -1,10 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 -set(APP_COMMON_SOURCE - ${PROJECT_SOURCE_DIR}/app/common/start.S - ${PROJECT_SOURCE_DIR}/app/common/eabi_compat.c -) - +# List of common libraries used by the application set(APP_COMMON_LIBRARY fatfs fdt @@ -13,12 +9,16 @@ set(APP_COMMON_LIBRARY gcc ) +# Function to add a new SyterKit application function(add_syterkit_app target_name) + # Add an executable for the target_name with _fel suffix add_executable(${target_name}_fel ${APP_COMMON_SOURCE} ${ARGN}) + # Set properties for the target, including link dependencies and libraries set_target_properties(${target_name}_fel PROPERTIES LINK_DEPENDS "${LINK_SCRIPT_FEL}") target_link_libraries(${target_name}_fel ${APP_COMMON_LIBRARY} -T"${LINK_SCRIPT_FEL}" -nostdlib -Wl,-z,noexecstack,-Map,${target_name}_fel.map) + # Add custom commands for post-build actions add_custom_command( TARGET ${target_name}_fel POST_BUILD COMMAND ${CMAKE_SIZE} -B -x ${target_name}_fel @@ -31,6 +31,7 @@ function(add_syterkit_app target_name) COMMENT "Copy Binary ${target_name}_fel" ) + # Repeat the above steps for the _bin version of the target add_executable(${target_name}_bin ${APP_COMMON_SOURCE} ${ARGN}) set_target_properties(${target_name}_bin PROPERTIES LINK_DEPENDS "${LINK_SCRIPT_BIN}") @@ -65,4 +66,4 @@ function(add_syterkit_app target_name) POST_BUILD COMMAND ${CMAKE_MKSUNXI} ${target_name}_bin_spi.bin 8192 COMMENT "Padding MTD 8192 Binary" ) -endfunction() \ No newline at end of file +endfunction() diff --git a/cmake/board/100ask-t113i.cmake b/cmake/board/100ask-t113i.cmake new file mode 100644 index 00000000..6373f963 --- /dev/null +++ b/cmake/board/100ask-t113i.cmake @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CONFIG_ARCH_ARM32 True) +set(CONFIG_CHIP_SUN8IW20 True) +set(CONFIG_BOARD_100ASK-T113I True) + +add_definitions(-DCONFIG_CHIP_SUN8IW20) + +# Options + +# By setting ENABLE_HARDFP to ON, it indicates that the project is configured +# to utilize hard floating-point operations when applicable. This can be beneficial +# in scenarios where performance gains from hardware acceleration are desired. +option(ENABLE_HARDFP "Enable hardware floating-point operations" ON) + +# Set the cross-compile toolchain +set(CROSS_COMPILE "arm-none-eabi-") +set(CROSS_COMPILE ${CROSS_COMPILE} CACHE STRING "CROSS_COMPILE Toolchain") + +# Set the C and C++ compilers +set(CMAKE_C_COMPILER "${CROSS_COMPILE}gcc") +set(CMAKE_CXX_COMPILER "${CROSS_COMPILE}g++") + +# Configure compiler flags based on ENABLE_HARDFP option +if(ENABLE_HARDFP) + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=hard") +else() + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=softfp") +endif() + +# Disable specific warning flags for C and C++ compilers +set(CMAKE_C_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers") +set(CMAKE_CXX_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast") + +set(ARCH_BIN_START_ADDRESS "0x00020000") +set(ARCH_BIN_SRAM_LENGTH "128K") + +set(ARCH_FEL_START_ADDRESS "0x00028000") +set(ARCH_FEL_SRAM_LENGTH "100K") \ No newline at end of file diff --git a/cmake/board/100ask-t113s3.cmake b/cmake/board/100ask-t113s3.cmake new file mode 100644 index 00000000..cf048122 --- /dev/null +++ b/cmake/board/100ask-t113s3.cmake @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CONFIG_ARCH_ARM32 True) +set(CONFIG_CHIP_SUN8IW20 True) +set(CONFIG_BOARD_100ASK-T113S3 True) + +add_definitions(-DCONFIG_CHIP_SUN8IW20) + +# Options + +# By setting ENABLE_HARDFP to ON, it indicates that the project is configured +# to utilize hard floating-point operations when applicable. This can be beneficial +# in scenarios where performance gains from hardware acceleration are desired. +option(ENABLE_HARDFP "Enable hardware floating-point operations" ON) + +# Set the cross-compile toolchain +set(CROSS_COMPILE "arm-none-eabi-") +set(CROSS_COMPILE ${CROSS_COMPILE} CACHE STRING "CROSS_COMPILE Toolchain") + +# Set the C and C++ compilers +set(CMAKE_C_COMPILER "${CROSS_COMPILE}gcc") +set(CMAKE_CXX_COMPILER "${CROSS_COMPILE}g++") + +# Configure compiler flags based on ENABLE_HARDFP option +if(ENABLE_HARDFP) + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=hard") +else() + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=softfp") +endif() + +# Disable specific warning flags for C and C++ compilers +set(CMAKE_C_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers") +set(CMAKE_CXX_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast") + +set(ARCH_BIN_START_ADDRESS "0x00020000") +set(ARCH_BIN_SRAM_LENGTH "128K") + +set(ARCH_FEL_START_ADDRESS "0x00028000") +set(ARCH_FEL_SRAM_LENGTH "100K") \ No newline at end of file diff --git a/cmake/board/tinyvision.cmake b/cmake/board/tinyvision.cmake new file mode 100644 index 00000000..ea934128 --- /dev/null +++ b/cmake/board/tinyvision.cmake @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CONFIG_ARCH_ARM32 True) +set(CONFIG_CHIP_SUN8IW21 True) +set(CONFIG_BOARD_TINYVISION True) + +add_definitions(-DCONFIG_CHIP_SUN8IW21) + +# Options + +# By setting ENABLE_HARDFP to ON, it indicates that the project is configured +# to utilize hard floating-point operations when applicable. This can be beneficial +# in scenarios where performance gains from hardware acceleration are desired. +option(ENABLE_HARDFP "Enable hardware floating-point operations" ON) + +# Set the cross-compile toolchain +set(CROSS_COMPILE "arm-none-eabi-") +set(CROSS_COMPILE ${CROSS_COMPILE} CACHE STRING "CROSS_COMPILE Toolchain") + +# Set the C and C++ compilers +set(CMAKE_C_COMPILER "${CROSS_COMPILE}gcc") +set(CMAKE_CXX_COMPILER "${CROSS_COMPILE}g++") + +# Configure compiler flags based on ENABLE_HARDFP option +if(ENABLE_HARDFP) + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=hard") +else() + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=softfp") +endif() + +# Disable specific warning flags for C and C++ compilers +set(CMAKE_C_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers") +set(CMAKE_CXX_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast") + +set(ARCH_BIN_START_ADDRESS "0x00020000") +set(ARCH_BIN_SRAM_LENGTH "128K") + +set(ARCH_FEL_START_ADDRESS "0x00028000") +set(ARCH_FEL_SRAM_LENGTH "100K") \ No newline at end of file diff --git a/cmake/board/yuzukilizard.cmake b/cmake/board/yuzukilizard.cmake new file mode 100644 index 00000000..ac6a43a3 --- /dev/null +++ b/cmake/board/yuzukilizard.cmake @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CONFIG_ARCH_ARM32 True) +set(CONFIG_CHIP_SUN8IW21 True) +set(CONFIG_BOARD_YUZUKILIZARD True) + +add_definitions(-DCONFIG_CHIP_SUN8IW21) + +# Options + +# By setting ENABLE_HARDFP to ON, it indicates that the project is configured +# to utilize hard floating-point operations when applicable. This can be beneficial +# in scenarios where performance gains from hardware acceleration are desired. +option(ENABLE_HARDFP "Enable hardware floating-point operations" ON) + +# Set the cross-compile toolchain +set(CROSS_COMPILE "arm-none-eabi-") +set(CROSS_COMPILE ${CROSS_COMPILE} CACHE STRING "CROSS_COMPILE Toolchain") + +# Set the C and C++ compilers +set(CMAKE_C_COMPILER "${CROSS_COMPILE}gcc") +set(CMAKE_CXX_COMPILER "${CROSS_COMPILE}g++") + +# Configure compiler flags based on ENABLE_HARDFP option +if(ENABLE_HARDFP) + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=hard") +else() + set(CMAKE_COMMON_FLAGS "-nostdlib -g -ggdb -O3 -mcpu=cortex-a7 -mthumb-interwork -mthumb -mno-unaligned-access -mfpu=neon-vfpv4 -mfloat-abi=softfp") +endif() + +# Disable specific warning flags for C and C++ compilers +set(CMAKE_C_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers") +set(CMAKE_CXX_DISABLE_WARN_FLAGS "-Wno-int-to-pointer-cast") + +set(ARCH_BIN_START_ADDRESS "0x00020000") +set(ARCH_BIN_SRAM_LENGTH "128K") + +set(ARCH_FEL_START_ADDRESS "0x00028000") +set(ARCH_FEL_SRAM_LENGTH "100K") \ No newline at end of file diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 7a871b23..00000000 --- a/docs/README.md +++ /dev/null @@ -1,6 +0,0 @@ -

SyterKit

-

SyterKit - A bare-metal framework

- -# SyterKit 简介 - -SyterKit 是一个纯裸机 diff --git a/docs/_navbar.md b/docs/_navbar.md deleted file mode 100644 index 1652c17e..00000000 --- a/docs/_navbar.md +++ /dev/null @@ -1,2 +0,0 @@ -* [HOME](/) -* [SupportList](/SupportList) \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 44948f88..00000000 --- a/docs/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - TinyVision 在线文档 - - - - - - - - - -
- - - - - - - - - - - \ No newline at end of file diff --git a/include/arch/barrier.h b/include/arch/arm32/barrier.h similarity index 100% rename from include/arch/barrier.h rename to include/arch/arm32/barrier.h diff --git a/include/io.h b/include/arch/arm32/io.h similarity index 53% rename from include/io.h rename to include/arch/arm32/io.h index a0464aaf..0eea9113 100644 --- a/include/io.h +++ b/include/arch/arm32/io.h @@ -15,43 +15,35 @@ typedef uint32_t virtual_addr_t; -static inline __attribute__((__always_inline__)) uint8_t -read8(virtual_addr_t addr) { +static inline __attribute__((__always_inline__)) uint8_t read8(virtual_addr_t addr) { return (*((volatile uint8_t *) (addr))); } -static inline __attribute__((__always_inline__)) uint16_t -read16(virtual_addr_t addr) { +static inline __attribute__((__always_inline__)) uint16_t read16(virtual_addr_t addr) { return (*((volatile uint16_t *) (addr))); } -static inline __attribute__((__always_inline__)) uint32_t -read32(virtual_addr_t addr) { +static inline __attribute__((__always_inline__)) uint32_t read32(virtual_addr_t addr) { return (*((volatile uint32_t *) (addr))); } -static inline __attribute__((__always_inline__)) uint64_t -read64(virtual_addr_t addr) { +static inline __attribute__((__always_inline__)) uint64_t read64(virtual_addr_t addr) { return (*((volatile uint64_t *) (addr))); } -static inline __attribute__((__always_inline__)) void -write8(virtual_addr_t addr, uint8_t value) { +static inline __attribute__((__always_inline__)) void write8(virtual_addr_t addr, uint8_t value) { *((volatile uint8_t *) (addr)) = value; } -static inline __attribute__((__always_inline__)) void -write16(virtual_addr_t addr, uint16_t value) { +static inline __attribute__((__always_inline__)) void write16(virtual_addr_t addr, uint16_t value) { *((volatile uint16_t *) (addr)) = value; } -static inline __attribute__((__always_inline__)) void -write32(virtual_addr_t addr, uint32_t value) { +static inline __attribute__((__always_inline__)) void write32(virtual_addr_t addr, uint32_t value) { *((volatile uint32_t *) (addr)) = value; } -static inline __attribute__((__always_inline__)) void -write64(virtual_addr_t addr, uint64_t value) { +static inline __attribute__((__always_inline__)) void write64(virtual_addr_t addr, uint64_t value) { *((volatile uint64_t *) (addr)) = value; } diff --git a/src/jmp.c b/include/arch/arm32/jmp.h similarity index 84% rename from src/jmp.c rename to include/arch/arm32/jmp.h index 5190ba61..8451e6d1 100644 --- a/src/jmp.c +++ b/include/arch/arm32/jmp.h @@ -1,14 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include - -#include -#include - -#include +#ifndef _JMP_H_ +#define _JMP_H_ /* * The code reads the value from the ACTLR register, @@ -16,7 +9,7 @@ * value back to the ACTLR register using coprocessor * 15 (CP15) and its control register (CR). */ -void enable_kernel_smp(void) { +inline void enable_kernel_smp(void) { // Read ACTLR from coprocessor 15 (CP15), register c1 asm volatile("MRC p15, 0, r0, c1, c0, 1"); // Perform bitwise OR operation on register r0 with 0x040, @@ -27,7 +20,7 @@ void enable_kernel_smp(void) { asm volatile("MCR p15, 0, r0, c1, c0, 1"); } -void syterkit_jmp(uint32_t addr) { +inline void syterkit_jmp(uint32_t addr) { // Move the constant value 0 into register r2 asm volatile("mov r2, #0"); @@ -42,12 +35,15 @@ void syterkit_jmp(uint32_t addr) { asm volatile("bx r0"); } -void jmp_to_fel() { +inline void jmp_to_fel() { syterkit_jmp(0x20); } -void syterkit_jmp_kernel(uint32_t addr, uint32_t fdt) { +inline void syterkit_jmp_kernel(uint32_t addr, uint32_t fdt) { void (*kernel_entry)(int zero, int arch, unsigned int params); kernel_entry = (void (*)(int, int, unsigned int)) addr; kernel_entry(0, ~0, (unsigned int) fdt); } + + +#endif// _JMP_H_ \ No newline at end of file diff --git a/include/arch/linkage.h b/include/arch/arm32/linkage.h similarity index 100% rename from include/arch/linkage.h rename to include/arch/arm32/linkage.h diff --git a/include/arch/arm32.h b/include/arch/arm32/mmu.h similarity index 96% rename from include/arch/arm32.h rename to include/arch/arm32/mmu.h index 607b7db6..e13a6bfb 100644 --- a/include/arch/arm32.h +++ b/include/arch/arm32/mmu.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#ifndef __ARM32_H__ -#define __ARM32_H__ +#ifndef __MMU_H__ +#define __MMU_H__ #ifdef __cplusplus extern "C" { @@ -9,7 +9,7 @@ extern "C" { #include -#include "sys-timer.h" +#include "timer.h" static inline uint32_t arm32_read_p15_c1(void) { uint32_t value; @@ -166,8 +166,13 @@ static inline void arm32_icache_disable(void) { arm32_write_p15_c1(value & ~(1 << 12)); } +inline void data_sync_barrier(void) { + asm volatile("DSB"); + asm volatile("ISB"); +} + #ifdef __cplusplus } #endif -#endif /* __ARM32_H__ */ +#endif /* __MMU_H__ */ diff --git a/include/drivers/sys-timer.h b/include/arch/arm32/timer.h similarity index 100% rename from include/drivers/sys-timer.h rename to include/arch/arm32/timer.h diff --git a/include/types.h b/include/arch/arm32/types.h similarity index 100% rename from include/types.h rename to include/arch/arm32/types.h diff --git a/include/arch/atomic.h b/include/arch/atomic.h deleted file mode 100644 index 0bc6b511..00000000 --- a/include/arch/atomic.h +++ /dev/null @@ -1,155 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#ifndef __ARM32_ATOMIC_H__ -#define __ARM32_ATOMIC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#if (__ARM32_ARCH__ >= 6) -static inline void atomic_add(atomic_t *a, int v) { - unsigned int tmp; - int result; - - __asm__ __volatile__("1: ldrex %0, [%3]\n" - " add %0, %0, %4\n" - " strex %1, %0, [%3]\n" - " teq %1, #0\n" - " bne 1b" - : "=&r"(result), "=&r"(tmp), "+Qo"(a->counter) - : "r"(&a->counter), "Ir"(v) - : "cc"); -} - -static inline int atomic_add_return(atomic_t *a, int v) { - unsigned int tmp; - int result; - - __asm__ __volatile__("1: ldrex %0, [%3]\n" - " add %0, %0, %4\n" - " strex %1, %0, [%3]\n" - " teq %1, #0\n" - " bne 1b" - : "=&r"(result), "=&r"(tmp), "+Qo"(a->counter) - : "r"(&a->counter), "Ir"(v) - : "cc"); - - return result; -} - -static inline void atomic_sub(atomic_t *a, int v) { - unsigned int tmp; - int result; - - __asm__ __volatile__("1: ldrex %0, [%3]\n" - " sub %0, %0, %4\n" - " strex %1, %0, [%3]\n" - " teq %1, #0\n" - " bne 1b" - : "=&r"(result), "=&r"(tmp), "+Qo"(a->counter) - : "r"(&a->counter), "Ir"(v) - : "cc"); -} - -static inline int atomic_sub_return(atomic_t *a, int v) { - unsigned int tmp; - int result; - - __asm__ __volatile__("1: ldrex %0, [%3]\n" - " sub %0, %0, %4\n" - " strex %1, %0, [%3]\n" - " teq %1, #0\n" - " bne 1b" - : "=&r"(result), "=&r"(tmp), "+Qo"(a->counter) - : "r"(&a->counter), "Ir"(v) - : "cc"); - - return result; -} - -static inline int atomic_cmp_exchange(atomic_t *a, int o, int n) { - int pre, res; - - do { - __asm__ __volatile__(" ldrex %1, [%3]\n" - " mov %0, #0\n" - " teq %1, %4\n" - " strexeq %0, %5, [%3]\n" - : "=&r"(res), "=&r"(pre), "+Qo"(a->counter) - : "r"(&a->counter), "Ir"(o), "r"(n) - : "cc"); - } while (res); - - return pre; -} -#else -static inline void atomic_add(atomic_t *a, int v) { - mb(); - a->counter += v; - mb(); -} - -static inline int atomic_add_return(atomic_t *a, int v) { - mb(); - a->counter += v; - mb(); - return a->counter; -} - -static inline void atomic_sub(atomic_t *a, int v) { - mb(); - a->counter -= v; - mb(); -} - -static inline int atomic_sub_return(atomic_t *a, int v) { - mb(); - a->counter -= v; - mb(); - return a->counter; -} - -static inline int atomic_cmp_exchange(atomic_t *a, int o, int n) { - volatile int v; - - mb(); - v = a->counter; - if (v == o) - a->counter = n; - mb(); - return v; -} -#endif - -#define atomic_set(a, v) \ - do { \ - ((a)->counter) = (v); \ - smp_wmb(); \ - } while (0) -#define atomic_get(a) \ - ({ \ - int __v; \ - __v = (a)->counter; \ - smp_rmb(); \ - __v; \ - }) -#define atomic_inc(a) (atomic_add(a, 1)) -#define atomic_dec(a) (atomic_sub(a, 1)) -#define atomic_inc_return(a) (atomic_add_return(a, 1)) -#define atomic_dec_return(a) (atomic_sub_return(a, 1)) -#define atomic_inc_and_test(a) (atomic_add_return(a, 1) == 0) -#define atomic_dec_and_test(a) (atomic_sub_return(a, 1) == 0) -#define atomic_add_negative(a, v) (atomic_add_return(a, v) < 0) -#define atomic_sub_and_test(a, v) (atomic_sub_return(a, v) == 0) -#define atomic_cmpxchg(a, o, n) (atomic_cmp_exchange(a, o, n)) - -#ifdef __cplusplus -} -#endif - -#endif /* __ARM32_ATOMIC_H__ */ diff --git a/include/arch/riscv64/barrier.h b/include/arch/riscv64/barrier.h new file mode 100644 index 00000000..9a44f707 --- /dev/null +++ b/include/arch/riscv64/barrier.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __RISCV64_BARRIER_H__ +#define __RISCV64_BARRIER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Read and write memory barrier */ +#define mb() __asm__ __volatile__ ("fence iorw, iorw" : : : "memory"); +/* Read memory barrier */ +#define rmb() __asm__ __volatile__ ("fence ir, ir" : : : "memory"); +/* Write memory barrier */ +#define wmb() __asm__ __volatile__ ("fence ow, ow" : : : "memory"); + +/* SMP read and write memory barrier */ +#define smp_mb() __asm__ __volatile__ ("fence rw, rw" : : : "memory"); +/* SMP read memory barrier */ +#define smp_rmb() __asm__ __volatile__ ("fence r, r" : : : "memory"); +/* SMP write memory barrier */ +#define smp_wmb() __asm__ __volatile__ ("fence w, w" : : : "memory"); + +#ifdef __cplusplus +} +#endif + +#endif /* __RISCV64_BARRIER_H__ */ \ No newline at end of file diff --git a/include/arch/riscv64/io.h b/include/arch/riscv64/io.h new file mode 100644 index 00000000..0eea9113 --- /dev/null +++ b/include/arch/riscv64/io.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __IO_H__ +#define __IO_H__ + +#include + +#define BIT(x) (1 << x) +#define clrsetbits_le32(addr, clear, set) \ + write32((addr), (read32(addr) & ~(clear)) | (set)) +#define setbits_le32(addr, set) write32((addr), read32(addr) | (set)) +#define clrbits_le32(addr, clear) write32((addr), read32(addr) & ~(clear)) +#define readl(addr) read32(addr) +#define writel(val, addr) write32((addr), (val)) + +typedef uint32_t virtual_addr_t; + +static inline __attribute__((__always_inline__)) uint8_t read8(virtual_addr_t addr) { + return (*((volatile uint8_t *) (addr))); +} + +static inline __attribute__((__always_inline__)) uint16_t read16(virtual_addr_t addr) { + return (*((volatile uint16_t *) (addr))); +} + +static inline __attribute__((__always_inline__)) uint32_t read32(virtual_addr_t addr) { + return (*((volatile uint32_t *) (addr))); +} + +static inline __attribute__((__always_inline__)) uint64_t read64(virtual_addr_t addr) { + return (*((volatile uint64_t *) (addr))); +} + +static inline __attribute__((__always_inline__)) void write8(virtual_addr_t addr, uint8_t value) { + *((volatile uint8_t *) (addr)) = value; +} + +static inline __attribute__((__always_inline__)) void write16(virtual_addr_t addr, uint16_t value) { + *((volatile uint16_t *) (addr)) = value; +} + +static inline __attribute__((__always_inline__)) void write32(virtual_addr_t addr, uint32_t value) { + *((volatile uint32_t *) (addr)) = value; +} + +static inline __attribute__((__always_inline__)) void write64(virtual_addr_t addr, uint64_t value) { + *((volatile uint64_t *) (addr)) = value; +} + +#endif \ No newline at end of file diff --git a/include/arch/riscv64/linkage.h b/include/arch/riscv64/linkage.h new file mode 100644 index 00000000..974c908b --- /dev/null +++ b/include/arch/riscv64/linkage.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __RISCV64_LINKAGE_H__ +#define __RISCV64_LINKAGE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if __riscv_xlen == 64 +#define LREG ld +#define SREG sd +#define REGSZ 8 +#define RVPTR .dword +#elif __riscv_xlen == 32 +#define LREG lw +#define SREG sw +#define REGSZ 4 +#define RVPTR .word +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __RISCV64_LINKAGE_H__ */ \ No newline at end of file diff --git a/include/arch/riscv64/timer.h b/include/arch/riscv64/timer.h new file mode 100644 index 00000000..62c1c1b7 --- /dev/null +++ b/include/arch/riscv64/timer.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SYS_TIMER_H__ +#define __SYS_TIMER_H__ + +#include +#include +#include +#include +#include +#include + +#include "log.h" + +uint64_t get_arch_counter(void); + +uint32_t time_ms(void); + +uint64_t time_us(void); + +void udelay(uint64_t us); + +void mdelay(uint32_t ms); + +void sdelay(uint32_t loops); + +#endif// __SYS_TIMER_H__ \ No newline at end of file diff --git a/include/common.h b/include/common.h index d05ce581..3f1a39e9 100644 --- a/include/common.h +++ b/include/common.h @@ -40,10 +40,4 @@ int raise(int signum); void show_banner(void); -void clean_syterkit_data(void); - -void rtc_set_vccio_det_spare(void); - -void sys_ldo_check(void); - #endif// __COMMON_H__ \ No newline at end of file diff --git a/include/reg/reg-dma.h b/include/drivers/reg/reg-dma.h similarity index 100% rename from include/reg/reg-dma.h rename to include/drivers/reg/reg-dma.h diff --git a/include/drivers/reg/reg-ncat.h b/include/drivers/reg/reg-ncat.h new file mode 100644 index 00000000..8f1612e6 --- /dev/null +++ b/include/drivers/reg/reg-ncat.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __G_REG_NCAT_H__ +#define __G_REG_NCAT_H__ + +#if defined(CONFIG_CHIP_SUN8IW21) + #include +#elif defined(CONFIG_CHIP_SUN8IW20) + #include +#else + #error "Unsupported chip" +#endif + +#endif // __G_REG_NCAT_H__ \ No newline at end of file diff --git a/include/reg/reg-smhc.h b/include/drivers/reg/reg-smhc.h similarity index 100% rename from include/reg/reg-smhc.h rename to include/drivers/reg/reg-smhc.h diff --git a/include/drivers/sun8iw20/reg/reg-ccu.h b/include/drivers/sun8iw20/reg/reg-ccu.h new file mode 100644 index 00000000..7ec00b9e --- /dev/null +++ b/include/drivers/sun8iw20/reg/reg-ccu.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW20_REG_CCU_H__ +#define __SUN8IW20_REG_CCU_H__ + +#include + +#define CCU_BASE (0x02001000) + +#define CCU_PLL_CPU_CTRL_REG (0x000) +#define CCU_PLL_DDR_CTRL_REG (0x010) +#define CCU_PLL_PERI0_CTRL_REG (0x020) +#define CCU_PLL_PERI1_CTRL_REG (0x028) +#define CCU_PLL_GPU_CTRL_REG (0x030) +#define CCU_PLL_VIDEO0_CTRL_REG (0x040) +#define CCU_PLL_VIDEO1_CTRL_REG (0x048) +#define CCU_PLL_VE_CTRL (0x058) +#define CCU_PLL_DE_CTRL (0x060) +#define CCU_PLL_HSIC_CTRL (0x070) +#define CCU_PLL_AUDIO0_CTRL_REG (0x078) +#define CCU_PLL_AUDIO1_CTRL_REG (0x080) +#define CCU_PLL_DDR_PAT0_CTRL_REG (0x110) +#define CCU_PLL_DDR_PAT1_CTRL_REG (0x114) +#define CCU_PLL_PERI0_PAT0_CTRL_REG (0x120) +#define CCU_PLL_PERI0_PAT1_CTRL_REG (0x124) +#define CCU_PLL_PERI1_PAT0_CTRL_REG (0x128) +#define CCU_PLL_PERI1_PAT1_CTRL_REG (0x12c) +#define CCU_PLL_GPU_PAT0_CTRL_REG (0x130) +#define CCU_PLL_GPU_PAT1_CTRL_REG (0x134) +#define CCU_PLL_VIDEO0_PAT0_CTRL_REG (0x140) +#define CCU_PLL_VIDEO0_PAT1_CTRL_REG (0x144) +#define CCU_PLL_VIDEO1_PAT0_CTRL_REG (0x148) +#define CCU_PLL_VIDEO1_PAT1_CTRL_REG (0x14c) +#define CCU_PLL_VE_PAT0_CTRL_REG (0x158) +#define CCU_PLL_VE_PAT1_CTRL_REG (0x15c) +#define CCU_PLL_DE_PAT0_CTRL_REG (0x160) +#define CCU_PLL_DE_PAT1_CTRL_REG (0x164) +#define CCU_PLL_HSIC_PAT0_CTRL_REG (0x170) +#define CCU_PLL_HSIC_PAT1_CTRL_REG (0x174) +#define CCU_PLL_AUDIO0_PAT0_CTRL_REG (0x178) +#define CCU_PLL_AUDIO0_PAT1_CTRL_REG (0x17c) +#define CCU_PLL_AUDIO1_PAT0_CTRL_REG (0x180) +#define CCU_PLL_AUDIO1_PAT1_CTRL_REG (0x184) +#define CCU_PLL_CPU_BIAS_REG (0x300) +#define CCU_PLL_DDR_BIAS_REG (0x310) +#define CCU_PLL_PERI0_BIAS_REG (0x320) +#define CCU_PLL_PERI1_BIAS_REG (0x328) +#define CCU_PLL_GPU_BIAS_REG (0x330) +#define CCU_PLL_VIDEO0_BIAS_REG (0x340) +#define CCU_PLL_VIDEO1_BIAS_REG (0x348) +#define CCU_PLL_VE_BIAS_REG (0x358) +#define CCU_PLL_DE_BIAS_REG (0x360) +#define CCU_PLL_HSIC_BIAS_REG (0x370) +#define CCU_PLL_AUDIO0_BIAS_REG (0x378) +#define CCU_PLL_AUDIO1_BIAS_REG (0x380) +#define CCU_PLL_CPU_TUN_REG (0x400) +#define CCU_CPU_AXI_CFG_REG (0x500) +#define CCU_CPU_GATING_REG (0x504) +#define CCU_PSI_CLK_REG (0x510) +#define CCU_AHB3_CLK_REG (0x51c) +#define CCU_APB0_CLK_REG (0x520) +#define CCU_APB1_CLK_REG (0x524) +#define CCU_MBUS_CLK_REG (0x540) +#define CCU_DMA_BGR_REG (0x70c) +#define CCU_DRAM_CLK_REG (0x800) +#define CCU_MBUS_MAT_CLK_GATING_REG (0x804) +#define CCU_DRAM_BGR_REG (0x80c) +#define CCU_SMHC0_CLK_REG (0x830) +#define CCU_SMHC_BGR_REG (0x84c) +#define CCU_UART_BGR_REG (0x90c) +#define CCU_TWI_BGR_REG (0x91c) +#define CCU_SCR_BGR_REG (0x93C) +#define CCU_SPI0_CLK_REG (0x940) +#define CCU_SPI_BGR_REG (0x96c) + +/* MMC clock bit field */ +#define CCU_MMC_CTRL_M(x) ((x) -1) +#define CCU_MMC_CTRL_N(x) ((x) << 8) +#define CCU_MMC_CTRL_OSCM24 (0x0 << 24) +#define CCU_MMC_CTRL_PLL6X1 (0x1 << 24) +#define CCU_MMC_CTRL_PLL6X2 (0x2 << 24) +#define CCU_MMC_CTRL_PLL_PERIPH1X CCU_MMC_CTRL_PLL6X1 +#define CCU_MMC_CTRL_PLL_PERIPH2X CCU_MMC_CTRL_PLL6X2 +#define CCU_MMC_CTRL_ENABLE (0x1 << 31) +/* if doesn't have these delays */ +#define CCU_MMC_CTRL_OCLK_DLY(a) ((void) (a), 0) +#define CCU_MMC_CTRL_SCLK_DLY(a) ((void) (a), 0) + +#define CCU_MMC_BGR_SMHC0_GATE (1 << 0) +#define CCU_MMC_BGR_SMHC1_GATE (1 << 1) +#define CCU_MMC_BGR_SMHC2_GATE (1 << 2) + +#define CCU_MMC_BGR_SMHC0_RST (1 << 16) +#define CCU_MMC_BGR_SMHC1_RST (1 << 17) +#define CCU_MMC_BGR_SMHC2_RST (1 << 18) + +/* RISC-V base */ +#define CCU_RISCV_GATING_RST_REG (CCU_BASE + 0x0d04) +#define CCU_RISCV_CLK_GATING (0x1 << 31) +#define CCU_RISCV_GATING_FIELD (0x16aa << 0) + +#define CCU_RISCV_RST_REG (CCU_BASE + 0x0f20) +#define CCU_RISCV_RST_KEY_FIELD (0x16aa << 16) +#define CCU_RISCV_RST_SOFT_RSTN (0x1 << 0) + +#define CCU_RISCV_CLK_REG (CCU_BASE + 0x0d00) +#define CCU_RISCV_CLK_MASK (0x7 << 24) +#define CCU_RISCV_CLK_HOSC (0x0 << 24) +#define CCU_RISCV_CLK_32K (0x1 << 24) +#define CCU_RISCV_CLK_16M (0x2 << 24) +#define CCU_RISCV_CLK_PERI_800M (0x3 << 24) +#define CCU_RISCV_CLK_PERI_PERIPLL1X (0x4 << 24) +#define CCU_RISCV_CLK_CPUPLL (0x5 << 24) +#define CCU_RISCV_CLK_AUDIO1PLL_DIV2 (0x6 << 24) + +#define CCU_RISCV_CFG_BGR_REG (CCU_BASE + 0x0d0c) +#define CCU_RISCV_CFG_RST (0x1 << 16) +#define CCU_RISCV_CFG_GATING (0x1 << 0) + +#define CCU_RISCV_CFG_BASE (0x06010000) +#define CCU_RISCV_STA_ADD_L_REG (CCU_RISCV_CFG_BASE + 0x0004) +#define CCU_RISCV_STA_ADD_H_REG (CCU_RISCV_CFG_BASE + 0x0008) + +#endif// __SUN8IW20_REG_CCU_H__ diff --git a/include/drivers/sun8iw20/reg/reg-dma.h b/include/drivers/sun8iw20/reg/reg-dma.h new file mode 100644 index 00000000..26a23ba6 --- /dev/null +++ b/include/drivers/sun8iw20/reg/reg-dma.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW20_REG_DMA_H__ +#define __SUN8IW20_REG_DMA_H__ + +#include + +#define SUNXI_DMA_CHANNEL_BASE (SUNXI_DMA_BASE + 0x100) +#define DMA_AUTO_GATE_REG (SUNXI_DMA_BASE + 0x28) + +#define SUNXI_DMA_CHANNEL_SIZE (0x40) +#define SUNXI_DMA_LINK_NULL (0xfffff800) + +#define DMAC_DMATYPE_NORMAL 0 +#define DMAC_CFG_TYPE_DRAM (1) +#define DMAC_CFG_TYPE_SRAM (0) + +#define DMAC_CFG_TYPE_SPI0 (22) +#define DMAC_CFG_TYPE_SHMC0 (20) +#define DMAC_CFG_SRC_TYPE_NAND (5) + +/* DMA base config */ +#define DMAC_CFG_CONTINUOUS_ENABLE (0x01) +#define DMAC_CFG_CONTINUOUS_DISABLE (0x00) + +/* ----------DMA dest config-------------------- */ +/* DMA dest width config */ +#define DMAC_CFG_DEST_DATA_WIDTH_8BIT (0x00) +#define DMAC_CFG_DEST_DATA_WIDTH_16BIT (0x01) +#define DMAC_CFG_DEST_DATA_WIDTH_32BIT (0x02) +#define DMAC_CFG_DEST_DATA_WIDTH_64BIT (0x03) + +/* DMA dest bust config */ +#define DMAC_CFG_DEST_1_BURST (0x00) +#define DMAC_CFG_DEST_4_BURST (0x01) +#define DMAC_CFG_DEST_8_BURST (0x02) +#define DMAC_CFG_DEST_16_BURST (0x03) + +#define DMAC_CFG_DEST_ADDR_TYPE_LINEAR_MODE (0x00) +#define DMAC_CFG_DEST_ADDR_TYPE_IO_MODE (0x01) + +/* ----------DMA src config -------------------*/ +#define DMAC_CFG_SRC_DATA_WIDTH_8BIT (0x00) +#define DMAC_CFG_SRC_DATA_WIDTH_16BIT (0x01) +#define DMAC_CFG_SRC_DATA_WIDTH_32BIT (0x02) +#define DMAC_CFG_SRC_DATA_WIDTH_64BIT (0x03) + +#define DMAC_CFG_SRC_1_BURST (0x00) +#define DMAC_CFG_SRC_4_BURST (0x01) +#define DMAC_CFG_SRC_8_BURST (0x02) +#define DMAC_CFG_SRC_16_BURST (0x03) + +#define DMAC_CFG_SRC_ADDR_TYPE_LINEAR_MODE (0x00) +#define DMAC_CFG_SRC_ADDR_TYPE_IO_MODE (0x01) + +/*dma int config*/ +#define DMA_PKG_HALF_INT (1 << 0) +#define DMA_PKG_END_INT (1 << 1) +#define DMA_QUEUE_END_INT (1 << 2) + +#endif// __SUN8IW20_REG_DMA_H__ \ No newline at end of file diff --git a/include/reg/reg-dram.h b/include/drivers/sun8iw20/reg/reg-dram.h similarity index 97% rename from include/reg/reg-dram.h rename to include/drivers/sun8iw20/reg/reg-dram.h index 4fa61116..fac95eb8 100644 --- a/include/reg/reg-dram.h +++ b/include/drivers/sun8iw20/reg/reg-dram.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef __REG_DRAM_H__ -#define __REG_DRAM_H__ +#ifndef __SUN8IW20_REG_DRAM_H__ +#define __SUN8IW20_REG_DRAM_H__ #define MCTL_COM_BASE (0x3102000) #define MCTL_COM_WORK_MODE0 (0x00) @@ -114,4 +114,4 @@ #define VDD_SYS_PWROFF_GATING_REG (0x250) #define ANALOG_PWROFF_GATING_REG (0x254) -#endif /* __REG_DRAM_H__ */ \ No newline at end of file +#endif /* __SUN8IW20_REG_DRAM_H__ */ \ No newline at end of file diff --git a/include/reg/reg-ncat.h b/include/drivers/sun8iw20/reg/reg-ncat.h similarity index 95% rename from include/reg/reg-ncat.h rename to include/drivers/sun8iw20/reg/reg-ncat.h index 3c448ac0..bd601b09 100644 --- a/include/reg/reg-ncat.h +++ b/include/drivers/sun8iw20/reg/reg-ncat.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef __REG_NCAT_H__ -#define __REG_NCAT_H__ +#ifndef __SUN8IW20_REG_NCAT_H__ +#define __SUN8IW20_REG_NCAT_H__ /*CPUX*/ #define SUNXI_CPUXCFG_BASE (0x08100000) @@ -26,6 +26,7 @@ /*storage*/ #define SUNXI_SMHC0_BASE (0x04020000) #define SUNXI_SMHC1_BASE (0x04021000) +#define SUNXI_SMHC2_BASE (0x04022000) /*noraml*/ #define SUNXI_UART0_BASE (0x02500000) @@ -68,8 +69,6 @@ #define AUDIO_POWER_REG (SUNXI_AUDIO_CODEC + 0x348) #define SUNXI_VER_REG (SUNXI_SYSCRL_BASE + 0x24) -/* use for usb correct */ -#define VDD_SYS_PWROFF_GATING_REG (SUNXI_RPRCM_BASE + 0x250) #define RES_CAL_CTRL_REG (SUNXI_RPRCM_BASE + 0X310) #define ANA_PWR_RST_REG (SUNXI_RPRCM_BASE + 0X254) @@ -94,4 +93,4 @@ #define VCCIO_THRESHOLD_VOLTAGE_3_0 (5 << 4) #define VCCIO_DET_BYPASS_EN (1 << 0) -#endif \ No newline at end of file +#endif// __SUN8IW20_REG_NCAT_H__ \ No newline at end of file diff --git a/include/reg/reg-rproc.h b/include/drivers/sun8iw20/reg/reg-rproc.h similarity index 100% rename from include/reg/reg-rproc.h rename to include/drivers/sun8iw20/reg/reg-rproc.h diff --git a/include/drivers/sun8iw20/sys-clk.h b/include/drivers/sun8iw20/sys-clk.h new file mode 100644 index 00000000..373a904c --- /dev/null +++ b/include/drivers/sun8iw20/sys-clk.h @@ -0,0 +1,12 @@ +#ifndef __SUN8IW20_CLK_H__ +#define __SUN8IW20_CLK_H__ + +#include "reg/reg-ccu.h" + +void sunxi_clk_init(void); + +void sunxi_clk_reset(void); + +void sunxi_clk_dump(void); + +#endif// __SUN8IW20_CLK_H__ \ No newline at end of file diff --git a/include/drivers/sun8iw20/sys-dram.h b/include/drivers/sun8iw20/sys-dram.h new file mode 100644 index 00000000..60e34297 --- /dev/null +++ b/include/drivers/sun8iw20/sys-dram.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __SUN8IW20_SYS_DRAM_H__ +#define __SUN8IW20_SYS_DRAM_H__ + +#include +#include +#include +#include +#include +#include + +#include "reg/reg-dram.h" + +#define SDRAM_BASE (0x40000000) + +enum sunxi_dram_type { + SUNXI_DRAM_TYPE_DDR2 = 2, + SUNXI_DRAM_TYPE_DDR3 = 3, + SUNXI_DRAM_TYPE_LPDDR2 = 6, + SUNXI_DRAM_TYPE_LPDDR3 = 7, +}; + +typedef struct __DRAM_PARA { + // normal configuration + uint32_t dram_clk; + uint32_t dram_type;// dram_type DDR2: 2 DDR3: 3 LPDDR2: 6 LPDDR3: 7 DDR3L: 31 + uint32_t dram_zq; // do not need + uint32_t dram_odt_en; + + // control configuration + uint32_t dram_para1; + uint32_t dram_para2; + + // timing configuration + uint32_t dram_mr0; + uint32_t dram_mr1; + uint32_t dram_mr2; + uint32_t dram_mr3; + uint32_t dram_tpr0;// DRAMTMG0 + uint32_t dram_tpr1;// DRAMTMG1 + uint32_t dram_tpr2;// DRAMTMG2 + uint32_t dram_tpr3;// DRAMTMG3 + uint32_t dram_tpr4;// DRAMTMG4 + uint32_t dram_tpr5;// DRAMTMG5 + uint32_t dram_tpr6;// DRAMTMG8 + // reserved for future use + uint32_t dram_tpr7; + uint32_t dram_tpr8; + uint32_t dram_tpr9; + uint32_t dram_tpr10; + uint32_t dram_tpr11; + uint32_t dram_tpr12; + uint32_t dram_tpr13; +} dram_para_t; + +int init_DRAM(int type, dram_para_t *para); + +uint64_t sunxi_dram_init(dram_para_t *para); + +#endif // __SUN8IW20_SYS_DRAM_H__ diff --git a/include/drivers/sun8iw20/sys-rproc.h b/include/drivers/sun8iw20/sys-rproc.h new file mode 100644 index 00000000..725a5f8f --- /dev/null +++ b/include/drivers/sun8iw20/sys-rproc.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW20_SYS_RPROC_H__ +#define __SUN8IW20_SYS_RPROC_H__ + +#include "reg/reg-rproc.h" + +void sunxi_c906_clock_init(uint32_t addr); + +void sunxi_c906_clock_reset(void); + +#endif// __SUN8IW20_SYS_RPROC_H__ \ No newline at end of file diff --git a/include/drivers/sun8iw20/sys-sid.h b/include/drivers/sun8iw20/sys-sid.h new file mode 100644 index 00000000..1db5581c --- /dev/null +++ b/include/drivers/sun8iw20/sys-sid.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW20_SYS_SID_H__ +#define __SUN8IW20_SYS_SID_H__ + +#include +#include +#include +#include +#include +#include + +#include "log.h" + +#include + +static const struct sid_section_t { + char *name; + uint32_t offset; + uint32_t size_bits; +} sids[] = { + {"chipid", 0x0000, 128}, + {"brom-conf-try", 0x0010, 32}, + {"thermal-sensor", 0x0014, 64}, + {"ft-zone", 0x001c, 128}, + {"tvout", 0x002c, 32}, + {"tvout-gamma", 0x0030, 64}, + {"oem-program", 0x0038, 64}, + {"write-protect", 0x0040, 32}, + {"read-protect", 0x0044, 32}, + {"reserved1", 0x0048, 64}, + {"huk", 0x0050, 192}, + {"reserved2", 0x0068, 64}, + {"rotpk", 0x0070, 256}, + {"ssk", 0x0090, 256}, + {"rssk", 0x00b0, 128}, + {"hdcp-hash", 0x00c0, 128}, + {"nv1", 0x00d0, 32}, + {"nv2", 0x00d4, 32}, + {"reserved3", 0x00d8, 96}, + {"oem-program-secure", 0x00e4, 224}, +}; + +enum { + SID_PRCTL = SUNXI_SID_BASE + 0x040, + SID_PRKEY = SUNXI_SID_BASE + 0x050, + SID_RDKEY = SUNXI_SID_BASE + 0x060, + EFUSE_HV_SWITCH = SUNXI_RTC_BASE + 0x204, +}; + +uint32_t efuse_read(uint32_t offset); + +void efuse_write(uint32_t offset, uint32_t value); + +void dump_efuse(void); + +#endif// __SUN8IW20_SYS_SID_H__ \ No newline at end of file diff --git a/include/reg/reg-ccu.h b/include/drivers/sun8iw21/reg/reg-ccu.h similarity index 99% rename from include/reg/reg-ccu.h rename to include/drivers/sun8iw21/reg/reg-ccu.h index 748d77ae..5e2e41ce 100644 --- a/include/reg/reg-ccu.h +++ b/include/drivers/sun8iw21/reg/reg-ccu.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#ifndef __CCU_H__ -#define __CCU_H__ +#ifndef __SUN8IW21_REG_CCU_H__ +#define __SUN8IW21_REG_CCU_H__ #define CCU_BASE (0x02001000) @@ -174,4 +174,4 @@ #define CCU_RISCV_CFG_GATING \ (0x1 << 0)// Bit field value for RISC-V configuration gating -#endif +#endif // __SUN8IW21_REG_CCU_H__ diff --git a/include/drivers/sun8iw21/reg/reg-dma.h b/include/drivers/sun8iw21/reg/reg-dma.h new file mode 100644 index 00000000..29325576 --- /dev/null +++ b/include/drivers/sun8iw21/reg/reg-dma.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW21_REG_DMA_H__ +#define __SUN8IW21_REG_DMA_H__ + +#include + +#define SUNXI_DMA_CHANNEL_BASE (SUNXI_DMA_BASE + 0x100) +#define DMA_AUTO_GATE_REG (SUNXI_DMA_BASE + 0x28) + +#define SUNXI_DMA_CHANNEL_SIZE (0x40) +#define SUNXI_DMA_LINK_NULL (0xfffff800) + +#define DMAC_DMATYPE_NORMAL 0 +#define DMAC_CFG_TYPE_DRAM (1) +#define DMAC_CFG_TYPE_SRAM (0) + +#define DMAC_CFG_TYPE_SPI0 (22) +#define DMAC_CFG_TYPE_SHMC0 (20) +#define DMAC_CFG_SRC_TYPE_NAND (5) + +/* DMA base config */ +#define DMAC_CFG_CONTINUOUS_ENABLE (0x01) +#define DMAC_CFG_CONTINUOUS_DISABLE (0x00) + +/* ----------DMA dest config-------------------- */ +/* DMA dest width config */ +#define DMAC_CFG_DEST_DATA_WIDTH_8BIT (0x00) +#define DMAC_CFG_DEST_DATA_WIDTH_16BIT (0x01) +#define DMAC_CFG_DEST_DATA_WIDTH_32BIT (0x02) +#define DMAC_CFG_DEST_DATA_WIDTH_64BIT (0x03) + +/* DMA dest bust config */ +#define DMAC_CFG_DEST_1_BURST (0x00) +#define DMAC_CFG_DEST_4_BURST (0x01) +#define DMAC_CFG_DEST_8_BURST (0x02) +#define DMAC_CFG_DEST_16_BURST (0x03) + +#define DMAC_CFG_DEST_ADDR_TYPE_LINEAR_MODE (0x00) +#define DMAC_CFG_DEST_ADDR_TYPE_IO_MODE (0x01) + +/* ----------DMA src config -------------------*/ +#define DMAC_CFG_SRC_DATA_WIDTH_8BIT (0x00) +#define DMAC_CFG_SRC_DATA_WIDTH_16BIT (0x01) +#define DMAC_CFG_SRC_DATA_WIDTH_32BIT (0x02) +#define DMAC_CFG_SRC_DATA_WIDTH_64BIT (0x03) + +#define DMAC_CFG_SRC_1_BURST (0x00) +#define DMAC_CFG_SRC_4_BURST (0x01) +#define DMAC_CFG_SRC_8_BURST (0x02) +#define DMAC_CFG_SRC_16_BURST (0x03) + +#define DMAC_CFG_SRC_ADDR_TYPE_LINEAR_MODE (0x00) +#define DMAC_CFG_SRC_ADDR_TYPE_IO_MODE (0x01) + +/*dma int config*/ +#define DMA_PKG_HALF_INT (1 << 0) +#define DMA_PKG_END_INT (1 << 1) +#define DMA_QUEUE_END_INT (1 << 2) + +#endif// __SUN8IW21_REG_DMA_H__ \ No newline at end of file diff --git a/include/drivers/sun8iw21/reg/reg-dram.h b/include/drivers/sun8iw21/reg/reg-dram.h new file mode 100644 index 00000000..2acc5a77 --- /dev/null +++ b/include/drivers/sun8iw21/reg/reg-dram.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __SUN8IW21_REG_DRAM_H__ +#define __SUN8IW21_REG_DRAM_H__ + +#define MCTL_COM_BASE (0x3102000) +#define MCTL_COM_WORK_MODE0 (0x00) +#define MCTL_COM_WORK_MODE1 (0x04) +#define MCTL_COM_DBGCR (0x08) +#define MCTL_COM_TMR (0x0c) +#define MCTL_COM_CCCR (0x14) +#define MCTL_COM_MAER0 (0x20) +#define MCTL_COM_MAER1 (0x24) +#define MCTL_COM_MAER2 (0x28) +#define MCTL_COM_REMAP0 (0x500) +#define MCTL_COM_REMAP1 (0x504) +#define MCTL_COM_REMAP2 (0x508) +#define MCTL_COM_REMAP3 (0x50c) + +#define MCTL_PHY_BASE (0x3103000) +#define MCTL_PHY_PIR (0x00) +#define MCTL_PHY_PWRCTL (0x04) +#define MCTL_PHY_MRCTRL0 (0x08) +#define MCTL_PHY_CLKEN (0x0c) +#define MCTL_PHY_PGSR0 (0x10) +#define MCTL_PHY_PGSR1 (0x14) +#define MCTL_PHY_STATR (0x18) +#define MCTL_PHY_LP3MR11 (0x2c) +#define MCTL_PHY_DRAM_MR0 (0x30) +#define MCTL_PHY_DRAM_MR1 (0x34) +#define MCTL_PHY_DRAM_MR2 (0x38) +#define MCTL_PHY_DRAM_MR3 (0x3c) +#define MCTL_PHY_PTR0 (0x44) +#define MCTL_PHY_PTR2 (0x4c) +#define MCTL_PHY_PTR3 (0x50) +#define MCTL_PHY_PTR4 (0x54) +#define MCTL_PHY_DRAMTMG0 (0x58) +#define MCTL_PHY_DRAMTMG1 (0x5c) +#define MCTL_PHY_DRAMTMG2 (0x60) +#define MCTL_PHY_DRAMTMG3 (0x64) +#define MCTL_PHY_DRAMTMG4 (0x68) +#define MCTL_PHY_DRAMTMG5 (0x6c) +#define MCTL_PHY_DRAMTMG6 (0x70) +#define MCTL_PHY_DRAMTMG7 (0x74) +#define MCTL_PHY_DRAMTMG8 (0x78) +#define MCTL_PHY_ODTCFG (0x7c) +#define MCTL_PHY_PITMG0 (0x80) +#define MCTL_PHY_PITMG1 (0x84) +#define MCTL_PHY_LPTPR (0x88) +#define MCTL_PHY_RFSHCTL0 (0x8c) +#define MCTL_PHY_RFSHTMG (0x90) +#define MCTL_PHY_RFSHCTL1 (0x94) +#define MCTL_PHY_PWRTMG (0x98) +#define MCTL_PHY_ASRC (0x9c) +#define MCTL_PHY_ASRTC (0xa0) +#define MCTL_PHY_VTFCR (0xb8) +#define MCTL_PHY_DQSGMR (0xbc) +#define MCTL_PHY_DTCR (0xc0) +#define MCTL_PHY_DTAR0 (0xc4) +#define MCTL_PHY_PGCR0 (0x100) +#define MCTL_PHY_PGCR1 (0x104) +#define MCTL_PHY_PGCR2 (0x108) +#define MCTL_PHY_PGCR3 (0x10c) +#define MCTL_PHY_IOVCR0 (0x110) +#define MCTL_PHY_IOVCR1 (0x114) +#define MCTL_PHY_DXCCR (0x11c) +#define MCTL_PHY_ODTMAP (0x120) +#define MCTL_PHY_ZQCTL0 (0x124) +#define MCTL_PHY_ZQCTL1 (0x128) +#define MCTL_PHY_ZQCR (0x140) +#define MCTL_PHY_ZQSR (0x144) +#define MCTL_PHY_ZQDR0 (0x148) +#define MCTL_PHY_ZQDR1 (0x14c) +#define MCTL_PHY_ZQDR2 (0x150) +#define MCTL_PHY_SCHED (0x1c0) +#define MCTL_PHY_PERFHPR0 (0x1c4) +#define MCTL_PHY_PERFHPR1 (0x1c8) +#define MCTL_PHY_PERFLPR0 (0x1cc) +#define MCTL_PHY_PERFLPR1 (0x1d0) +#define MCTL_PHY_PERFWR0 (0x1d4) +#define MCTL_PHY_PERFWR1 (0x1d8) +#define MCTL_PHY_ACMDLR (0x200) +#define MCTL_PHY_ACLDLR (0x204) +#define MCTL_PHY_ACIOCR0 (0x208) +#define MCTL_PHY_ACIOCR1(x) (0x210 + 0x4 * x) +#define MCTL_PHY_DXnMDLR(x) (0x300 + 0x80 * x) +#define MCTL_PHY_DXnLDLR0(x) (0x304 + 0x80 * x) +#define MCTL_PHY_DXnLDLR1(x) (0x308 + 0x80 * x) +#define MCTL_PHY_DXnLDLR2(x) (0x30c + 0x80 * x) +#define MCTL_PHY_DXIOCR (0x310) +#define MCTL_PHY_DATX0IOCR(x) (0x310 + 0x4 * x) +#define MCTL_PHY_DATX1IOCR(x) (0x390 + 0x4 * x) +#define MCTL_PHY_DATX2IOCR(x) (0x410 + 0x4 * x) +#define MCTL_PHY_DATX3IOCR(x) (0x490 + 0x4 * x) +#define MCTL_PHY_DXnSDLR6(x) (0x33c + 0x80 * x) +#define MCTL_PHY_DXnGTR(x) (0x340 + 0x80 * x) +#define MCTL_PHY_DXnGCR0(x) (0x344 + 0x80 * x) +#define MCTL_PHY_DXnGSR0(x) (0x348 + 0x80 * x) + +#define SYS_CONTROL_REG_BASE (0x3000000) +#define LDO_CTAL_REG (0x150) +#define ZQ_CAL_CTRL_REG (0x160) +#define ZQ_RES_CTRL_REG (0x168) +#define ZQ_RES_STATUS_REG (0x16c) + +#define SYS_SID_BASE (0x3006000) +#define SYS_EFUSE_REG (0x228) +#define SYS_LDOB_SID (0x21c) + +#define SUNXI_R_CPUCFG_BASE (0x7000400) +#define SUNXI_R_CPUCFG_SUP_STAN_FLAG (0x1d4) + +#define R_PRCM_BASE (0x7010000) +#define VDD_SYS_PWROFF_GATING_REG (0x250) +#define ANALOG_PWROFF_GATING_REG (0x254) + +#endif /* __SUN8IW21_REG_DRAM_H__ */ \ No newline at end of file diff --git a/include/drivers/sun8iw21/reg/reg-ncat.h b/include/drivers/sun8iw21/reg/reg-ncat.h new file mode 100644 index 00000000..47c796c5 --- /dev/null +++ b/include/drivers/sun8iw21/reg/reg-ncat.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __SUN8IW21_REG_NCAT_H__ +#define __SUN8IW21_REG_NCAT_H__ + +/*CPUX*/ +#define SUNXI_CPUXCFG_BASE (0x08100000) + +/*sys ctrl*/ +#define SUNXI_TIMER_BASE (0x02050000) +#define SUNXI_CCM_BASE (0x02001000) +#define SUNXI_PIO_BASE (0x02000000) +#define SUNXI_SPC_BASE (0x02000800) +#define SUNXI_SYSCRL_BASE (0x03000000) +#define SUNXI_DMA_BASE (0x03002000) +#define SUNXI_SID_BASE (0x03006000) +#define SUNXI_SID_SRAM_BASE (0x03006200) + +#define SUNXI_WDOG_BASE (0x020500A0) + +#define SUNXI_CE_BASE (0x03040000) +#define SUNXI_SS_BASE SUNXI_CE_BASE + +#define SUNXI_SMC_BASE (0x03007000) + +/*storage*/ +#define SUNXI_SMHC0_BASE (0x04020000) +#define SUNXI_SMHC1_BASE (0x04021000) +#define SUNXI_SMHC2_BASE (0x04022000) + +/*noraml*/ +#define SUNXI_UART0_BASE (0x02500000) +#define SUNXI_UART1_BASE (0x02500400) +#define SUNXI_UART2_BASE (0x02500800) +#define SUNXI_UART3_BASE (0x02500C00) + +#define SUNXI_TWI0_BASE (0x02502000) +#define SUNXI_TWI1_BASE (0x02502400) + +#define SUNXI_SPI0_BASE (0x04025000) +#define SUNXI_SPI1_BASE (0x04026000) +#define SUNXI_SPIF_BASE (0x04f00000) + +/*physical key*/ +#define SUNXI_GPADC_BASE (0x02009000) +#define SUNXI_LRADC_BASE (0x02009800) +#define SUNXI_KEYADC_BASE SUNXI_LRADC_BASE + +/*cpus*/ +#define SUNXI_RTC_BASE (0x07090000) +#define SUNXI_AUDIO_CODEC (0x02030000) +#define SUNXI_CPUS_CFG_BASE (0x07000400) +#define SUNXI_RCPUCFG_BASE (SUNXI_CPUS_CFG_BASE) +#define SUNXI_RPRCM_BASE (0x07010000) +#define SUNXI_RPWM_BASE (0x07020c00) +#define SUNXI_RPIO_BASE (0x07022000) +#define SUNXI_R_PIO_BASE SUNXI_RPIO_BASE +#define SUNXI_RTWI_BASE (0x07020800) +#define SUNXI_RRSB_BASE (0x07083000) +#define SUNXI_RSB_BASE SUNXI_RRSB_BASE +#define SUNXI_RTWI_BRG_REG (SUNXI_RPRCM_BASE + 0x019c) +#define SUNXI_RTWI0_RST_BIT (16) +#define SUNXI_RTWI0_GATING_BIT (0) +#define SUNXI_RST_BIT (16) +#define SUNXI_GATING_BIT (0) + +#define SUNXI_RTC_DATA_BASE (SUNXI_RTC_BASE + 0x100) +#define AUDIO_CODEC_BIAS_REG (SUNXI_AUDIO_CODEC + 0x320) +#define AUDIO_POWER_REG (SUNXI_AUDIO_CODEC + 0x348) +#define SUNXI_VER_REG (SUNXI_SYSCRL_BASE + 0x24) + +#define RES_CAL_CTRL_REG (SUNXI_RPRCM_BASE + 0X310) +#define ANA_PWR_RST_REG (SUNXI_RPRCM_BASE + 0X254) + +#define VDD_ADDA_OFF_GATING (9) +#define CAL_ANA_EN (1) +#define CAL_EN (0) + +#define RVBARADDR0_L (SUNXI_CPUXCFG_BASE + 0x40) +#define RVBARADDR0_H (SUNXI_CPUXCFG_BASE + 0x44) + +#define SRAM_CONTRL_REG0 (SUNXI_SYSCRL_BASE + 0x0) +#define SRAM_CONTRL_REG1 (SUNXI_SYSCRL_BASE + 0x4) + + +/* rtc check power off */ +#define FORCE_DETECTER_OUTPUT (1 << 7) +#define VCCIO_THRESHOLD_VOLTAGE_2_5 (0 << 4) +#define VCCIO_THRESHOLD_VOLTAGE_2_6 (1 << 4) +#define VCCIO_THRESHOLD_VOLTAGE_2_7 (2 << 4) +#define VCCIO_THRESHOLD_VOLTAGE_2_8 (3 << 4) +#define VCCIO_THRESHOLD_VOLTAGE_2_9 (4 << 4) +#define VCCIO_THRESHOLD_VOLTAGE_3_0 (5 << 4) +#define VCCIO_DET_BYPASS_EN (1 << 0) + +#endif // __SUN8IW21_REG_NCAT_H__ \ No newline at end of file diff --git a/include/drivers/sun8iw21/reg/reg-rproc.h b/include/drivers/sun8iw21/reg/reg-rproc.h new file mode 100644 index 00000000..8eb19066 --- /dev/null +++ b/include/drivers/sun8iw21/reg/reg-rproc.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW21_REG_RPROC_H__ +#define __SUN8IW21_REG_RPROC_H__ + +#define RISCV_CFG_BASE (0x06010000)// Base address for RISC-V configuration +#define RISCV_STA_ADD_REG \ + (RISCV_CFG_BASE + 0x0204)// Register address for RISC-V start address + +#endif// __SUN8IW21_REG_RPROC_H__ \ No newline at end of file diff --git a/include/drivers/sun8iw21/sys-clk.h b/include/drivers/sun8iw21/sys-clk.h new file mode 100644 index 00000000..f7fbccbb --- /dev/null +++ b/include/drivers/sun8iw21/sys-clk.h @@ -0,0 +1,12 @@ +#ifndef __SUN8IW21_CLK_H__ +#define __SUN8IW21_CLK_H__ + +#include "reg/reg-ccu.h" + +void sunxi_clk_init(void); + +void sunxi_clk_reset(void); + +void sunxi_clk_dump(void); + +#endif// __SUN8IW21_CLK_H__ \ No newline at end of file diff --git a/include/drivers/sun8iw21/sys-dram.h b/include/drivers/sun8iw21/sys-dram.h new file mode 100644 index 00000000..1ec41d0d --- /dev/null +++ b/include/drivers/sun8iw21/sys-dram.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __SUN8IW21_SYS_DRAM_H__ +#define __SUN8IW21_SYS_DRAM_H__ + +#include +#include +#include +#include +#include +#include + +#include "reg/reg-dram.h" + +#define SDRAM_BASE (0x40000000) + +enum sunxi_dram_type { + SUNXI_DRAM_TYPE_DDR2 = 2, + SUNXI_DRAM_TYPE_DDR3 = 3, + SUNXI_DRAM_TYPE_LPDDR2 = 6, + SUNXI_DRAM_TYPE_LPDDR3 = 7, +}; + +typedef struct __DRAM_PARA { + // normal configuration + uint32_t dram_clk; + uint32_t dram_type;// dram_type DDR2: 2 DDR3: 3 LPDDR2: 6 LPDDR3: 7 DDR3L: 31 + uint32_t dram_zq; // do not need + uint32_t dram_odt_en; + + // control configuration + uint32_t dram_para1; + uint32_t dram_para2; + + // timing configuration + uint32_t dram_mr0; + uint32_t dram_mr1; + uint32_t dram_mr2; + uint32_t dram_mr3; + uint32_t dram_tpr0;// DRAMTMG0 + uint32_t dram_tpr1;// DRAMTMG1 + uint32_t dram_tpr2;// DRAMTMG2 + uint32_t dram_tpr3;// DRAMTMG3 + uint32_t dram_tpr4;// DRAMTMG4 + uint32_t dram_tpr5;// DRAMTMG5 + uint32_t dram_tpr6;// DRAMTMG8 + // reserved for future use + uint32_t dram_tpr7; + uint32_t dram_tpr8; + uint32_t dram_tpr9; + uint32_t dram_tpr10; + uint32_t dram_tpr11; + uint32_t dram_tpr12; + uint32_t dram_tpr13; +} dram_para_t; + +int init_DRAM(int type, dram_para_t *para); + +uint64_t sunxi_dram_init(dram_para_t *para); + +#endif // __SUN8IW21_SYS_DRAM_H__ diff --git a/include/drivers/sun8iw21/sys-rproc.h b/include/drivers/sun8iw21/sys-rproc.h new file mode 100644 index 00000000..d3ef8122 --- /dev/null +++ b/include/drivers/sun8iw21/sys-rproc.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW21_SYS_RPROC_H__ +#define __SUN8IW21_SYS_RPROC_H__ + +#include "reg/reg-rproc.h" + +void sunxi_e907_clock_init(uint32_t addr); + +void sunxi_e907_clock_reset(void); + +#endif// __SUN8IW21_SYS_RPROC_H__ \ No newline at end of file diff --git a/include/drivers/sun8iw21/sys-sid.h b/include/drivers/sun8iw21/sys-sid.h new file mode 100644 index 00000000..db662dab --- /dev/null +++ b/include/drivers/sun8iw21/sys-sid.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef __SUN8IW21_SYS_SID_H__ +#define __SUN8IW21_SYS_SID_H__ + +#include +#include +#include +#include +#include +#include + +#include "log.h" + +#include + +static const struct sid_section_t { + char *name; + uint32_t offset; + uint32_t size_bits; +} sids[] = { + {"chipid", 0x0000, 128}, + {"brom-conf-try", 0x0010, 32}, + {"thermal-sensor", 0x0014, 64}, + {"ft-zone", 0x001c, 128}, + {"reserved1", 0x002c, 96}, + {"write-protect", 0x0038, 32}, + {"read-protect", 0x003c, 32}, + {"lcjs", 0x0040, 32}, + {"reserved2", 0x0044, 800}, + {"rotpk", 0x00a8, 256}, + {"reserved3", 0x00c8, 448}, +}; + +enum { + SID_PRCTL = SUNXI_SID_BASE + 0x040, + SID_PRKEY = SUNXI_SID_BASE + 0x050, + SID_RDKEY = SUNXI_SID_BASE + 0x060, + EFUSE_HV_SWITCH = SUNXI_RTC_BASE + 0x204, +}; + +uint32_t efuse_read(uint32_t offset); + +void efuse_write(uint32_t offset, uint32_t value); + +void dump_efuse(void); + +#endif// __SUN8IW21_SYS_SID_H__ \ No newline at end of file diff --git a/include/drivers/sys-clk.h b/include/drivers/sys-clk.h index 377debbc..4e81dc56 100644 --- a/include/drivers/sys-clk.h +++ b/include/drivers/sys-clk.h @@ -1,27 +1,12 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - #ifndef __SYS_CLK_H__ #define __SYS_CLK_H__ -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "log.h" - -#include "reg-ccu.h" - -/* Init SoC Clock */ -void sunxi_clk_init(void); - -void sunxi_clk_reset(void); - -uint32_t sunxi_clk_get_peri1x_rate(void); - -void sunxi_clk_dump(void); - +#if defined(CONFIG_CHIP_SUN8IW21) + #include +#elif defined(CONFIG_CHIP_SUN8IW20) + #include +#else + #error "Unsupported chip" #endif + +#endif // __SYS_CLK_H__ \ No newline at end of file diff --git a/include/drivers/sys-dma.h b/include/drivers/sys-dma.h index c95971af..f10c1c9e 100644 --- a/include/drivers/sys-dma.h +++ b/include/drivers/sys-dma.h @@ -96,15 +96,23 @@ typedef struct { #define DMA_GATING_OFS 0 void dma_init(void); + void dma_exit(void); uint32_t dma_request(uint32_t dmatype); + uint32_t dma_request_from_last(uint32_t dmatype); + int dma_release(uint32_t hdma); + int dma_setting(uint32_t hdma, dma_set_t *cfg); + int dma_start(uint32_t hdma, uint32_t saddr, uint32_t daddr, uint32_t bytes); + int dma_stop(uint32_t hdma); + int dma_querystatus(uint32_t hdma); + int dma_test(uint32_t *src_addr, uint32_t *dst_addr); #endif /* _SUNXI_DMA_H */ diff --git a/include/drivers/sys-dram.h b/include/drivers/sys-dram.h index 330f710e..2e5b9bec 100644 --- a/include/drivers/sys-dram.h +++ b/include/drivers/sys-dram.h @@ -1,61 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -#ifndef __dram_head_h__ -#define __dram_head_h__ - -#include -#include -#include -#include -#include -#include - -#include "log.h" - -#define SDRAM_BASE (0x40000000) - -enum sunxi_dram_type { - SUNXI_DRAM_TYPE_DDR2 = 2, - SUNXI_DRAM_TYPE_DDR3 = 3, - SUNXI_DRAM_TYPE_LPDDR2 = 6, - SUNXI_DRAM_TYPE_LPDDR3 = 7, -}; - -typedef struct __DRAM_PARA { - // normal configuration - uint32_t dram_clk; - uint32_t dram_type;// dram_type DDR2: 2 DDR3: 3 LPDDR2: 6 LPDDR3: 7 DDR3L: 31 - uint32_t dram_zq; // do not need - uint32_t dram_odt_en; - - // control configuration - uint32_t dram_para1; - uint32_t dram_para2; - - // timing configuration - uint32_t dram_mr0; - uint32_t dram_mr1; - uint32_t dram_mr2; - uint32_t dram_mr3; - uint32_t dram_tpr0;// DRAMTMG0 - uint32_t dram_tpr1;// DRAMTMG1 - uint32_t dram_tpr2;// DRAMTMG2 - uint32_t dram_tpr3;// DRAMTMG3 - uint32_t dram_tpr4;// DRAMTMG4 - uint32_t dram_tpr5;// DRAMTMG5 - uint32_t dram_tpr6;// DRAMTMG8 - // reserved for future use - uint32_t dram_tpr7; - uint32_t dram_tpr8; - uint32_t dram_tpr9; - uint32_t dram_tpr10; - uint32_t dram_tpr11; - uint32_t dram_tpr12; - uint32_t dram_tpr13; -} dram_para_t; - -int init_DRAM(int type, dram_para_t *para); - -uint64_t sunxi_dram_init(void); - +#ifndef __SYS_DRAM_H__ +#define __SYS_DRAM_H__ + +#if defined(CONFIG_CHIP_SUN8IW21) + #include +#elif defined(CONFIG_CHIP_SUN8IW20) + #include +#else + #error "Unsupported chip" #endif + +#endif // __SYS_DRAM_H__ diff --git a/include/drivers/sys-gpio.h b/include/drivers/sys-gpio.h index 636d866f..cd3d8d12 100644 --- a/include/drivers/sys-gpio.h +++ b/include/drivers/sys-gpio.h @@ -27,13 +27,20 @@ enum { GPIO_DISABLED = 0xf, }; -#define PORTA 0 -#define PORTC 1 -#define PORTD 2 -#define PORTE 3 -#define PORTF 4 -#define PORTH 5 -#define SUNXI_GPIO_PORTS 6 +enum { + GPIO_PORTA = 0, + GPIO_PORTB, + GPIO_PORTC, + GPIO_PORTD, + GPIO_PORTE, + GPIO_PORTF, + GPIO_PORTG, + GPIO_PORTH, + GPIO_PORTI, + GPIO_PORTJ, + GPIO_PORTK, + GPIO_PORTL, +}; enum gpio_pull_t { GPIO_PULL_UP = 0, diff --git a/include/drivers/sys-rproc.h b/include/drivers/sys-rproc.h index 79ff128c..369c3a2e 100644 --- a/include/drivers/sys-rproc.h +++ b/include/drivers/sys-rproc.h @@ -3,8 +3,12 @@ #ifndef __SYS_RPROC_H__ #define __SYS_RPROC_H__ -void sunxi_e907_clock_init(uint32_t addr); - -void sunxi_e907_clock_reset(void); +#if defined(CONFIG_CHIP_SUN8IW21) + #include +#elif defined(CONFIG_CHIP_SUN8IW20) + #include +#else +#error "Unsupported chip" +#endif #endif// __SYS_RPROC_H__ \ No newline at end of file diff --git a/include/drivers/sys-sdcard.h b/include/drivers/sys-sdcard.h index 7ed01414..99a279bb 100644 --- a/include/drivers/sys-sdcard.h +++ b/include/drivers/sys-sdcard.h @@ -140,6 +140,7 @@ enum { enum { MMC_BUS_WIDTH_1 = 1, MMC_BUS_WIDTH_4 = 2, + MMC_BUS_WIDTH_8 = 3, }; enum { diff --git a/include/drivers/sys-sid.h b/include/drivers/sys-sid.h index 0ad2135c..debe9294 100644 --- a/include/drivers/sys-sid.h +++ b/include/drivers/sys-sid.h @@ -3,44 +3,12 @@ #ifndef _SYS_SID_H_ #define _SYS_SID_H_ -#include -#include -#include -#include -#include -#include - -#include "log.h" - -#include - -static const struct sid_section_t { - char *name; - uint32_t offset; - uint32_t size_bits; -} sids[] = { - {"chipid", 0x0000, 128}, - {"brom-conf-try", 0x0010, 32}, - {"thermal-sensor", 0x0014, 64}, - {"ft-zone", 0x001c, 128}, - {"reserved1", 0x002c, 96}, - {"write-protect", 0x0038, 32}, - {"read-protect", 0x003c, 32}, - {"lcjs", 0x0040, 32}, - {"reserved2", 0x0044, 800}, - {"rotpk", 0x00a8, 256}, - {"reserved3", 0x00c8, 448}, -}; - -enum { - SID_PRCTL = SUNXI_SID_BASE + 0x040, - SID_PRKEY = SUNXI_SID_BASE + 0x050, - SID_RDKEY = SUNXI_SID_BASE + 0x060, - EFUSE_HV_SWITCH = SUNXI_RTC_BASE + 0x204, -}; - -uint32_t efuse_read(uint32_t offset); - -void efuse_write(uint32_t offset, uint32_t value); +#if defined(CONFIG_CHIP_SUN8IW21) + #include +#elif defined(CONFIG_CHIP_SUN8IW20) + #include +#else + #error "Unsupported chip" +#endif #endif// _SYS_SID_H_ \ No newline at end of file diff --git a/include/drivers/sys-uart.h b/include/drivers/sys-uart.h index 1d4b22c5..a1b27d6b 100644 --- a/include/drivers/sys-uart.h +++ b/include/drivers/sys-uart.h @@ -1,20 +1,8 @@ -/* SPDX-License-Identifier: Apache-2.0 */ +#ifndef __SYS_UART_H__ +#define __SYS_UART_H__ -#ifndef __SYS_USART_H__ -#define __SYS_USART_H__ - -#include -#include -#include -#include -#include #include - -#include "sys-clk.h" -#include "sys-gpio.h" -#include "sys-uart.h" - -#include "log.h" +#include typedef struct { uint32_t base; @@ -31,4 +19,4 @@ int sunxi_serial_tstc(void *arg); char sunxi_serial_getc(void *arg); -#endif +#endif // __SYS_UART_H__ \ No newline at end of file diff --git a/include/jmp.h b/include/jmp.h deleted file mode 100644 index 53c0a6ef..00000000 --- a/include/jmp.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#ifndef _JMP_H_ -#define _JMP_H_ - -void enable_kernel_smp(void); - -void syterkit_jmp(uint32_t addr); - -void jmp_to_fel(); - -void syterkit_jmp_kernel(uint32_t addr, uint32_t fdt); - -#endif// _JMP_H_ \ No newline at end of file diff --git a/include/lib/elf/elf_loader.h b/include/lib/elf/elf_loader.h index 23ac00da..483ae4e8 100644 --- a/include/lib/elf/elf_loader.h +++ b/include/lib/elf/elf_loader.h @@ -3,8 +3,12 @@ #ifndef __ELF_LOADER_H__ #define __ELF_LOADER_H__ -phys_addr_t elf_get_entry_addr(phys_addr_t base); +phys_addr_t elf32_get_entry_addr(phys_addr_t base); -int load_elf_image(phys_addr_t img_addr); +int load_elf32_image(phys_addr_t img_addr); + +phys_addr_t elf64_get_entry_addr(phys_addr_t base); + +int load_elf64_image(phys_addr_t img_addr); #endif // __ELF_LOADER_H__ \ No newline at end of file diff --git a/include/log.h b/include/log.h index 49c215a3..c0274bf0 100644 --- a/include/log.h +++ b/include/log.h @@ -8,7 +8,8 @@ #include #include -#include +#include + #include #include "xformat.h" diff --git a/lib/elf/CMakeLists.txt b/lib/elf/CMakeLists.txt index 68d2239b..fc7b8958 100644 --- a/lib/elf/CMakeLists.txt +++ b/lib/elf/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(elf - elf.c + elf32.c + elf64.c ) target_link_libraries(elf PRIVATE gcc) \ No newline at end of file diff --git a/lib/elf/elf.c b/lib/elf/elf32.c similarity index 85% rename from lib/elf/elf.c rename to lib/elf/elf32.c index 4ec827e7..5766ca13 100644 --- a/lib/elf/elf.c +++ b/lib/elf/elf32.c @@ -12,7 +12,7 @@ void print_elf32_ehdr(Elf32_Ehdr *header) { - printk(LOG_LEVEL_DEBUG, "e_ident: "); + printk(LOG_LEVEL_INFO, "e_ident: "); for (int i = 0; i < EI_NIDENT; i++) { printk(LOG_LEVEL_MUTE, "%02x ", header->e_ident[i]); } @@ -32,7 +32,7 @@ void print_elf32_ehdr(Elf32_Ehdr *header) printk(LOG_LEVEL_DEBUG, "e_shstrndx: 0x%08x\n", header->e_shstrndx); } -phys_addr_t elf_get_entry_addr(phys_addr_t base) +phys_addr_t elf32_get_entry_addr(phys_addr_t base) { Elf32_Ehdr *ehdr; @@ -41,7 +41,7 @@ phys_addr_t elf_get_entry_addr(phys_addr_t base) return ehdr->e_entry; } -int load_elf_image(phys_addr_t img_addr) +int load_elf32_image(phys_addr_t img_addr) { int i; Elf32_Ehdr *ehdr; @@ -78,7 +78,7 @@ int load_elf_image(phys_addr_t img_addr) return 0; } -static Elf32_Shdr *elf_find_segment(phys_addr_t elf_addr, const char *seg_name) +static Elf32_Shdr *elf32_find_segment(phys_addr_t elf_addr, const char *seg_name) { int i = 0; Elf32_Shdr *shdr; @@ -101,22 +101,22 @@ static Elf32_Shdr *elf_find_segment(phys_addr_t elf_addr, const char *seg_name) return NULL; } -void *elf_find_segment_offset(phys_addr_t elf_addr, const char *seg_name) +void *elf32_find_segment_offset(phys_addr_t elf_addr, const char *seg_name) { Elf32_Shdr *shdr; - shdr = elf_find_segment(elf_addr, seg_name); + shdr = elf32_find_segment(elf_addr, seg_name); if (!shdr) return NULL; return (void *)elf_addr + shdr->sh_offset; } -void *elf_find_segment_addr(phys_addr_t elf_addr, const char *seg_name) +void *elf32_find_segment_addr(phys_addr_t elf_addr, const char *seg_name) { Elf32_Shdr *shdr; - shdr = elf_find_segment(elf_addr, seg_name); + shdr = elf32_find_segment(elf_addr, seg_name); if (!shdr) return NULL; diff --git a/lib/elf/elf64.c b/lib/elf/elf64.c new file mode 100644 index 00000000..aacdbbd4 --- /dev/null +++ b/lib/elf/elf64.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +void print_elf64_ehdr(Elf64_Ehdr *header) +{ + printk(LOG_LEVEL_INFO, "e_ident: "); + for (int i = 0; i < EI_NIDENT; i++) { + printk(LOG_LEVEL_MUTE, "%02x ", header->e_ident[i]); + } + printk(LOG_LEVEL_MUTE, "\n"); + printk(LOG_LEVEL_DEBUG, "e_type: 0x%08x\n", header->e_type); + printk(LOG_LEVEL_DEBUG, "e_machine: 0x%08x\n", header->e_machine); + printk(LOG_LEVEL_DEBUG, "e_version: 0x%08x\n", header->e_version); + printk(LOG_LEVEL_DEBUG, "e_entry: 0x%08x\n", header->e_entry); + printk(LOG_LEVEL_DEBUG, "e_phoff: 0x%08x\n", header->e_phoff); + printk(LOG_LEVEL_DEBUG, "e_shoff: 0x%08x\n", header->e_shoff); + printk(LOG_LEVEL_DEBUG, "e_flags: 0x%08x\n", header->e_flags); + printk(LOG_LEVEL_DEBUG, "e_ehsize: 0x%08x\n", header->e_ehsize); + printk(LOG_LEVEL_DEBUG, "e_phentsize: 0x%08x\n", header->e_phentsize); + printk(LOG_LEVEL_DEBUG, "e_phnum: 0x%08x\n", header->e_phnum); + printk(LOG_LEVEL_DEBUG, "e_shentsize: 0x%08x\n", header->e_shentsize); + printk(LOG_LEVEL_DEBUG, "e_shnum: 0x%08x\n", header->e_shnum); + printk(LOG_LEVEL_DEBUG, "e_shstrndx: 0x%08x\n", header->e_shstrndx); +} + +phys_addr_t elf64_get_entry_addr(phys_addr_t base) +{ + Elf64_Ehdr *ehdr; + + ehdr = (Elf64_Ehdr *)base; + + return ehdr->e_entry; +} + +int load_elf64_image(phys_addr_t img_addr) +{ + int i; + Elf64_Ehdr *ehdr; + Elf64_Phdr *phdr; + + void *dst = NULL; + void *src = NULL; + + ehdr = (Elf64_Ehdr *)img_addr; + + print_elf64_ehdr(ehdr); + + phdr = (Elf64_Phdr *)(img_addr + ehdr->e_phoff); + + /* load elf program segment */ + for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { + dst = (void *)((phys_addr_t)phdr->p_paddr); + src = (void *)(img_addr + phdr->p_offset); + + if (phdr->p_type != PT_LOAD) + continue; + + if ((phdr->p_memsz == 0) || (phdr->p_filesz == 0)) + continue; + + if (phdr->p_filesz) + memcpy(dst, src, phdr->p_filesz); + + if (phdr->p_filesz != phdr->p_memsz) + memset((u8 *)dst + phdr->p_filesz, 0x00, + phdr->p_memsz - phdr->p_filesz); + } + + return 0; +} + +static Elf64_Shdr *elf64_find_segment(phys_addr_t elf_addr, const char *seg_name) +{ + int i = 0; + Elf64_Shdr *shdr; + Elf64_Ehdr *ehdr; + const char *name_table; + const uint8_t *elf_data = (void *)elf_addr; + + ehdr = (Elf64_Ehdr *)elf_data; + shdr = (Elf64_Shdr *)(elf_data + ehdr->e_shoff); + name_table = + (const char *)(elf_data + shdr[ehdr->e_shstrndx].sh_offset); + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + if (strcmp(name_table + shdr->sh_name, seg_name)) + continue; + + return shdr; + } + + return NULL; +} + +void *elf64_find_segment_offset(phys_addr_t elf_addr, const char *seg_name) +{ + Elf64_Shdr *shdr; + + shdr = elf64_find_segment(elf_addr, seg_name); + if (!shdr) + return NULL; + + return (void *)elf_addr + shdr->sh_offset; +} + +void *elf64_find_segment_addr(phys_addr_t elf_addr, const char *seg_name) +{ + Elf64_Shdr *shdr; + + shdr = elf64_find_segment(elf_addr, seg_name); + if (!shdr) + return NULL; + + return (void *)shdr->sh_addr; +} diff --git a/link/link_bin.ld b/link/arm32/link.ld similarity index 90% rename from link/link_bin.ld rename to link/arm32/link.ld index 713b3026..5f9b22a3 100644 --- a/link/link_bin.ld +++ b/link/arm32/link.ld @@ -7,7 +7,7 @@ SEARCH_DIR(.) /* Memory Spaces Definitions */ MEMORY { - ram (rwx) : ORIGIN = 0x00020000, LENGTH = 128K /* SRAMC. 132K on boot mode, 100K on FEL mode */ + ram (rwx) : ORIGIN = @ARCH_START_ADDRESS@, LENGTH = @ARCH_SRAM_LENGTH@ /* SRAMC. 132K on boot mode, 100K on FEL mode */ } /* The stack size used by the application. NOTE: you need to adjust according to your application. */ diff --git a/link/link_elf.ld b/link/link_elf.ld deleted file mode 100644 index c0d3e1ee..00000000 --- a/link/link_elf.ld +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -SEARCH_DIR(.) - -/* Memory Spaces Definitions */ -MEMORY -{ - ram (rwx) : ORIGIN = 0x00028000, LENGTH = 100K /* SRAMC. 132K on boot mode, 100K on FEL mode */ -} - -/* The stack size used by the application. NOTE: you need to adjust according to your application. */ -STACK_SIZE = 0x1000; /* 4KB */ - -/* Section Definitions */ -SECTIONS -{ - - .text : - { - . = ALIGN(4); - PROVIDE(__spl_start = .); - *(.text .text.*) - KEEP(*(.note.gnu.build-id)) - . = ALIGN(4); - } > ram - - . = ALIGN(4); - - .ARM.exidx : { - __exidx_start = .; - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __exidx_end = .; - } > ram - - PROVIDE(__spl_end = .); - PROVIDE(__spl_size = __spl_end - __spl_start); - - /* .bss section which is used for uninitialized data */ - .bss (NOLOAD) : - { - . = ALIGN(4); - _sbss = . ; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4); - _ebss = . ; - } > ram - - .stack (NOLOAD): - { - . = ALIGN(8); - /* SRV stack section */ - __stack_srv_start = .; - . += STACK_SIZE; - __stack_srv_end = .; - } > ram - - . = ALIGN(4); - _end = . ; -} diff --git a/scripts/genimage.sh b/scripts/genimage.sh deleted file mode 100755 index acc50e73..00000000 --- a/scripts/genimage.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -die() { - cat <&2 -Error: $@ - -Usage: ${0} -c GENIMAGE_CONFIG_FILE -EOF - exit 1 -} - -# Parse arguments and put into argument list of the script -opts="$(getopt -n "${0##*/}" -o c: -- "$@")" || exit $? -eval set -- "$opts" - -GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp" - -while true ; do - case "$1" in - -c) - GENIMAGE_CFG="${2}"; - shift 2 ;; - --) # Discard all non-option parameters - shift 1; - break ;; - *) - die "unknown option '${1}'" ;; - esac -done - -[ -n "${GENIMAGE_CFG}" ] || die "Missing argument" - -# Pass an empty rootpath. genimage makes a full copy of the given rootpath to -# ${GENIMAGE_TMP}/root so passing TARGET_DIR would be a waste of time and disk -# space. We don't rely on genimage to build the rootfs image, just to insert a -# pre-built one in the disk image. - -trap 'rm -rf "${ROOTPATH_TMP}"' EXIT -ROOTPATH_TMP="$(mktemp -d)" -GENIMAGE_TMP="$(mktemp -d)" -rm -rf "${GENIMAGE_TMP}" - -genimage \ - --rootpath "${ROOTPATH_TMP}" \ - --tmppath "${GENIMAGE_TMP}" \ - --inputpath "${BINARIES_DIR}" \ - --outputpath "${BINARIES_DIR}" \ - --config "${GENIMAGE_CFG}" diff --git a/scripts/genimage_buildroot.cfg b/scripts/genimage_buildroot.cfg deleted file mode 100644 index 383f898c..00000000 --- a/scripts/genimage_buildroot.cfg +++ /dev/null @@ -1,36 +0,0 @@ -image boot.vfat { - vfat { - files = { - "zImage", - "sunxi.dtb" - } - } - size = 8M -} - -image sdcard.img { - hdimage {} - - partition boot0 { - in-partition-table = "no" - image = "syter_boot_bin.bin" - offset = 8K - } - - partition boot0-gpt { - in-partition-table = "no" - image = "syter_boot_bin.bin" - offset = 128K - } - - partition kernel { - partition-type = 0xC - bootable = "true" - image = "boot.vfat" - } - - partition rootfs { - partition-type = 0x83 - image = "rootfs.img" - } -} diff --git a/scripts/genimage_loade907.cfg b/scripts/genimage_loade907.cfg deleted file mode 100644 index 24ba9193..00000000 --- a/scripts/genimage_loade907.cfg +++ /dev/null @@ -1,30 +0,0 @@ -image boot.vfat { - vfat { - files = { - "e907.elf", - } - } - size = 8M -} - -image sdcard.img { - hdimage {} - - partition boot0 { - in-partition-table = "no" - image = "loade907_bin.bin" - offset = 8K - } - - partition boot0-gpt { - in-partition-table = "no" - image = "loade907_bin.bin" - offset = 128K - } - - partition kernel { - partition-type = 0xC - bootable = "true" - image = "boot.vfat" - } -} diff --git a/scripts/genimage_openwrt.cfg b/scripts/genimage_openwrt.cfg deleted file mode 100644 index a2fb3df7..00000000 --- a/scripts/genimage_openwrt.cfg +++ /dev/null @@ -1,32 +0,0 @@ -image boot.vfat { - vfat { - files = { - "zImage", - "sunxi.dtb", - "config.txt" - } - } - size = 8M -} - -image sdcard.img { - hdimage {} - - partition boot0 { - in-partition-table = "no" - image = "syter_boot_bin_card.bin" - offset = 8K - } - - partition boot0-gpt { - in-partition-table = "no" - image = "syter_boot_bin_card.bin" - offset = 128K - } - - partition kernel { - partition-type = 0xC - bootable = "true" - image = "boot.vfat" - } -} diff --git a/scripts/genimage_syterboot_only.cfg b/scripts/genimage_syterboot_only.cfg deleted file mode 100644 index e0c038a1..00000000 --- a/scripts/genimage_syterboot_only.cfg +++ /dev/null @@ -1,15 +0,0 @@ -image sdcard.img { - hdimage {} - - partition boot0 { - in-partition-table = "no" - image = "syter_boot_bin.elf" - offset = 8K - } - - partition boot0-gpt { - in-partition-table = "no" - image = "syter_boot_bin.elf" - offset = 128K - } -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..642ba962 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,40 @@ +add_subdirectory(arch) +add_subdirectory(drivers) + +add_library(SyterKit + # Common + common.c + + # String + string.c + + # log + log/log.c + log/xformat.c + + # uart + uart.c + + # cli + cli/commands.c + cli/history.c + cli/lineedit.c + cli/parse.c + cli/shell.c + + # malloc + smalloc.c + + # stdlib + sstdlib.c + + # fdt + fdt_wrapper.c + + # ctype + ctype.c + + $ + $ + $ +) \ No newline at end of file diff --git a/src/arch/CMakeLists.txt b/src/arch/CMakeLists.txt new file mode 100644 index 00000000..8d3a7d9a --- /dev/null +++ b/src/arch/CMakeLists.txt @@ -0,0 +1,8 @@ + +if (CONFIG_ARCH_ARM32) + add_subdirectory(arm32) +endif() + +if (CONFIG_ARCH_RISCV64) + add_subdirectory(riscv64) +endif() \ No newline at end of file diff --git a/src/arch/arm32/CMakeLists.txt b/src/arch/arm32/CMakeLists.txt new file mode 100644 index 00000000..f63adfa7 --- /dev/null +++ b/src/arch/arm32/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(arch-obj OBJECT + exception.c + memcmp.S + memcpy.S + memset.S + strncmp.S + timer.c +) \ No newline at end of file diff --git a/docs/.nojekyll b/src/arch/arm32/arch.c similarity index 100% rename from docs/.nojekyll rename to src/arch/arm32/arch.c diff --git a/src/exception.c b/src/arch/arm32/exception.c similarity index 97% rename from src/exception.c rename to src/arch/arm32/exception.c index 008682a9..d61dd6cc 100644 --- a/src/exception.c +++ b/src/arch/arm32/exception.c @@ -5,8 +5,7 @@ #include #include -#include -#include +#include #include diff --git a/src/string/memcmp.S b/src/arch/arm32/memcmp.S similarity index 100% rename from src/string/memcmp.S rename to src/arch/arm32/memcmp.S diff --git a/src/string/memcpy.S b/src/arch/arm32/memcpy.S similarity index 100% rename from src/string/memcpy.S rename to src/arch/arm32/memcpy.S diff --git a/src/string/memset.S b/src/arch/arm32/memset.S similarity index 100% rename from src/string/memset.S rename to src/arch/arm32/memset.S diff --git a/src/string/strncmp.S b/src/arch/arm32/strncmp.S similarity index 100% rename from src/string/strncmp.S rename to src/arch/arm32/strncmp.S diff --git a/src/arch/arm32/timer.c b/src/arch/arm32/timer.c new file mode 100644 index 00000000..b5ce9284 --- /dev/null +++ b/src/arch/arm32/timer.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* + * 64bit arch timer.CNTPCT + * Freq = 24000000Hz + */ +uint64_t get_arch_counter(void) { + uint32_t low = 0, high = 0; + asm volatile("mrrc p15, 0, %0, %1, c14" + : "=r"(low), "=r"(high) + : + : "memory"); + return ((uint64_t) high << 32) | (uint64_t) low; +} + +/* + * get current time.(millisecond) + */ +uint32_t time_ms(void) { + return get_arch_counter() / 24000; +} + +/* + * get current time.(microsecond) + */ +uint64_t time_us(void) { + return get_arch_counter() / (uint64_t) 24; +} + +void udelay(uint64_t us) { + uint64_t now; + + now = time_us(); + while (time_us() - now < us) { + }; +} + +void mdelay(uint32_t ms) { + udelay(ms * 1000); + uint32_t now; + + now = time_ms(); + while (time_ms() - now < ms) { + }; +} + +void sdelay(uint32_t loops) { + __asm__ volatile( + "1:\n" // Define label 1 + "subs %0, %1, #1\n"// Subtract 1 from the loop count and store the result in the first operand + // If the loop count has become 0, exit the loop + "bne 1b" // Jump to label 1, i.e., the beginning of the loop + : "=r"(loops) // Output operand: update the loop count in the variable 'loops' + : "0"(loops) // Input operand: initialize the second operand with the value of 'loops' + : // No other registers are used or modified + ); +} diff --git a/src/arch/arm64/bin/rmr_switch.c b/src/arch/arm64/bin/rmr_switch.c new file mode 100644 index 00000000..3667fa0c --- /dev/null +++ b/src/arch/arm64/bin/rmr_switch.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +uint32_t rvbar0 = 0x017000a0; +uint32_t start_addr = 0x28000; + +/* + * First, it loads the value of rvbar0 into register r1, and the value of startAddr into register r0. + * Then, it stores the value in register r0 to the address pointed to by r1, + * which means storing startAddr to the MMIO mapped RVBAR[0] register. + * + * After that, it uses a data synchronization barrier (dsb) to ensure memory access completion, + * and an instruction synchronization barrier (isb) to ensure correct instruction execution order and prevent instruction reordering. + * + * Next, it reads the value of Register Maintenance Register (RMR) from co-processor CP15 into register r0, + * performs a bitwise OR operation between the value in register r0 and 0x3, setting the lowest two bits to 1, + * requesting a reset in AArch64 mode. Then, it writes the modified value to the RMR register in co-processor CP15, + * requesting a reset. It uses the instruction synchronization barrier again afterwards. + * + * Finally, it executes the Wait For Interrupt (WFI) instruction, + * waiting for an external event to wake up the system. It jumps back to the WFI instruction to continue waiting using an infinite loop. + */ +void rmr_switch(void) { + asm volatile( + "ldr r1, %[rvbar] \n" // Load the value of rvbar0 into register r1 + "ldr r0, %[start] \n" // Load the value of start_addr into register r0 + "str r0, [r1] \n" // Store the value in register r0 to the address pointed by r1, which means storing start_addr to MMIO mapped RVBAR[0] register + "dsb sy \n" // Data Synchronization Barrier to ensure memory access completion + "isb sy \n" // Instruction Synchronization Barrier to ensure correct instruction execution order and prevent instruction reordering + "mrc 15, 0, r0, cr12, cr0, 2 \n"// Read the value of Register Maintenance Register (RMR) from co-processor CP15 into register r0 + "orr r0, r0, #3 \n" // Perform a bitwise OR operation between the value in register r0 and 0x3, setting the lowest two bits to 1, requesting a reset in AArch64 mode + "mcr 15, 0, r0, cr12, cr0, 2 \n"// Write the value in register r0 to the RMR register in co-processor CP15, requesting a reset + "isb sy \n" // Use the instruction synchronization barrier again + "1: wfi \n" // Execute the Wait For Interrupt (WFI) instruction, waiting for an external event to wake up the system + "b 1b \n" // Jump back to the WFI instruction to continue waiting + : + : [rvbar] "m"(rvbar0), [start] "m"(start_addr) + : "r0", "r1"); +} \ No newline at end of file diff --git a/src/arch/riscv64/CMakeLists.txt b/src/arch/riscv64/CMakeLists.txt new file mode 100644 index 00000000..a674e56d --- /dev/null +++ b/src/arch/riscv64/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_library(arch-obj OBJECT + timer.c +) \ No newline at end of file diff --git a/src/arch/riscv64/memcpy.S b/src/arch/riscv64/memcpy.S new file mode 100644 index 00000000..7d045ee4 --- /dev/null +++ b/src/arch/riscv64/memcpy.S @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + + .global memcpy + .type memcpy, %function + .align 3 +memcpy: + move t6, a0 + sltiu a3, a2, 128 + bnez a3, 4f + andi a3, t6, REGSZ - 1 + andi a4, a1, REGSZ - 1 + bne a3, a4, 4f + beqz a3, 2f + andi a3, a1, ~(REGSZ - 1) + addi a3, a3, REGSZ + sub a4, a3, a1 +1: lb a5, 0(a1) + addi a1, a1, 1 + sb a5, 0(t6) + addi t6, t6, 1 + bltu a1, a3, 1b + sub a2, a2, a4 +2: andi a4, a2, ~((16 * REGSZ) - 1) + beqz a4, 4f + add a3, a1, a4 +3: LREG a4, 0(a1) + LREG a5, REGSZ(a1) + LREG a6, 2 * REGSZ(a1) + LREG a7, 3 * REGSZ(a1) + LREG t0, 4 * REGSZ(a1) + LREG t1, 5 * REGSZ(a1) + LREG t2, 6 * REGSZ(a1) + LREG t3, 7 * REGSZ(a1) + LREG t4, 8 * REGSZ(a1) + LREG t5, 9 * REGSZ(a1) + SREG a4, 0(t6) + SREG a5, REGSZ(t6) + SREG a6, 2 * REGSZ(t6) + SREG a7, 3 * REGSZ(t6) + SREG t0, 4 * REGSZ(t6) + SREG t1, 5 * REGSZ(t6) + SREG t2, 6 * REGSZ(t6) + SREG t3, 7 * REGSZ(t6) + SREG t4, 8 * REGSZ(t6) + SREG t5, 9 * REGSZ(t6) + LREG a4, 10 * REGSZ(a1) + LREG a5, 11 * REGSZ(a1) + LREG a6, 12 * REGSZ(a1) + LREG a7, 13 * REGSZ(a1) + LREG t0, 14 * REGSZ(a1) + LREG t1, 15 * REGSZ(a1) + addi a1, a1, 16 * REGSZ + SREG a4, 10 * REGSZ(t6) + SREG a5, 11 * REGSZ(t6) + SREG a6, 12 * REGSZ(t6) + SREG a7, 13 * REGSZ(t6) + SREG t0, 14 * REGSZ(t6) + SREG t1, 15 * REGSZ(t6) + addi t6, t6, 16 * REGSZ + bltu a1, a3, 3b + andi a2, a2, (16 * REGSZ) - 1 +4: beqz a2, 6f + add a3, a1, a2 + or a5, a1, t6 + or a5, a5, a3 + andi a5, a5, 3 + bnez a5, 5f +7: lw a4, 0(a1) + addi a1, a1, 4 + sw a4, 0(t6) + addi t6, t6, 4 + bltu a1, a3, 7b + ret +5: lb a4, 0(a1) + addi a1, a1, 1 + sb a4, 0(t6) + addi t6, t6, 1 + bltu a1, a3, 5b +6: ret \ No newline at end of file diff --git a/src/arch/riscv64/memset.S b/src/arch/riscv64/memset.S new file mode 100644 index 00000000..8660c60f --- /dev/null +++ b/src/arch/riscv64/memset.S @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + + .global memset + .type memset, %function + .align 3 +memset: + move t0, a0 + sltiu a3, a2, 16 + bnez a3, 4f + addi a3, t0, REGSZ - 1 + andi a3, a3, ~(REGSZ - 1) + beq a3, t0, 2f + sub a4, a3, t0 +1: sb a1, 0(t0) + addi t0, t0, 1 + bltu t0, a3, 1b + sub a2, a2, a4 +2: andi a1, a1, 0xff + slli a3, a1, 8 + or a1, a3, a1 + slli a3, a1, 16 + or a1, a3, a1 +#if __riscv_xlen == 64 + slli a3, a1, 32 + or a1, a3, a1 +#endif + andi a4, a2, ~(REGSZ - 1) + add a3, t0, a4 + andi a4, a4, 31 * REGSZ + beqz a4, 3f + neg a4, a4 + addi a4, a4, 32 * REGSZ + sub t0, t0, a4 + la a5, 3f +#if __riscv_xlen == 64 + srli a4, a4, 1 +#endif + add a5, a5, a4 + jr a5 +3: SREG a1, 0(t0) + SREG a1, REGSZ(t0) + SREG a1, 2 * REGSZ(t0) + SREG a1, 3 * REGSZ(t0) + SREG a1, 4 * REGSZ(t0) + SREG a1, 5 * REGSZ(t0) + SREG a1, 6 * REGSZ(t0) + SREG a1, 7 * REGSZ(t0) + SREG a1, 8 * REGSZ(t0) + SREG a1, 9 * REGSZ(t0) + SREG a1, 10 * REGSZ(t0) + SREG a1, 11 * REGSZ(t0) + SREG a1, 12 * REGSZ(t0) + SREG a1, 13 * REGSZ(t0) + SREG a1, 14 * REGSZ(t0) + SREG a1, 15 * REGSZ(t0) + SREG a1, 16 * REGSZ(t0) + SREG a1, 17 * REGSZ(t0) + SREG a1, 18 * REGSZ(t0) + SREG a1, 19 * REGSZ(t0) + SREG a1, 20 * REGSZ(t0) + SREG a1, 21 * REGSZ(t0) + SREG a1, 22 * REGSZ(t0) + SREG a1, 23 * REGSZ(t0) + SREG a1, 24 * REGSZ(t0) + SREG a1, 25 * REGSZ(t0) + SREG a1, 26 * REGSZ(t0) + SREG a1, 27 * REGSZ(t0) + SREG a1, 28 * REGSZ(t0) + SREG a1, 29 * REGSZ(t0) + SREG a1, 30 * REGSZ(t0) + SREG a1, 31 * REGSZ(t0) + addi t0, t0, 32 * REGSZ + bltu t0, a3, 3b + andi a2, a2, REGSZ - 1 +4: beqz a2, 6f + add a3, t0, a2 +5: sb a1, 0(t0) + addi t0, t0, 1 + bltu t0, a3, 5b +6: ret \ No newline at end of file diff --git a/drivers/sys-timer.c b/src/arch/riscv64/timer.c similarity index 61% rename from drivers/sys-timer.c rename to src/arch/riscv64/timer.c index 8dacb600..f8720528 100644 --- a/drivers/sys-timer.c +++ b/src/arch/riscv64/timer.c @@ -9,19 +9,21 @@ #include -#include "sys-timer.h" +#include /* * 64bit arch timer.CNTPCT * Freq = 24000000Hz */ uint64_t get_arch_counter(void) { - uint32_t low = 0, high = 0; - asm volatile("mrrc p15, 0, %0, %1, c14" - : "=r"(low), "=r"(high) + uint64_t cnt = 0; + + asm volatile("csrr %0, time\n" + : "=r"(cnt) : : "memory"); - return ((uint64_t) high << 32) | (uint64_t) low; + + return cnt; } /* @@ -56,9 +58,13 @@ void mdelay(uint32_t ms) { } void sdelay(uint32_t loops) { - __asm__ volatile("1:\n" - "subs %0, %1, #1\n" - "bne 1b" - : "=r"(loops) - : "0"(loops)); + asm volatile( + "mv t0, %0\n"// Move the 'loops' value to register t0 + "1:\n" + "addi t0, t0, -1\n"// Decrement t0 by 1 + "bnez t0, 1b\n" // Branch back to label 1 if t0 is not zero + : // No output operands + : "r"(loops) // Input operand: loops + : "t0" // Clobbered registers: t0 + ); } diff --git a/src/cache.S b/src/cache.S deleted file mode 100644 index c73db802..00000000 --- a/src/cache.S +++ /dev/null @@ -1,52 +0,0 @@ -.globl __v7_flush_dcache_all -__v7_flush_dcache_all: - dmb - mrc p15, 1, r0, c0, c0, 1 - mov r3, r0, lsr #23 - ands r3, r3, #14 - beq finished -start_flush_levels: - mov r10, #0 -flush_levels: - add r2, r10, r10, lsr #1 - mov r1, r0, lsr r2 - and r1, r1, #7 - cmp r1, #2 - blt skip - mcr p15, 2, r10, c0, c0, 0 - isb - mrc p15, 1, r1, c0, c0, 0 - and r2, r1, #7 - add r2, r2, #4 - movw r4, #1023 - ands r4, r4, r1, lsr #3 - clz r5, r4 - movw r7, #32767 - ands r7, r7, r1, lsr #13 -loop1: - mov r9, r7 -loop2: - orr r11, r10, r4, lsl r5 - orr r11, r11, r9, lsl r2 - mcr p15, 0, r11, c7, c14, 2 - subs r9, r9, #1 - bge loop2 - subs r4, r4, #1 - bge loop1 -skip: - add r10, r10, #2 - cmp r3, r10 - bgt flush_levels -finished: - mov r10, #0 - mcr p15, 2, r10, c0, c0, 0 - dsb st - isb - bx lr - -.globl v7_flush_dcache_all -v7_flush_dcache_all: - stmfd sp!, {r4-r7, r9-r11, lr} - bl __v7_flush_dcache_all - ldmfd sp!, {r4-r7, r9-r11, lr} - bx lr diff --git a/src/cli/commands.c b/src/cli/commands.c index 6d610ecd..1e9e6931 100644 --- a/src/cli/commands.c +++ b/src/cli/commands.c @@ -7,8 +7,6 @@ #include #include -#include - #include "cli.h" #include "cli_config.h" #include "cli_history.h" diff --git a/src/cli/lineedit.c b/src/cli/lineedit.c index 2a443353..bd4b9ded 100644 --- a/src/cli/lineedit.c +++ b/src/cli/lineedit.c @@ -1,12 +1,13 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include #include #include +#include "ctype.h" + #include "cli_history.h" #include "cli_termesc.h" diff --git a/src/cli/parse.c b/src/cli/parse.c index 9eda3e0a..c332d7d7 100644 --- a/src/cli/parse.c +++ b/src/cli/parse.c @@ -137,59 +137,59 @@ const char *msh_parse_line(const char *cmdline, char *argvbuf, int *pargc, char if (ret < 0) { return NULL; } else - /* + /* * No more chars to read. Case I */ - if (ret == 0) { - switch (*(state.readpos)) { - case '\0': - return cmdline; - case MSH_CMD_SEP_CHAR: - return (state.readpos + 1); - default: - uart_puts("Fatal error in parse() \n"); - return NULL; + if (ret == 0) { + switch (*(state.readpos)) { + case '\0': + return cmdline; + case MSH_CMD_SEP_CHAR: + return (state.readpos + 1); + default: + uart_puts("Fatal error in parse() \n"); + return NULL; + } } - } - /* + /* * Normal */ - else { - (*pargc)++; - char stopchar = *(state.readpos); - /* + else { + (*pargc)++; + char stopchar = *(state.readpos); + /* * No more chars to read. Case II */ - if (stopchar == '\0') { - return cmdline; - } + if (stopchar == '\0') { + return cmdline; + } - /* + /* * End of command by ';'. * Tell the caller where to restart. */ - if (stopchar == MSH_CMD_SEP_CHAR) { - state.readpos++; /* skip ';' */ - return (state.readpos); - } + if (stopchar == MSH_CMD_SEP_CHAR) { + state.readpos++; /* skip ';' */ + return (state.readpos); + } - /* + /* * read_token() stoped by a argument separator. */ - else if (isspace((unsigned) stopchar)) { - argv[*pargc] = state.writepos; - continue; - } + else if (isspace((unsigned) stopchar)) { + argv[*pargc] = state.writepos; + continue; + } - /* + /* * Can't be!! */ - else { - uart_puts("Fatal error in parse() "); - return NULL; + else { + uart_puts("Fatal error in parse() "); + return NULL; + } } - } } /* Tell the caller that whole line has processed */ diff --git a/src/common.c b/src/common.c index 5d12be7d..14b72f16 100644 --- a/src/common.c +++ b/src/common.c @@ -1,87 +1,10 @@ /* SPDX-License-Identifier: Apache-2.0 */ - -#include #include #include #include - -#include - -#include -#include - -void clean_syterkit_data(void) { - /* Disable MMU, data cache, instruction cache, interrupts */ - arm32_mmu_disable(); - printk(LOG_LEVEL_INFO, "disable mmu ok...\n"); - arm32_dcache_disable(); - printk(LOG_LEVEL_INFO, "disable dcache ok...\n"); - arm32_icache_disable(); - printk(LOG_LEVEL_INFO, "disable icache ok...\n"); - arm32_interrupt_disable(); - printk(LOG_LEVEL_INFO, "free interrupt ok...\n"); -} - -void rtc_set_vccio_det_spare(void) { - u32 val = 0; - val = readl(SUNXI_RTC_BASE + 0x1f4); - val &= ~(0xff << 4); - val |= (VCCIO_THRESHOLD_VOLTAGE_2_9 | FORCE_DETECTER_OUTPUT); - val &= ~VCCIO_DET_BYPASS_EN; - writel(val, SUNXI_RTC_BASE + 0x1f4); -} - -void sys_ldo_check(void) { - uint32_t reg_val = 0; - uint32_t roughtrim_val = 0, finetrim_val = 0; - - /* reset */ - reg_val = readl(CCU_AUDIO_CODEC_BGR_REG); - reg_val &= ~(1 << 16); - writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); - - sdelay(2); - - reg_val |= (1 << 16); - writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); - - /* enable AUDIO gating */ - reg_val = readl(CCU_AUDIO_CODEC_BGR_REG); - reg_val |= (1 << 0); - writel(reg_val, CCU_AUDIO_CODEC_BGR_REG); - - /* enable pcrm CTRL */ - reg_val = readl(ANA_PWR_RST_REG); - reg_val &= ~(1 << 0); - writel(reg_val, ANA_PWR_RST_REG); - - /* read efuse */ - printk(LOG_LEVEL_DEBUG, "Audio: avcc calibration\n"); - reg_val = readl(SUNXI_SID_SRAM_BASE + 0x28); - roughtrim_val = (reg_val >> 0) & 0xF; - reg_val = readl(SUNXI_SID_SRAM_BASE + 0x24); - finetrim_val = (reg_val >> 16) & 0xFF; - - if (roughtrim_val == 0 && finetrim_val == 0) { - reg_val = readl(SUNXI_VER_REG); - reg_val = (reg_val >> 0) & 0x7; - if (reg_val) { - printk(LOG_LEVEL_DEBUG, "Audio: chip not version A\n"); - } else { - roughtrim_val = 0x5; - finetrim_val = 0x19; - printk(LOG_LEVEL_DEBUG, "Audio: chip version A\n"); - } - } - reg_val = readl(AUDIO_POWER_REG); - reg_val &= ~(0xF << 8 | 0xFF); - reg_val |= roughtrim_val << 8 | finetrim_val; - writel(reg_val, AUDIO_POWER_REG); -} +#include void show_banner(void) { - uint32_t id[4]; - printk(LOG_LEVEL_MUTE, "\n"); printk(LOG_LEVEL_INFO, " _____ _ _____ _ _ \n"); printk(LOG_LEVEL_INFO, "| __|_ _| |_ ___ ___| | |_| |_ \n"); @@ -89,15 +12,8 @@ void show_banner(void) { printk(LOG_LEVEL_INFO, "|_____|_ |_| |___|_| |__|__|_|_| \n"); printk(LOG_LEVEL_INFO, " |___| \n"); printk(LOG_LEVEL_INFO, "***********************************\n"); - printk(LOG_LEVEL_INFO, " %s V0.1.2 Commit: %s\n", PROJECT_NAME, PROJECT_GIT_HASH); + printk(LOG_LEVEL_INFO, " %s V0.2.0 Commit: %s\n", PROJECT_NAME, PROJECT_GIT_HASH); printk(LOG_LEVEL_INFO, " Built by: %s\n", PROJECT_C_COMPILER); printk(LOG_LEVEL_INFO, "***********************************\n"); printk(LOG_LEVEL_INFO, "\n"); - - id[0] = read32(0x03006200 + 0x0); - id[1] = read32(0x03006200 + 0x4); - id[2] = read32(0x03006200 + 0x8); - id[3] = read32(0x03006200 + 0xc); - - printk(LOG_LEVEL_INFO, "Chip ID is: %08x%08x%08x%08x\n", id[0], id[1], id[2], id[3]); } diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt new file mode 100644 index 00000000..09e014e4 --- /dev/null +++ b/src/drivers/CMakeLists.txt @@ -0,0 +1,17 @@ +if (CONFIG_CHIP_SUN8IW21) + add_subdirectory(sun8iw21) +elseif(CONFIG_CHIP_SUN8IW20) + add_subdirectory(sun8iw20) +endif() + +add_library(drivers-obj OBJECT + sys-uart.c + sys-gpio.c + sys-rtc.c + sys-spi-nand.c + sys-spi.c + sys-sdcard.c + sys-sdhci.c + sys-dma.c + sys-i2c.c +) \ No newline at end of file diff --git a/src/drivers/sun8iw20/CMakeLists.txt b/src/drivers/sun8iw20/CMakeLists.txt new file mode 100644 index 00000000..41d913f5 --- /dev/null +++ b/src/drivers/sun8iw20/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(chip_drivers-obj OBJECT + sys-clk.c + sys-sid.c + sys-wdt.c + sys-dram.c + sys-rproc.c +) \ No newline at end of file diff --git a/src/drivers/sun8iw20/sys-clk.c b/src/drivers/sun8iw20/sys-clk.c new file mode 100644 index 00000000..c8def714 --- /dev/null +++ b/src/drivers/sun8iw20/sys-clk.c @@ -0,0 +1,297 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +void set_pll_cpux_axi(void) { + uint32_t val; + + /* AXI: Select cpu clock src to PLL_PERI(1x) */ + write32(CCU_BASE + CCU_CPU_AXI_CFG_REG, (4 << 24) | (1 << 0)); + sdelay(10); + + /* Disable pll gating */ + val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + val &= ~(1 << 27); + write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val); + + /* Enable pll ldo */ + val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + val |= (1 << 30); + write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val); + sdelay(5); + + /* Set clk to 1008mhz (default) or CONFIG_CPU_FREQ */ + /* PLL_CPUX = 24 MHz*N/P */ + val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + val &= ~((0x3 << 16) | (0xff << 8) | (0x3 << 0)); + val |= (41 << 8); + write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val); + + /* Lock enable */ + val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + val |= (1 << 29); + write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val); + + /* Enable pll */ + val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + val |= (1 << 31); + write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val); + + /* Wait pll stable */ + while (!(read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG) & (0x1 << 28))) + ; + sdelay(20); + + /* Enable pll gating */ + val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + val |= (1 << 27); + write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val); + + /* Lock disable */ + val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + val &= ~(1 << 29); + write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val); + sdelay(1); + + /* AXI: set and change cpu clk src to PLL_CPUX, PLL_CPUX:AXI0 = 1200MHz:600MHz */ + val = read32(CCU_BASE + CCU_CPU_AXI_CFG_REG); + val &= ~(0x07 << 24 | 0x3 << 16 | 0x3 << 8 | 0xf << 0);// Clear + val |= (0x03 << 24 | 0x0 << 16 | 0x1 << 8 | 0x1 << 0); // CLK_SEL=PLL_CPU/P, DIVP=0, DIV2=1, DIV1=1 + write32(CCU_BASE + CCU_CPU_AXI_CFG_REG, val); + sdelay(1); +} + +static void set_pll_periph0(void) { + uint32_t val; + + /* Periph0 has been enabled */ + if (read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG) & (1 << 31)) + return; + + /* Set default val */ + write32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG, 0x63 << 8); + + /* Lock enable */ + val = read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG); + val |= (1 << 29); + write32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG, val); + + /* Enabe pll 600m(1x) 1200m(2x) */ + val = read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG); + val |= (1 << 31); + write32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG, val); + + /* Wait pll stable */ + while (!(read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG) & (0x1 << 28))) + ; + sdelay(20); + + /* Lock disable */ + val = read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG); + val &= ~(1 << 29); + write32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG, val); +} + +static void set_ahb(void) { + write32(CCU_BASE + CCU_PSI_CLK_REG, (2 << 0) | (0 << 8) | (0x03 << 24)); + sdelay(1); +} + +static void set_apb(void) { + write32(CCU_BASE + CCU_APB0_CLK_REG, (2 << 0) | (1 << 8) | (0x03 << 24)); + sdelay(1); +} + +static void set_dma(void) { + /* Dma reset */ + write32(CCU_BASE + CCU_DMA_BGR_REG, read32(CCU_BASE + CCU_DMA_BGR_REG) | (1 << 16)); + sdelay(20); + /* Enable gating clock for dma */ + write32(CCU_BASE + CCU_DMA_BGR_REG, read32(CCU_BASE + CCU_DMA_BGR_REG) | (1 << 0)); +} + +static void set_mbus(void) { + uint32_t val; + + /* Reset mbus domain */ + val = read32(CCU_BASE + CCU_MBUS_CLK_REG); + val |= (0x1 << 30); + write32(CCU_BASE + CCU_MBUS_CLK_REG, val); + sdelay(1); + + /* Enable mbus master clock gating */ + write32(CCU_BASE + CCU_MBUS_MAT_CLK_GATING_REG, 0x00000d87); +} + +static void set_module(virtual_addr_t addr) { + uint32_t val; + + if (!(read32(addr) & (1 << 31))) { + val = read32(addr); + write32(addr, val | (1 << 31) | (1 << 30)); + + /* Lock enable */ + val = read32(addr); + val |= (1 << 29); + write32(addr, val); + + /* Wait pll stable */ + while (!(read32(addr) & (0x1 << 28))) + ; + sdelay(20); + + /* Lock disable */ + val = read32(addr); + val &= ~(1 << 29); + write32(addr, val); + } +} + +void sunxi_clk_init(void) { + set_pll_cpux_axi(); + set_pll_periph0(); + set_ahb(); + set_apb(); + set_dma(); + set_mbus(); + set_module(CCU_BASE + CCU_PLL_PERI0_CTRL_REG); + set_module(CCU_BASE + CCU_PLL_VIDEO0_CTRL_REG); + set_module(CCU_BASE + CCU_PLL_VIDEO1_CTRL_REG); + set_module(CCU_BASE + CCU_PLL_VE_CTRL); + set_module(CCU_BASE + CCU_PLL_AUDIO0_CTRL_REG); + set_module(CCU_BASE + CCU_PLL_AUDIO1_CTRL_REG); +} + +void sunxi_clk_reset(void) { + uint32_t reg_val; + + /*set ahb,apb to default, use OSC24M*/ + reg_val = readl(CCU_BASE + CCU_PSI_CLK_REG); + reg_val &= (~((0x3 << 24) | (0x3 << 8) | (0x3))); + writel(reg_val, CCU_BASE + CCU_PSI_CLK_REG); + + reg_val = readl(CCU_BASE + CCU_APB0_CLK_REG); + reg_val &= (~((0x3 << 24) | (0x3 << 8) | (0x3))); + writel(reg_val, CCU_BASE + CCU_APB0_CLK_REG); + + /*set cpux pll to default,use OSC24M*/ + writel(0x0301, CCU_BASE + CCU_CPU_AXI_CFG_REG); + return; +} + +uint32_t sunxi_clk_get_peri1x_rate() { + uint32_t reg32; + uint8_t plln, pllm, p0; + + /* PLL PERIx */ + reg32 = read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG); + if (reg32 & (1 << 31)) { + plln = ((reg32 >> 8) & 0xff) + 1; + pllm = (reg32 & 0x01) + 1; + p0 = ((reg32 >> 16) & 0x03) + 1; + + return ((((24 * plln) / (pllm * p0)) >> 1) * 1000 * 1000); + } + + return 0; +} + +void sunxi_clk_dump() { + uint32_t reg32; + uint32_t cpu_clk_src; + uint32_t plln, pllm; + uint8_t p0; + uint8_t p1; + const char *clock_str; + + /* PLL CPU */ + reg32 = read32(CCU_BASE + CCU_CPU_AXI_CFG_REG); + cpu_clk_src = (reg32 >> 24) & 0x7; + + switch (cpu_clk_src) { + case 0x0: + clock_str = "OSC24M"; + break; + + case 0x1: + clock_str = "CLK32"; + break; + + case 0x2: + clock_str = "CLK16M_RC"; + break; + + case 0x3: + clock_str = "PLL_CPU"; + break; + + case 0x4: + clock_str = "PLL_PERI(1X)"; + break; + + case 0x5: + clock_str = "PLL_PERI(2X)"; + break; + + case 0x6: + clock_str = "PLL_PERI(800M)"; + break; + + default: + clock_str = "ERROR"; + } + + reg32 = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG); + p0 = (reg32 >> 16) & 0x03; + if (p0 == 0) { + p1 = 1; + } else if (p0 == 1) { + p1 = 2; + } else if (p0 == 2) { + p1 = 4; + } else { + p1 = 1; + } + + printk(LOG_LEVEL_DEBUG, "CLK: CPU PLL=%s FREQ=%" PRIu32 "MHz\r\n", clock_str, ((((reg32 >> 8) & 0xff) + 1) * 24 / p1)); + + /* PLL PERIx */ + reg32 = read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG); + if (reg32 & (1 << 31)) { + plln = ((reg32 >> 8) & 0xff) + 1; + pllm = (reg32 & 0x01) + 1; + p0 = ((reg32 >> 16) & 0x03) + 1; + p1 = ((reg32 >> 20) & 0x03) + 1; + + printk(LOG_LEVEL_DEBUG, "CLK: PLL_peri (2X)=%" PRIu32 "MHz, (1X)=%" PRIu32 "MHz, (800M)=%" PRIu32 "MHz\r\n", (24 * plln) / (pllm * p0), + (24 * plln) / (pllm * p0) >> 1, (24 * plln) / (pllm * p1)); + } else { + printk(LOG_LEVEL_DEBUG, "CLK: PLL_peri disabled\r\n"); + } + + /* PLL DDR */ + reg32 = read32(CCU_BASE + CCU_PLL_DDR_CTRL_REG); + if (reg32 & (1 << 31)) { + plln = ((reg32 >> 8) & 0xff) + 1; + + pllm = (reg32 & 0x01) + 1; + p1 = ((reg32 >> 1) & 0x1) + 1; + p0 = (reg32 & 0x01) + 1; + + printk(LOG_LEVEL_DEBUG, "CLK: PLL_ddr=%" PRIu32 "MHz\r\n", (24 * plln) / (p0 * p1)); + + } else { + printk(LOG_LEVEL_DEBUG, "CLK: PLL_ddr disabled\r\n"); + } +} \ No newline at end of file diff --git a/src/drivers/sun8iw20/sys-dram.c b/src/drivers/sun8iw20/sys-dram.c new file mode 100644 index 00000000..41b03091 --- /dev/null +++ b/src/drivers/sun8iw20/sys-dram.c @@ -0,0 +1,1385 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#define DIV_ROUND_UP(a, b) (((a) + (b) -1) / (b)) + +#define CONFIG_SYS_SDRAM_BASE SDRAM_BASE + +#ifndef SUNXI_SID_BASE +#define SUNXI_SID_BASE 0x3006200 +#endif + +static int ns_to_t(dram_para_t *para, int nanoseconds) { + const unsigned int ctrl_freq = para->dram_clk / 2; + + return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000); +} + +static void sid_read_ldoB_cal(dram_para_t *para) { + uint32_t reg; + + reg = (readl(SYS_SID_BASE + SYS_LDOB_SID) & 0xff00) >> 8; + + if (reg == 0) + return; + + switch (para->dram_type) { + case SUNXI_DRAM_TYPE_DDR2: + break; + case SUNXI_DRAM_TYPE_DDR3: + if (reg > 0x20) + reg -= 0x16; + break; + default: + reg = 0; + break; + } + + clrsetbits_le32((SYS_CONTROL_REG_BASE + LDO_CTAL_REG), 0xff00, reg << 8); +} + +static void dram_voltage_set(dram_para_t *para) { + int vol; + + switch (para->dram_type) { + case SUNXI_DRAM_TYPE_DDR2: + vol = 47; + break; + case SUNXI_DRAM_TYPE_DDR3: + vol = 25; + break; + default: + vol = 0; + break; + } + + clrsetbits_le32((SYS_CONTROL_REG_BASE + LDO_CTAL_REG), 0x20ff00, vol << 8); + + udelay(1); + + sid_read_ldoB_cal(para); +} + +static void dram_enable_all_master(void) { + writel(~0, (MCTL_COM_BASE + MCTL_COM_MAER0)); + writel(0xff, (MCTL_COM_BASE + MCTL_COM_MAER1)); + writel(0xffff, (MCTL_COM_BASE + MCTL_COM_MAER2)); + udelay(10); +} + +static void dram_disable_all_master(void) { + writel(1, (MCTL_COM_BASE + MCTL_COM_MAER0)); + writel(0, (MCTL_COM_BASE + MCTL_COM_MAER1)); + writel(0, (MCTL_COM_BASE + MCTL_COM_MAER2)); + udelay(10); +} + +static void eye_delay_compensation(dram_para_t *para)// s1 +{ + uint32_t delay, i = 0; + + // DATn0IOCR, n = 0...7 + delay = (para->dram_tpr11 & 0xf) << 9; + delay |= (para->dram_tpr12 & 0xf) << 1; + + for (i = 0; i < 9; i++) + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DATX0IOCR(i)), delay); + + // DATn1IOCR, n = 0...7 + delay = (para->dram_tpr11 & 0xf0) << 5; + delay |= (para->dram_tpr12 & 0xf0) >> 3; + for (i = 0; i < 9; i++) + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DATX1IOCR(i)), delay); + + // PGCR0: assert AC loopback FIFO reset + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR0), 0x04000000); + + // DQS0 read and write delay + delay = (para->dram_tpr11 & 0xf0000) >> 7; + delay |= (para->dram_tpr12 & 0xf0000) >> 15; + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DATX0IOCR(9)), delay); // DQS0 P + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DATX0IOCR(10)), delay);// DQS0 N + + // DQS1 read and write delay + delay = (para->dram_tpr11 & 0xf00000) >> 11; + delay |= (para->dram_tpr12 & 0xf00000) >> 19; + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DATX1IOCR(9)), delay); // DQS1 P + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DATX1IOCR(10)), delay);// DQS1 N + + // DQS0 enable bit delay + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXnSDLR6(0)), (para->dram_tpr11 & 0xf0000) << 9); + + // DQS1 enable bit delay + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXnSDLR6(1)), (para->dram_tpr11 & 0xf00000) << 5); + + // PGCR0: release AC loopback FIFO reset + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR0), (1 << 26)); + + udelay(1); + + delay = (para->dram_tpr10 & 0xf0) << 4; + + // Set RAS CAS and CA delay + for (i = 6; i < 27; ++i) + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_ACIOCR1(i)), delay); + + // Set CK CS delay + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_ACIOCR1(2)), (para->dram_tpr10 & 0x0f) << 8); + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_ACIOCR1(3)), (para->dram_tpr10 & 0x0f) << 8); + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_ACIOCR1(28)), (para->dram_tpr10 & 0xf00) >> 4); +} + +/* + * Main purpose of the auto_set_timing routine seems to be to calculate all + * timing settings for the specific type of sdram used. Read together with + * an sdram datasheet for context on the various variables. + */ +static void mctl_set_timing_params(dram_para_t *para) { + /* DRAM_TPR0 */ + u8 tccd = 2; + u8 tfaw; + u8 trrd; + u8 trcd; + u8 trc; + + /* DRAM_TPR1 */ + u8 txp; + u8 twtr; + u8 trtp = 4; + u8 twr; + u8 trp; + u8 tras; + + /* DRAM_TPR2 */ + u16 trefi; + u16 trfc; + + u8 tcksrx; + u8 tckesr; + u8 trd2wr; + u8 twr2rd; + u8 trasmax; + u8 twtp; + u8 tcke; + u8 tmod; + u8 tmrd; + u8 tmrw; + + u8 tcl; + u8 tcwl; + u8 t_rdata_en; + u8 wr_latency; + + u32 mr0; + u32 mr1; + u32 mr2; + u32 mr3; + + u32 tdinit0; + u32 tdinit1; + u32 tdinit2; + u32 tdinit3; + + switch (para->dram_type) { + case SUNXI_DRAM_TYPE_DDR2: + /* DRAM_TPR0 */ + tfaw = ns_to_t(para, 50); + trrd = ns_to_t(para, 10); + trcd = ns_to_t(para, 20); + trc = ns_to_t(para, 65); + + /* DRAM_TPR1 */ + txp = 2; + twtr = ns_to_t(para, 8); + twr = ns_to_t(para, 15); + trp = ns_to_t(para, 15); + tras = ns_to_t(para, 45); + + /* DRAM_TRP2 */ + trfc = ns_to_t(para, 328); + trefi = ns_to_t(para, 7800) / 32; + + trasmax = para->dram_clk / 30; + if (para->dram_clk < 409) { + t_rdata_en = 1; + tcl = 3; + mr0 = 0x06a3; + } else { + t_rdata_en = 2; + tcl = 4; + mr0 = 0x0e73; + } + tmrd = 2; + twtp = twr + 5; + tcksrx = 5; + tckesr = 4; + trd2wr = 4; + tcke = 3; + tmod = 12; + wr_latency = 1; + tmrw = 0; + twr2rd = twtr + 5; + tcwl = 0; + + mr1 = para->dram_mr1; + mr2 = 0; + mr3 = 0; + + tdinit0 = 200 * para->dram_clk + 1; + tdinit1 = 100 * para->dram_clk / 1000 + 1; + tdinit2 = 200 * para->dram_clk + 1; + tdinit3 = 1 * para->dram_clk + 1; + + break; + case SUNXI_DRAM_TYPE_DDR3: + trfc = ns_to_t(para, 350); + trefi = ns_to_t(para, 7800) / 32 + 1;// XXX + + twtr = ns_to_t(para, 8) + 2;// + 2 ? XXX + /* Only used by trd2wr calculation, which gets discard below */ + // twr = max(ns_to_t(para, 15), 2); + trrd = max(ns_to_t(para, 10), 2); + txp = max(ns_to_t(para, 10), 2); + + if (para->dram_clk <= 800) { + tfaw = ns_to_t(para, 50); + trcd = ns_to_t(para, 15); + trp = ns_to_t(para, 15); + trc = ns_to_t(para, 53); + tras = ns_to_t(para, 38); + + mr0 = 0x1c70; + mr2 = 0x18; + tcl = 6; + wr_latency = 2; + tcwl = 4; + t_rdata_en = 4; + } else { + tfaw = ns_to_t(para, 35); + trcd = ns_to_t(para, 14); + trp = ns_to_t(para, 14); + trc = ns_to_t(para, 48); + tras = ns_to_t(para, 34); + + mr0 = 0x1e14; + mr2 = 0x20; + tcl = 7; + wr_latency = 3; + tcwl = 5; + t_rdata_en = 5; + } + + trasmax = para->dram_clk / 30; + twtp = tcwl + 2 + twtr;// WL+BL/2+tWTR + /* Gets overwritten below */ + // trd2wr = tcwl + 2 + twr; // WL+BL/2+tWR + twr2rd = tcwl + twtr;// WL+tWTR + + tdinit0 = 500 * para->dram_clk + 1; // 500 us + tdinit1 = 360 * para->dram_clk / 1000 + 1;// 360 ns + tdinit2 = 200 * para->dram_clk + 1; // 200 us + tdinit3 = 1 * para->dram_clk + 1; // 1 us + + mr1 = para->dram_mr1; + mr3 = 0; + tcke = 3; + tcksrx = 5; + tckesr = 4; + if (((para->dram_tpr13 & 0xc) == 0x04) || para->dram_clk < 912) + trd2wr = 5; + else + trd2wr = 6; + + tmod = 12; + tmrd = 4; + tmrw = 0; + + break; + case SUNXI_DRAM_TYPE_LPDDR2: + tfaw = max(ns_to_t(para, 50), 4); + trrd = max(ns_to_t(para, 10), 1); + trcd = max(ns_to_t(para, 24), 2); + trc = ns_to_t(para, 70); + txp = ns_to_t(para, 8); + if (txp < 2) { + txp++; + twtr = 2; + } else { + twtr = txp; + } + twr = max(ns_to_t(para, 15), 2); + trp = ns_to_t(para, 17); + tras = ns_to_t(para, 42); + trefi = ns_to_t(para, 3900) / 32; + trfc = ns_to_t(para, 210); + + trasmax = para->dram_clk / 60; + mr3 = para->dram_mr3; + twtp = twr + 5; + mr2 = 6; + mr1 = 5; + tcksrx = 5; + tckesr = 5; + trd2wr = 10; + tcke = 2; + tmod = 5; + tmrd = 5; + tmrw = 3; + tcl = 4; + wr_latency = 1; + t_rdata_en = 1; + + tdinit0 = 200 * para->dram_clk + 1; + tdinit1 = 100 * para->dram_clk / 1000 + 1; + tdinit2 = 11 * para->dram_clk + 1; + tdinit3 = 1 * para->dram_clk + 1; + twr2rd = twtr + 5; + tcwl = 2; + mr1 = 195; + mr0 = 0; + + break; + case SUNXI_DRAM_TYPE_LPDDR3: + tfaw = max(ns_to_t(para, 50), 4); + trrd = max(ns_to_t(para, 10), 1); + trcd = max(ns_to_t(para, 24), 2); + trc = ns_to_t(para, 70); + twtr = max(ns_to_t(para, 8), 2); + twr = max(ns_to_t(para, 15), 2); + trp = ns_to_t(para, 17); + tras = ns_to_t(para, 42); + trefi = ns_to_t(para, 3900) / 32; + trfc = ns_to_t(para, 210); + txp = twtr; + + trasmax = para->dram_clk / 60; + if (para->dram_clk < 800) { + tcwl = 4; + wr_latency = 3; + t_rdata_en = 6; + mr2 = 12; + } else { + tcwl = 3; + tcke = 6; + wr_latency = 2; + t_rdata_en = 5; + mr2 = 10; + } + twtp = tcwl + 5; + tcl = 7; + mr3 = para->dram_mr3; + tcksrx = 5; + tckesr = 5; + trd2wr = 13; + tcke = 3; + tmod = 12; + tdinit0 = 400 * para->dram_clk + 1; + tdinit1 = 500 * para->dram_clk / 1000 + 1; + tdinit2 = 11 * para->dram_clk + 1; + tdinit3 = 1 * para->dram_clk + 1; + tmrd = 5; + tmrw = 5; + twr2rd = tcwl + twtr + 5; + mr1 = 195; + mr0 = 0; + + break; + default: + trfc = 128; + trp = 6; + trefi = 98; + txp = 10; + twr = 8; + twtr = 3; + tras = 14; + tfaw = 16; + trc = 20; + trcd = 6; + trrd = 3; + + twr2rd = 8; // 48(sp) + tcksrx = 4; // t1 + tckesr = 3; // t4 + trd2wr = 4; // t6 + trasmax = 27; // t3 + twtp = 12; // s6 + tcke = 2; // s8 + tmod = 6; // t0 + tmrd = 2; // t5 + tmrw = 0; // a1 + tcwl = 3; // a5 + tcl = 3; // a0 + wr_latency = 1;// a7 + t_rdata_en = 1;// a4 + mr3 = 0; // s0 + mr2 = 0; // t2 + mr1 = 0; // s1 + mr0 = 0; // a3 + tdinit3 = 0; // 40(sp) + tdinit2 = 0; // 32(sp) + tdinit1 = 0; // 24(sp) + tdinit0 = 0; // 16(sp) + + break; + } + + /* Set mode registers */ + writel(mr0, (MCTL_PHY_BASE + MCTL_PHY_DRAM_MR0)); + writel(mr1, (MCTL_PHY_BASE + MCTL_PHY_DRAM_MR1)); + writel(mr2, (MCTL_PHY_BASE + MCTL_PHY_DRAM_MR2)); + writel(mr3, (MCTL_PHY_BASE + MCTL_PHY_DRAM_MR3)); + /* TODO: dram_odt_en is either 0x0 or 0x1, so right shift looks weird */ + writel((para->dram_odt_en >> 4) & 0x3, (MCTL_PHY_BASE + MCTL_PHY_LP3MR11)); + + /* Set dram timing DRAMTMG0 - DRAMTMG5 */ + writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0), (MCTL_PHY_BASE + MCTL_PHY_DRAMTMG0)); + writel((txp << 16) | (trtp << 8) | (trc << 0), (MCTL_PHY_BASE + MCTL_PHY_DRAMTMG1)); + writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0), (MCTL_PHY_BASE + MCTL_PHY_DRAMTMG2)); + writel((tmrw << 16) | (tmrd << 12) | (tmod << 0), (MCTL_PHY_BASE + MCTL_PHY_DRAMTMG3)); + writel((trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0), (MCTL_PHY_BASE + MCTL_PHY_DRAMTMG4)); + writel((tcksrx << 24) | (tcksrx << 16) | (tckesr << 8) | (tcke << 0), (MCTL_PHY_BASE + MCTL_PHY_DRAMTMG5)); + + /* Set dual rank timing */ + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DRAMTMG8), 0xf000ffff, (para->dram_clk < 800) ? 0xf0006610 : 0xf0007610); + + /* Set phy interface time PITMG0, PTR3, PTR4 */ + writel((0x2 << 24) | (t_rdata_en << 16) | (1 << 8) | (wr_latency << 0), (MCTL_PHY_BASE + MCTL_PHY_PITMG0)); + writel(((tdinit0 << 0) | (tdinit1 << 20)), (MCTL_PHY_BASE + MCTL_PHY_PTR3)); + writel(((tdinit2 << 0) | (tdinit3 << 20)), (MCTL_PHY_BASE + MCTL_PHY_PTR4)); + + /* Set refresh timing and mode */ + writel((trefi << 16) | (trfc << 0), (MCTL_PHY_BASE + MCTL_PHY_RFSHTMG)); + writel((trefi << 15) & 0x0fff0000, (MCTL_PHY_BASE + MCTL_PHY_RFSHCTL1)); +} + +// Purpose of this routine seems to be to initialize the PLL driving +// the MBUS and sdram. +// +static int ccu_set_pll_ddr_clk(int index, dram_para_t *para) { + unsigned int val, clk, n; + + if (para->dram_tpr13 & (1 << 6)) + clk = para->dram_tpr9; + else + clk = para->dram_clk; + + // set VCO clock divider + n = (clk * 2) / 24; + + val = readl((CCU_BASE + CCU_PLL_DDR_CTRL_REG)); + val &= 0xfff800fc; // clear dividers + val |= (n - 1) << 8;// set PLL division + val |= 0xc0000000; // enable PLL and LDO + val &= 0xdfffffff; + writel(val | 0x20000000, (CCU_BASE + CCU_PLL_DDR_CTRL_REG)); + + // wait for PLL to lock + while ((readl((CCU_BASE + CCU_PLL_DDR_CTRL_REG)) & 0x10000000) == 0) { + ; + } + + udelay(20); + + // enable PLL output + val = readl(CCU_BASE); + val |= 0x08000000; + writel(val, CCU_BASE); + + // turn clock gate on + val = readl((CCU_BASE + CCU_DRAM_CLK_REG)); + val &= 0xfcfffcfc;// select DDR clk source, n=1, m=1 + val |= 0x80000000;// turn clock on + writel(val, (CCU_BASE + CCU_DRAM_CLK_REG)); + + return n * 24; +} + +// Main purpose of sys_init seems to be to initalise the clocks for +// the sdram controller. +// +static void mctl_sys_init(dram_para_t *para) { + // assert MBUS reset + clrbits_le32((CCU_BASE + CCU_MBUS_CLK_REG), (1 << 30)); + + // turn off sdram clock gate, assert sdram reset + clrbits_le32((CCU_BASE + CCU_DRAM_BGR_REG), 0x10001); + clrsetbits_le32((CCU_BASE + CCU_DRAM_CLK_REG), (1 << 31) | (1 << 30), (1 << 27)); + udelay(10); + + // set ddr pll clock + para->dram_clk = ccu_set_pll_ddr_clk(0, para) / 2; + udelay(100); + dram_disable_all_master(); + + // release sdram reset + setbits_le32((CCU_BASE + CCU_DRAM_BGR_REG), (1 << 16)); + + // release MBUS reset + setbits_le32((CCU_BASE + CCU_MBUS_CLK_REG), (1 << 30)); + setbits_le32((CCU_BASE + CCU_DRAM_CLK_REG), (1 << 30)); + + udelay(5); + + // turn on sdram clock gate + setbits_le32((CCU_BASE + CCU_DRAM_BGR_REG), (1 << 0)); + + // turn dram clock gate on, trigger sdr clock update + setbits_le32((CCU_BASE + CCU_DRAM_CLK_REG), (1 << 31) | (1 << 27)); + udelay(5); + + // mCTL clock enable + writel(0x8000, (MCTL_PHY_BASE + MCTL_PHY_CLKEN)); + udelay(10); +} + +// The main purpose of this routine seems to be to copy an address configuration +// from the dram_para1 and dram_para2 fields to the PHY configuration registers +// (MCTL_COM_WORK_MODE0, MCTL_COM_WORK_MODE1). +// +static void mctl_com_init(dram_para_t *para) { + uint32_t val, width; + unsigned long ptr; + int i; + + // Setting controller wait time + clrsetbits_le32((MCTL_COM_BASE + MCTL_COM_DBGCR), 0x3f00, 0x2000); + + // set SDRAM type and word width + val = readl((MCTL_COM_BASE + MCTL_COM_WORK_MODE0)) & ~0x00fff000; + val |= (para->dram_type & 0x7) << 16; // DRAM type + val |= (~para->dram_para2 & 0x1) << 12;// DQ width + val |= (1 << 22); // ?? + if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 || para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) { + val |= (1 << 19);// type 6 and 7 must use 1T + } else { + if (para->dram_tpr13 & (1 << 5)) + val |= (1 << 19); + } + writel(val, (MCTL_COM_BASE + MCTL_COM_WORK_MODE0)); + + // init rank / bank / row for single/dual or two different ranks + if ((para->dram_para2 & (1 << 8)) && ((para->dram_para2 & 0xf000) != 0x1000)) + width = 32; + else + width = 16; + + ptr = (MCTL_COM_BASE + MCTL_COM_WORK_MODE0); + for (i = 0; i < width; i += 16) { + val = readl(ptr) & 0xfffff000; + + val |= (para->dram_para2 >> 12) & 0x3; // rank + val |= ((para->dram_para1 >> (i + 12)) << 2) & 0x4; // bank - 2 + val |= (((para->dram_para1 >> (i + 4)) - 1) << 4) & 0xff;// row - 1 + + // convert from page size to column addr width - 3 + switch ((para->dram_para1 >> i) & 0xf) { + case 8: + val |= 0xa00; + break; + case 4: + val |= 0x900; + break; + case 2: + val |= 0x800; + break; + case 1: + val |= 0x700; + break; + default: + val |= 0x600; + break; + } + writel(val, ptr); + ptr += 4; + } + + // set ODTMAP based on number of ranks in use + val = (readl((MCTL_COM_BASE + MCTL_COM_WORK_MODE0)) & 0x1) ? 0x303 : 0x201; + writel(val, (MCTL_PHY_BASE + MCTL_PHY_ODTMAP)); + + // set mctl reg 3c4 to zero when using half DQ + if (para->dram_para2 & (1 << 0)) + writel(0, (MCTL_PHY_BASE + MCTL_PHY_DXnGCR0(1))); + + // set dram address mapping from dram_tpr4 param + if (para->dram_tpr4) { + setbits_le32((MCTL_COM_BASE + MCTL_COM_WORK_MODE0), (para->dram_tpr4 & 0x3) << 25); + setbits_le32((MCTL_COM_BASE + MCTL_COM_WORK_MODE1), (para->dram_tpr4 & 0x7fc) << 10); + } +} + +static const uint8_t ac_remapping_tables[][22] = + { + /* No Remap */ + [0] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* ASIC Chip */ + [1] = {0x1, 0x9, 0x3, 0x7, 0x8, 0x12, 0x4, 0xD, + 0x5, 0x6, 0xA, 0x2, 0xE, 0xC, 0x0, 0x0, + 0x15, 0x11, 0x14, 0x13, 0xB, 0x16},// Generic DDR3 Type1 + [2] = {0x4, 0x9, 0x3, 0x7, 0x8, 0x12, 0x1, 0xD, + 0x2, 0x6, 0xA, 0x5, 0xE, 0xC, 0x0, 0x0, + 0x15, 0x11, 0x14, 0x13, 0xB, 0x16},// Generic DDR3 Type C + [3] = {0x1, 0x7, 0x8, 0xC, 0xA, 0x12, 0x4, 0xD, + 0x5, 0x6, 0x3, 0x2, 0x9, 0x0, 0x0, 0x0, + 0x15, 0x11, 0x14, 0x13, 0xB, 0x16},// Generic DDR3 Type 8 + [4] = {0x4, 0xC, 0xA, 0x7, 0x8, 0x12, 0x1, 0xD, + 0x2, 0x6, 0x3, 0x5, 0x9, 0x0, 0x0, 0x0, + 0x15, 0x11, 0x14, 0x13, 0xB, 0x16},// Generic DDR3 Type 9 + [5] = {0xD, 0x2, 0x7, 0x9, 0xC, 0x13, 0x5, 0x1, + 0x6, 0x3, 0x4, 0x8, 0xA, 0x0, 0x0, 0x0, + 0x15, 0x16, 0x12, 0x11, 0xB, 0x14},// DDR3 Type bf (T113) + [6] = {0x3, 0xA, 0x7, 0xD, 0x9, 0xB, 0x1, 0x2, + 0x4, 0x6, 0x8, 0x5, 0xC, 0x0, 0x0, 0x0, + 0x14, 0x12, 0x0, 0x15, 0x16, 0x11},// DDR2 + [7] = {0x3, 0x2, 0x4, 0x7, 0x9, 0x1, 0x11, 0xC, + 0x12, 0xE, 0xD, 0x8, 0xF, 0x6, 0xA, 0x5, + 0x13, 0x16, 0x10, 0x15, 0x14, 0xB},// DDR3 D1-H + [8] = {0x2, 0x13, 0x8, 0x6, 0xE, 0x5, 0x14, 0xA, + 0x3, 0x12, 0xD, 0xB, 0x7, 0xF, 0x9, 0x1, + 0x16, 0x15, 0x11, 0xC, 0x4, 0x10},// DDR3 H133 + [9] = {0x1, 0x2, 0xD, 0x8, 0xF, 0xC, 0x13, 0xA, + 0x3, 0x15, 0x6, 0x11, 0x9, 0xE, 0x5, 0x10, + 0x14, 0x16, 0xB, 0x7, 0x4, 0x12},// DDR2 H133 +}; + +/* + * This routine chooses one of several remapping tables for 22 lines. + * It is unclear which lines are being remapped. It seems to pick + * table cfg7 for the Nezha board. + */ +static void mctl_phy_ac_remapping(dram_para_t *para) { + const uint8_t *cfg; + uint32_t fuse, val; + + /* + * Only DDR2 and DDR3 Support Remap + */ + if (para->dram_type != SUNXI_DRAM_TYPE_DDR2 && + para->dram_type != SUNXI_DRAM_TYPE_DDR3) + return; + + fuse = (readl(SYS_SID_BASE + SYS_EFUSE_REG) & 0xf00) >> 8; + printk(LOG_LEVEL_DEBUG, "DDR efuse: 0x%x\r\n", fuse); + + if (para->dram_type == SUNXI_DRAM_TYPE_DDR2) { + /* if fuse is 0xa then D1s -> no remap*/ + if (fuse == 0x0a) { + printk(LOG_LEVEL_DEBUG, "D1s no REMAP!!\r\n"); + return; + } + if (fuse == 15) + return; + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 6 \r\n"); + cfg = ac_remapping_tables[6]; + } else { + if (para->dram_tpr13 & 0xc0000) { + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 7 \r\n"); + cfg = ac_remapping_tables[7]; + } else { + switch (fuse) { + case 8: + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 2 \r\n"); + cfg = ac_remapping_tables[2]; + break; + case 9: + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 3 \r\n"); + cfg = ac_remapping_tables[3]; + break; + case 10: + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 5 \r\n"); + cfg = ac_remapping_tables[5]; + break; + case 11: + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 4 \r\n"); + cfg = ac_remapping_tables[4]; + break; + default: + case 12: + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 1 \r\n"); + cfg = ac_remapping_tables[1]; + break; + case 13: + case 14: + printk(LOG_LEVEL_DEBUG, "DDR Using MAP: 0 \r\n"); + cfg = ac_remapping_tables[0]; + break; + } + } + } + + val = (cfg[1] << 10) | (32 * cfg[0]) | 1 | (cfg[2] << 15) | (cfg[3] << 20) | + (cfg[4] << 25); + writel(val, (MCTL_COM_BASE + MCTL_COM_REMAP0)); + val = (cfg[7] << 10) | (32 * cfg[6]) | cfg[5] | (cfg[8] << 15) | + (cfg[9] << 20) | (cfg[10] << 25); + writel(val, (MCTL_COM_BASE + MCTL_COM_REMAP1)); + val = (cfg[13] << 10) | (32 * cfg[12]) | cfg[11] | (cfg[14] << 15) | + (cfg[15] << 20); + writel(val, (MCTL_COM_BASE + MCTL_COM_REMAP2)); + val = (cfg[18] << 10) | (32 * cfg[17]) | cfg[16] | (cfg[19] << 15) | + (cfg[20] << 20) | (cfg[21] << 25); + writel(val, (MCTL_COM_BASE + MCTL_COM_REMAP3)); + + printk(LOG_LEVEL_DEBUG, "MCTL_COM_REMAP0 = 0x%x\r\n", + readl((MCTL_COM_BASE + MCTL_COM_REMAP0))); + printk(LOG_LEVEL_DEBUG, "MCTL_COM_REMAP1 = 0x%x\r\n", + readl((MCTL_COM_BASE + MCTL_COM_REMAP1))); + printk(LOG_LEVEL_DEBUG, "MCTL_COM_REMAP2 = 0x%x\r\n", + readl((MCTL_COM_BASE + MCTL_COM_REMAP2))); + printk(LOG_LEVEL_DEBUG, "MCTL_COM_REMAP3 = 0x%x\r\n", + readl((MCTL_COM_BASE + MCTL_COM_REMAP3))); +} + +// Init the controller channel. The key part is placing commands in the main +// command register (PIR, 0x3103000) and checking command status (PGSR0, 0x3103010). +// +static unsigned int mctl_channel_init(unsigned int ch_index, dram_para_t *para) { + unsigned int val, dqs_gating_mode; + + dqs_gating_mode = (para->dram_tpr13 & 0xc) >> 2; + + // set DDR clock to half of CPU clock + clrsetbits_le32((MCTL_COM_BASE + MCTL_COM_TMR), 0xfff, (para->dram_clk / 2) - 1); + + // MRCTRL0 nibble 3 undocumented + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), 0xf00, 0x300); + + if (para->dram_odt_en) + val = 0; + else + val = (1 << 5); + + // DX0GCR0 + if (para->dram_clk > 672) + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXnGCR0(0)), 0xf63e, val); + else + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXnGCR0(0)), 0xf03e, val); + + // DX1GCR0 + if (para->dram_clk > 672) { + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXnGCR0(0)), 0x400); + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXnGCR0(1)), 0xf63e, val); + } else { + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXnGCR0(1)), 0xf03e, val); + } + + // (MCTL_PHY_BASE+MCTL_PHY_ACIOCR0) undocumented + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_ACIOCR0), (1 << 1)); + + eye_delay_compensation(para); + + // set PLL SSCG ? + val = readl((MCTL_PHY_BASE + MCTL_PHY_PGCR2)); + if (dqs_gating_mode == 1) { + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), 0xc0, 0); + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_DQSGMR), 0x107); + } else if (dqs_gating_mode == 2) { + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), 0xc0, 0x80); + + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DQSGMR), 0x107, (((para->dram_tpr13 >> 16) & 0x1f) - 2) | 0x100); + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXCCR), (1 << 31), (1 << 27)); + } else { + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), 0x40); + udelay(10); + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), 0xc0); + } + + if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 || para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) { + if (dqs_gating_mode == 1) + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXCCR), 0x080000c0, 0x80000000); + else + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXCCR), 0x77000000, 0x22000000); + } + + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DTCR), 0x0fffffff, + (para->dram_para2 & (1 << 12)) ? 0x03000001 : 0x01000007); + + if (readl((SUNXI_R_CPUCFG_BASE + SUNXI_R_CPUCFG_SUP_STAN_FLAG)) & (1 << 16)) { + clrbits_le32((R_PRCM_BASE + VDD_SYS_PWROFF_GATING_REG), 0x2); + udelay(10); + } + + // Set ZQ config + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_ZQCR), 0x3ffffff, (para->dram_zq & 0x00ffffff) | (1 << 25)); + + // Initialise DRAM controller + if (dqs_gating_mode == 1) { + // writel(0x52, (MCTL_PHY_BASE+MCTL_PHY_PIR)); // prep PHY reset + PLL init + // + z-cal + writel(0x53, (MCTL_PHY_BASE + MCTL_PHY_PIR));// Go + + while ((readl((MCTL_PHY_BASE + MCTL_PHY_PGSR0)) & 0x1) == 0) { + }// wait for IDONE + udelay(10); + + // 0x520 = prep DQS gating + DRAM init + d-cal + if (para->dram_type == SUNXI_DRAM_TYPE_DDR3) + writel(0x5a0, (MCTL_PHY_BASE + MCTL_PHY_PIR));// + DRAM reset + else + writel(0x520, (MCTL_PHY_BASE + MCTL_PHY_PIR)); + } else { + if ((readl((SUNXI_R_CPUCFG_BASE + SUNXI_R_CPUCFG_SUP_STAN_FLAG)) & (1 << 16)) == 0) { + // prep DRAM init + PHY reset + d-cal + PLL init + z-cal + if (para->dram_type == SUNXI_DRAM_TYPE_DDR3) + writel(0x1f2, (MCTL_PHY_BASE + MCTL_PHY_PIR));// + DRAM reset + else + writel(0x172, (MCTL_PHY_BASE + MCTL_PHY_PIR)); + } else { + // prep PHY reset + d-cal + z-cal + writel(0x62, (MCTL_PHY_BASE + MCTL_PHY_PIR)); + } + } + + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_PIR), 0x1);// GO + + udelay(10); + while ((readl((MCTL_PHY_BASE + MCTL_PHY_PGSR0)) & 0x1) == 0) { + }// wait for IDONE + + if (readl((SUNXI_R_CPUCFG_BASE + SUNXI_R_CPUCFG_SUP_STAN_FLAG)) & (1 << 16)) { + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR3), 0x06000000, 0x04000000); + udelay(10); + + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_PWRCTL), 0x1); + + while ((readl((MCTL_PHY_BASE + MCTL_PHY_STATR)) & 0x7) != 0x3) { + } + + clrbits_le32((R_PRCM_BASE + VDD_SYS_PWROFF_GATING_REG), 0x1); + udelay(10); + + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PWRCTL), 0x1); + + while ((readl((MCTL_PHY_BASE + MCTL_PHY_STATR)) & 0x7) != 0x1) { + } + + udelay(15); + + if (dqs_gating_mode == 1) { + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), 0xc0); + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR3), 0x06000000, 0x02000000); + udelay(1); + writel(0x401, (MCTL_PHY_BASE + MCTL_PHY_PIR)); + + while ((readl((MCTL_PHY_BASE + MCTL_PHY_PGSR0)) & 0x1) == 0) { + } + } + } + + // Check for training error + if (readl((MCTL_PHY_BASE + MCTL_PHY_PGSR0)) & (1 << 20)) { + printk(LOG_LEVEL_ERROR, "ZQ calibration error, check external 240 ohm resistor\r\n"); + return 0; + } + + // STATR = Zynq STAT? Wait for status 'normal'? + while ((readl((MCTL_PHY_BASE + MCTL_PHY_STATR)) & 0x1) == 0) { + } + + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_RFSHCTL0), (1 << 31)); + udelay(10); + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_RFSHCTL0), (1 << 31)); + udelay(10); + setbits_le32((MCTL_COM_BASE + MCTL_COM_CCCR), (1 << 31)); + udelay(10); + + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR3), 0x06000000); + + if (dqs_gating_mode == 1) + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_DXCCR), 0xc0, 0x40); + + return 1; +} + +static unsigned int calculate_rank_size(uint32_t regval) { + unsigned int bits; + + bits = (regval >> 8) & 0xf; /* page size - 3 */ + bits += (regval >> 4) & 0xf; /* row width - 1 */ + bits += (regval >> 2) & 0x3; /* bank count - 2 */ + bits -= 14; /* 1MB = 20 bits, minus above 6 = 14 */ + + return 1U << bits; +} + +/* + * The below routine reads the dram config registers and extracts + * the number of address bits in each rank available. It then calculates + * total memory size in MB. + */ +static unsigned int DRAMC_get_dram_size(void) { + uint32_t val; + unsigned int size; + + val = readl((MCTL_COM_BASE + MCTL_COM_WORK_MODE0)); /* MCTL_COM_WORK_MODE0 */ + size = calculate_rank_size(val); + + if ((val & 0x3) == 0) /* single rank? */ + return size; + + val = readl((MCTL_COM_BASE + MCTL_COM_WORK_MODE1)); /* MCTL_WORK_MODE1 */ + if ((val & 0x3) == 0) /* two identical ranks? */ + return size * 2; + + /* add sizes of both ranks */ + return size + calculate_rank_size(val); +} + +/* + * The below routine reads the command status register to extract + * DQ width and rank count. This follows the DQS training command in + * channel_init. If error bit 22 is reset, we have two ranks and full DQ. + * If there was an error, figure out whether it was half DQ, single rank, + * or both. Set bit 12 and 0 in dram_para2 with the results. + */ +static int dqs_gate_detect(dram_para_t *para) { + uint32_t dx0 = 0, dx1 = 0; + + if ((readl(MCTL_PHY_BASE + MCTL_PHY_PGSR0) & BIT(22)) == 0) { + para->dram_para2 = (para->dram_para2 & ~0xf) | BIT(12); + printk(LOG_LEVEL_DEBUG, "dual rank and full DQ\r\n"); + + return 1; + } + + dx0 = (readl(MCTL_PHY_BASE + MCTL_PHY_DXnGSR0(0)) & 0x3000000) >> 24; + if (dx0 == 0) { + para->dram_para2 = (para->dram_para2 & ~0xf) | 0x1001; + printk(LOG_LEVEL_DEBUG, "dual rank and half DQ\r\n"); + + return 1; + } + + if (dx0 == 2) { + dx1 = (readl(MCTL_PHY_BASE + MCTL_PHY_DXnGSR0(1)) & 0x3000000) >> 24; + if (dx1 == 2) { + para->dram_para2 = para->dram_para2 & ~0xf00f; + printk(LOG_LEVEL_DEBUG, "single rank and full DQ\r\n"); + } else { + para->dram_para2 = (para->dram_para2 & ~0xf00f) | BIT(0); + printk(LOG_LEVEL_DEBUG, "single rank and half DQ\r\n"); + } + + return 1; + } + + if ((para->dram_tpr13 & BIT(29)) == 0) + return 0; + + printk(LOG_LEVEL_DEBUG, "DX0 state: %" PRIu32 "\r\n", dx0); + printk(LOG_LEVEL_DEBUG, "DX1 state: %" PRIu32 "\r\n", dx1); + + return 0; +} + +static int dramc_simple_wr_test(unsigned int mem_mb, int len) { + unsigned int offs = (mem_mb / 2) << 18;// half of memory size + unsigned int patt1 = 0x01234567; + unsigned int patt2 = 0xfedcba98; + unsigned int *addr, v1, v2, i; + + addr = (unsigned int *) CONFIG_SYS_SDRAM_BASE; + for (i = 0; i != len; i++, addr++) { + writel(patt1 + i, (unsigned long) addr); + writel(patt2 + i, (unsigned long) (addr + offs)); + } + + addr = (unsigned int *) CONFIG_SYS_SDRAM_BASE; + for (i = 0; i != len; i++) { + v1 = readl((unsigned long) (addr + i)); + v2 = patt1 + i; + if (v1 != v2) { + printk(LOG_LEVEL_ERROR, "DRAM: simple test FAIL\r\n"); + printk(LOG_LEVEL_ERROR, "%x != %x at address %p\r\n", v1, v2, addr + i); + return 1; + } + v1 = readl((unsigned long) (addr + offs + i)); + v2 = patt2 + i; + if (v1 != v2) { + printk(LOG_LEVEL_ERROR, "DRAM: simple test FAIL\r\n"); + printk(LOG_LEVEL_ERROR, "%x != %x at address %p\r\n", v1, v2, addr + offs + i); + return 1; + } + } + + printk(LOG_LEVEL_DEBUG, "DRAM: simple test OK\r\n"); + return 0; +} + +// Set the Vref mode for the controller +// +static void mctl_vrefzq_init(dram_para_t *para) { + if (para->dram_tpr13 & (1 << 17)) + return; + + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_IOVCR0), 0x7f7f7f7f, para->dram_tpr5); + + // IOCVR1 + if ((para->dram_tpr13 & (1 << 16)) == 0) + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_IOVCR1), 0x7f, para->dram_tpr6 & 0x7f); +} + +// Perform an init of the controller. This is actually done 3 times. The first +// time to establish the number of ranks and DQ width. The second time to +// establish the actual ram size. The third time is final one, with the final +// settings. +// +static int mctl_core_init(dram_para_t *para) { + mctl_sys_init(para); + + mctl_vrefzq_init(para); + + mctl_com_init(para); + + mctl_phy_ac_remapping(para); + + mctl_set_timing_params(para); + + return mctl_channel_init(0, para); +} + +/* + * This routine sizes a DRAM device by cycling through address lines and + * figuring out if they are connected to a real address line, or if the + * address is a mirror. + * First the column and bank bit allocations are set to low values (2 and 9 + * address lines). Then a maximum allocation (16 lines) is set for rows and + * this is tested. + * Next the BA2 line is checked. This seems to be placed above the column, + * BA0-1 and row addresses. Finally, the column address is allocated 13 lines + * and these are tested. The results are placed in dram_para1 and dram_para2. + */ +static int auto_scan_dram_size(dram_para_t *para) { + uint32_t i = 0, j = 0, current_rank = 0; + uint32_t rank_count = 1, addr_line = 0; + uint32_t reg_val = 0, ret = 0, cnt = 0; + unsigned long mc_work_mode; + uint32_t rank1_addr = CONFIG_SYS_SDRAM_BASE; + + // init core + if (mctl_core_init(para) == 0) { + printk(LOG_LEVEL_DEBUG, "DRAM initial error : 0!\r\n"); + return 0; + } + + // Set rank_count to 2 + if ((((para->dram_para2 >> 12) & 0xf) == 0x1)) + rank_count = 2; + + for (current_rank = 0; current_rank < rank_count; current_rank++) { + mc_work_mode = ((MCTL_COM_BASE + MCTL_COM_WORK_MODE0) + 4 * current_rank); + + /* Set 16 Row 4Bank 512BPage for Rank 1 */ + if (current_rank == 1) { + clrsetbits_le32((MCTL_COM_BASE + MCTL_COM_WORK_MODE0), 0xf0c, 0x6f0); + clrsetbits_le32((MCTL_COM_BASE + MCTL_COM_WORK_MODE1), 0xf0c, 0x6f0); + /* update Rank 1 addr */ + rank1_addr = CONFIG_SYS_SDRAM_BASE + (0x1 << 27); + } + + /* write test pattern */ + for (i = 0; i < 64; i++) { + writel((i % 2) ? (CONFIG_SYS_SDRAM_BASE + 4 * i) : (~(CONFIG_SYS_SDRAM_BASE + 4 * i)), + CONFIG_SYS_SDRAM_BASE + 4 * i); + } + /* set row mode */ + clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0); + udelay(2); + + for (i = 11; i < 17; i++) { + ret = CONFIG_SYS_SDRAM_BASE + (1 << (i + 2 + 9)); /* row-bank-column */ + cnt = 0; + for (j = 0; j < 64; j++) { + reg_val = (j % 2) ? (rank1_addr + 4 * j) : (~(rank1_addr + 4 * j)); + if (reg_val == readl(ret + j * 4)) { + cnt++; + } else + break; + } + if (cnt == 64) { + break; + } + } + if (i >= 16) + i = 16; + addr_line += i; + + printk(LOG_LEVEL_DEBUG, "rank %" PRIu32 " row = %" PRIu32 " \r\n", current_rank, i); + + /* Store rows in para 1 */ + para->dram_para1 &= ~(0xffU << (16 * current_rank + 4)); + para->dram_para1 |= (i << (16 * current_rank + 4)); + + /* Set bank mode for current rank */ + if (current_rank == 1) { /* Set bank mode for rank0 */ + clrsetbits_le32((MCTL_COM_BASE + MCTL_COM_WORK_MODE0), 0xffc, 0x6a4); + } + + /* Set bank mode for current rank */ + clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4); + udelay(1); + + for (i = 0; i < 1; i++) { + ret = CONFIG_SYS_SDRAM_BASE + (0x1U << (i + 2 + 9)); + cnt = 0; + for (j = 0; j < 64; j++) { + reg_val = (j % 2) ? (rank1_addr + 4 * j) : (~(rank1_addr + 4 * j)); + if (reg_val == readl(ret + j * 4)) { + cnt++; + } else + break; + } + if (cnt == 64) { + break; + } + } + + addr_line += i + 2; + printk(LOG_LEVEL_DEBUG, "rank %" PRIu32 " bank = %" PRIu32 " \r\n", current_rank, (4 + i * 4)); + + /* Store bank in para 1 */ + para->dram_para1 &= ~(0xfU << (16 * current_rank + 12)); + para->dram_para1 |= (i << (16 * current_rank + 12)); + + /* Set page mode for rank0 */ + if (current_rank == 1) { + clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0); + } + + /* Set page mode for current rank */ + clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0); + udelay(2); + + /* Scan per address line, until address wraps (i.e. see shadow) */ + for (i = 9; i <= 13; i++) { + ret = CONFIG_SYS_SDRAM_BASE + (0x1U << i);// column 40000000+(9~13) + cnt = 0; + for (j = 0; j < 64; j++) { + reg_val = (j % 2) ? (CONFIG_SYS_SDRAM_BASE + 4 * j) : (~(CONFIG_SYS_SDRAM_BASE + 4 * j)); + if (reg_val == readl(ret + j * 4)) { + cnt++; + } else { + break; + } + } + if (cnt == 64) { + break; + } + } + + if (i >= 13) { + i = 13; + } + + /* add page size */ + addr_line += i; + + if (i == 9) { + i = 0; + } else { + i = (0x1U << (i - 10)); + } + + printk(LOG_LEVEL_DEBUG, "rank %" PRIu32 " page size = %" PRIu32 " KB \r\n", current_rank, i); + + /* Store page in para 1 */ + para->dram_para1 &= ~(0xfU << (16 * current_rank)); + para->dram_para1 |= (i << (16 * current_rank)); + } + + /* check dual rank config */ + if (rank_count == 2) { + para->dram_para2 &= 0xfffff0ff; + if ((para->dram_para1 & 0xffff) == (para->dram_para1 >> 16)) { + printk(LOG_LEVEL_DEBUG, "rank1 config same as rank0\r\n"); + } else { + para->dram_para2 |= 0x1 << 8; + printk(LOG_LEVEL_DEBUG, "rank1 config different from rank0\r\n"); + } + } + return 1; +} + +/* + * This routine sets up parameters with dqs_gating_mode equal to 1 and two + * ranks enabled. It then configures the core and tests for 1 or 2 ranks and + * full or half DQ width. It then resets the parameters to the original values. + * dram_para2 is updated with the rank and width findings. + */ +static int auto_scan_dram_rank_width(dram_para_t *para) { + unsigned int s1 = para->dram_tpr13; + unsigned int s2 = para->dram_para1; + + para->dram_para1 = 0x00b000b0; + para->dram_para2 = (para->dram_para2 & ~0xf) | (1 << 12); + + /* set DQS probe mode */ + para->dram_tpr13 = (para->dram_tpr13 & ~0x8) | (1 << 2) | (1 << 0); + + mctl_core_init(para); + + if (readl((MCTL_PHY_BASE + MCTL_PHY_PGSR0)) & (1 << 20)) + return 0; + + if (dqs_gate_detect(para) == 0) + return 0; + + para->dram_tpr13 = s1; + para->dram_para1 = s2; + + return 1; +} + +/* + * This routine determines the SDRAM topology. It first establishes the number + * of ranks and the DQ width. Then it scans the SDRAM address lines to establish + * the size of each rank. It then updates dram_tpr13 to reflect that the sizes + * are now known: a re-init will not repeat the autoscan. + */ +static int auto_scan_dram_config(dram_para_t *para) { + if (((para->dram_tpr13 & BIT(14)) == 0) && (auto_scan_dram_rank_width(para) == 0)) { + printk(LOG_LEVEL_ERROR, "ERROR: auto scan dram rank & width failed\r\n"); + return 0; + } + + if (((para->dram_tpr13 & BIT(0)) == 0) && (auto_scan_dram_size(para) == 0)) { + printk(LOG_LEVEL_ERROR, "ERROR: auto scan dram size failed\r\n"); + return 0; + } + + if ((para->dram_tpr13 & BIT(15)) == 0) + para->dram_tpr13 |= BIT(14) | BIT(13) | BIT(1) | BIT(0); + + return 1; +} + +int init_DRAM(int type, dram_para_t *para) { + u32 rc, mem_size_mb; + + printk(LOG_LEVEL_DEBUG, "DRAM BOOT DRIVE INFO: %s\r\n", "V0.24"); + printk(LOG_LEVEL_DEBUG, "DRAM CLK = %d MHz\r\n", para->dram_clk); + printk(LOG_LEVEL_DEBUG, "DRAM Type = %d (2:DDR2,3:DDR3)\r\n", para->dram_type); + if ((para->dram_odt_en & 0x1) == 0) + printk(LOG_LEVEL_DEBUG, "DRAMC read ODT off\r\n"); + else + printk(LOG_LEVEL_DEBUG, "DRAMC ZQ value: 0x%x\r\n", para->dram_zq); + + /* Test ZQ status */ + if (para->dram_tpr13 & (1 << 16)) { + printk(LOG_LEVEL_DEBUG, "DRAM only have internal ZQ\r\n"); + setbits_le32((SYS_CONTROL_REG_BASE + ZQ_CAL_CTRL_REG), (1 << 8)); + writel(0, (SYS_CONTROL_REG_BASE + ZQ_RES_CTRL_REG)); + udelay(10); + } else { + clrbits_le32((SYS_CONTROL_REG_BASE + ZQ_CAL_CTRL_REG), 0x3); + writel(para->dram_tpr13 & (1 << 16), (R_PRCM_BASE + ANALOG_PWROFF_GATING_REG)); + udelay(10); + clrsetbits_le32((SYS_CONTROL_REG_BASE + ZQ_CAL_CTRL_REG), 0x108, (1 << 1)); + udelay(10); + setbits_le32((SYS_CONTROL_REG_BASE + ZQ_CAL_CTRL_REG), (1 << 0)); + udelay(20); + printk(LOG_LEVEL_DEBUG, "ZQ value = 0x%" PRIx32 "\r\n", readl((SYS_CONTROL_REG_BASE + ZQ_RES_STATUS_REG))); + } + + dram_voltage_set(para); + + /* Set SDRAM controller auto config */ + if ((para->dram_tpr13 & (1 << 0)) == 0) { + if (auto_scan_dram_config(para) == 0) { + printk(LOG_LEVEL_ERROR, "auto_scan_dram_config() FAILED\r\n"); + return 0; + } + } + + /* report ODT */ + rc = para->dram_mr1; + if ((rc & 0x44) == 0) + printk(LOG_LEVEL_DEBUG, "DRAM ODT off\r\n"); + else + printk(LOG_LEVEL_DEBUG, "DRAM ODT value: 0x%" PRIx32 "\r\n", rc); + + /* Init core, final run */ + if (mctl_core_init(para) == 0) { + printk(LOG_LEVEL_DEBUG, "DRAM initialisation error: 1\r\n"); + return 0; + } + + /* Get SDRAM size + * You can set dram_para2 to force set the dram size + */ + rc = para->dram_para2; + if (rc & (1 << 31)) { + rc = (rc >> 16) & ~(1 << 15); + } else { + rc = DRAMC_get_dram_size(); + printk(LOG_LEVEL_INFO, "DRAM: size = %uMB\r\n", rc); + para->dram_para2 = (para->dram_para2 & 0xffffU) | rc << 16; + } + mem_size_mb = rc; + + /* Enable hardware auto refresh */ + if (para->dram_tpr13 & (1 << 30)) { + rc = para->dram_tpr8; + if (rc == 0) + rc = 0x10000200; + writel(rc, (MCTL_PHY_BASE + MCTL_PHY_ASRTC)); + writel(0x40a, (MCTL_PHY_BASE + MCTL_PHY_ASRC)); + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_PWRCTL), (1 << 0)); + printk(LOG_LEVEL_DEBUG, "Enable Auto SR\r\n"); + } else { + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_ASRTC), 0xffff); + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PWRCTL), 0x1); + } + + /* Set HDR/DDR dynamic */ + if (para->dram_tpr13 & (1 << 9)) { + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR0), 0xf000, 0x5000); + } else { + if (para->dram_type != SUNXI_DRAM_TYPE_LPDDR2) + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR0), 0xf000); + } + + /* Disable ZQ calibration */ + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_ZQCR), (1 << 31)); + + /* Set VTF feature */ + if (para->dram_tpr13 & (1 << 8)) + writel(readl((MCTL_PHY_BASE + MCTL_PHY_VTFCR)) | 0x300, (MCTL_PHY_BASE + MCTL_PHY_VTFCR)); + + /* Set PAD Hold */ + if (para->dram_tpr13 & (1 << 16)) + clrbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), (1 << 13)); + else + setbits_le32((MCTL_PHY_BASE + MCTL_PHY_PGCR2), (1 << 13)); + + /* Set LPDDR3 ODT delay */ + if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) + clrsetbits_le32((MCTL_PHY_BASE + MCTL_PHY_ODTCFG), 0xf0000, 0x1000); + + dram_enable_all_master(); + if (para->dram_tpr13 & (1 << 28)) { + if ((readl((SUNXI_R_CPUCFG_BASE + SUNXI_R_CPUCFG_SUP_STAN_FLAG)) & (1 << 16)) || + dramc_simple_wr_test(mem_size_mb, 4096)) + return 0; + } + + return mem_size_mb; +} + +uint64_t sunxi_dram_init(dram_para_t *para) { + return init_DRAM(0, para); +}; \ No newline at end of file diff --git a/src/drivers/sun8iw20/sys-rproc.c b/src/drivers/sun8iw20/sys-rproc.c new file mode 100644 index 00000000..b528ba16 --- /dev/null +++ b/src/drivers/sun8iw20/sys-rproc.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +void sunxi_c906_clock_init(uint32_t addr) { + uint32_t reg_val; + + reg_val = 0; + reg_val |= CCU_RISCV_CFG_RST; + reg_val |= CCU_RISCV_CFG_GATING; + writel(reg_val, CCU_RISCV_CFG_BGR_REG); + + /* set start addr */ + reg_val = addr; + writel(reg_val, CCU_RISCV_STA_ADD_L_REG); + reg_val = 0; + writel(reg_val, CCU_RISCV_STA_ADD_H_REG); + + /* set c906 clock */ + reg_val = readl(CCU_RISCV_CLK_REG); + reg_val &= ~(CCU_RISCV_CLK_MASK); + reg_val |= CCU_RISCV_CLK_PERI_800M; + writel(reg_val, CCU_RISCV_CLK_REG); + + /* soft reset */ + reg_val = CCU_RISCV_RST_KEY_FIELD; + reg_val |= CCU_RISCV_RST_SOFT_RSTN; + writel(reg_val, CCU_RISCV_RST_REG); +} + +void sunxi_c906_clock_reset(void) { + uint32_t reg_val; + + reg_val = 0; + reg_val |= CCU_RISCV_CLK_GATING; + reg_val |= CCU_RISCV_GATING_FIELD; + writel(reg_val, CCU_RISCV_GATING_RST_REG); + + reg_val = 0; + writel(reg_val, CCU_RISCV_CFG_BGR_REG); +} + +void dump_c906_clock(void) { + uint32_t reg_val, pll_perf, factor_m, factor_n, pll_riscv; + uint32_t plln, pllm; + uint8_t p0, p1; + + /* PLL PERI0 */ + reg_val = read32(CCU_BASE + CCU_PLL_PERI0_CTRL_REG); + + if (reg_val & (1 << 31)) { + plln = ((reg_val >> 8) & 0xff) + 1; + pllm = (reg_val & 0x01) + 1; + p0 = ((reg_val >> 16) & 0x03) + 1; + p1 = ((reg_val >> 20) & 0x03) + 1; + + pll_perf = (24 * plln) / (pllm * p1); + } else { + printk(LOG_LEVEL_INFO, "CLK: PLL_peri disabled\n"); + return; + } + + reg_val = read32(CCU_RISCV_CLK_REG); + factor_m = (reg_val & 0x1F) + 1; + factor_n = ((reg_val >> 8) & 0x3) + 1; + pll_riscv = pll_perf / factor_m; + + printk(LOG_LEVEL_INFO, "CLK: RISC-V PLL FREQ=%uMHz\n", pll_riscv); + printk(LOG_LEVEL_INFO, "CLK: RISC-V AXI FREQ=%uMHz\n", + pll_riscv / factor_n); +} \ No newline at end of file diff --git a/drivers/sys-sid.c b/src/drivers/sun8iw20/sys-sid.c similarity index 98% rename from drivers/sys-sid.c rename to src/drivers/sun8iw20/sys-sid.c index 33d1c74a..519d87eb 100644 --- a/drivers/sys-sid.c +++ b/src/drivers/sun8iw20/sys-sid.c @@ -10,6 +10,8 @@ #include +#include + #include "sys-sid.h" uint32_t efuse_read(uint32_t offset) { diff --git a/drivers/sys-wdt.c b/src/drivers/sun8iw20/sys-wdt.c similarity index 100% rename from drivers/sys-wdt.c rename to src/drivers/sun8iw20/sys-wdt.c diff --git a/src/drivers/sun8iw21/CMakeLists.txt b/src/drivers/sun8iw21/CMakeLists.txt new file mode 100644 index 00000000..41d913f5 --- /dev/null +++ b/src/drivers/sun8iw21/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(chip_drivers-obj OBJECT + sys-clk.c + sys-sid.c + sys-wdt.c + sys-dram.c + sys-rproc.c +) \ No newline at end of file diff --git a/drivers/sys-clk.c b/src/drivers/sun8iw21/sys-clk.c similarity index 99% rename from drivers/sys-clk.c rename to src/drivers/sun8iw21/sys-clk.c index 4a0158a1..e4a53d26 100644 --- a/drivers/sys-clk.c +++ b/src/drivers/sun8iw21/sys-clk.c @@ -7,9 +7,11 @@ #include #include +#include + #include -#include "sys-clk.h" +#include void sunxi_clk_init(void) { uint32_t val; diff --git a/drivers/sys-dram.c b/src/drivers/sun8iw21/sys-dram.c similarity index 97% rename from drivers/sys-dram.c rename to src/drivers/sun8iw21/sys-dram.c index 88c85a43..67b58dba 100644 --- a/drivers/sys-dram.c +++ b/src/drivers/sun8iw21/sys-dram.c @@ -10,9 +10,9 @@ #include #include +#include -#include "reg-dram.h" -#include "sys-dram.h" +#include #define DIV_ROUND_UP(a, b) (((a) + (b) -1) / (b)) @@ -1281,33 +1281,6 @@ int init_DRAM(int type, dram_para_t *para) { return mem_size_mb; } -uint64_t sunxi_dram_init(void) { - dram_para_t para = { - .dram_clk = 528, - .dram_type = 2, - .dram_zq = 0x7b7bf9, - .dram_odt_en = 0x0, - .dram_para1 = 0x00d2, - .dram_para2 = 0x0, - .dram_mr0 = 0xe73, - .dram_mr1 = 0x02, - .dram_mr2 = 0x0, - .dram_mr3 = 0x0, - .dram_tpr0 = 0x00471992, - .dram_tpr1 = 0x0131a10c, - .dram_tpr2 = 0x00057041, - .dram_tpr3 = 0xb4787896, - .dram_tpr4 = 0x0, - .dram_tpr5 = 0x48484848, - .dram_tpr6 = 0x48, - .dram_tpr7 = 0x1621121e, - .dram_tpr8 = 0x0, - .dram_tpr9 = 0x0, - .dram_tpr10 = 0x00000000, - .dram_tpr11 = 0x00000022, - .dram_tpr12 = 0x00000077, - .dram_tpr13 = 0x34000100, - }; - - return init_DRAM(0, ¶); +uint64_t sunxi_dram_init(dram_para_t *para) { + return init_DRAM(0, para); } \ No newline at end of file diff --git a/drivers/sys-rproc.c b/src/drivers/sun8iw21/sys-rproc.c similarity index 97% rename from drivers/sys-rproc.c rename to src/drivers/sun8iw21/sys-rproc.c index 981b09f9..6ead2189 100644 --- a/drivers/sys-rproc.c +++ b/src/drivers/sun8iw21/sys-rproc.c @@ -9,9 +9,9 @@ #include -#include "reg-ccu.h" -#include "reg-rproc.h" -#include "sys-rproc.h" +#include + +#include void sunxi_e907_clock_init(uint32_t addr) { uint32_t reg_val; diff --git a/src/drivers/sun8iw21/sys-sid.c b/src/drivers/sun8iw21/sys-sid.c new file mode 100644 index 00000000..519d87eb --- /dev/null +++ b/src/drivers/sun8iw21/sys-sid.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "sys-sid.h" + +uint32_t efuse_read(uint32_t offset) { + uint32_t val; + + val = read32(SID_PRCTL); + val &= ~((0x1ff << 16) | 0x3); + val |= offset << 16; + write32(SID_PRCTL, val); + val &= ~((0xff << 8) | 0x3); + val |= (0xac << 8) | 0x2; + write32(SID_PRCTL, val); + while (read32(SID_PRCTL) & 0x2) + ; + val &= ~((0x1ff << 16) | (0xff << 8) | 0x3); + write32(SID_PRCTL, val); + val = read32(SID_RDKEY); + + return val; +} + +void efuse_write(uint32_t offset, uint32_t value) { + uint32_t val; + + write32(EFUSE_HV_SWITCH, 0x1); + write32(SID_PRKEY, value); + val = read32(SID_PRCTL); + val &= ~((0x1ff << 16) | 0x3); + val |= offset << 16; + write32(SID_PRCTL, val); + val &= ~((0xff << 8) | 0x3); + val |= (0xac << 8) | 0x1; + write32(SID_PRCTL, val); + while (read32(SID_PRCTL) & 0x1) + ; + val &= ~((0x1ff << 16) | (0xff << 8) | 0x3); + write32(SID_PRCTL, val); + write32(EFUSE_HV_SWITCH, 0x0); +} + +void dump_efuse(void) { + uint32_t buffer[2048 / 4]; + + for (int n = 0; n < ARRAY_SIZE(sids); n++) { + uint32_t count = sids[n].size_bits / 32; + for (int i = 0; i < count; i++) + buffer[i] = efuse_read(sids[n].offset + i * 4); + + printk(LOG_LEVEL_MUTE, "%s:(0x%04x %d-bits)", sids[n].name, + sids[n].offset, sids[n].size_bits); + for (int i = 0; i < count; i++) { + if (i >= 0 && ((i % 8) == 0)) + printk(LOG_LEVEL_MUTE, "\n%-4s", ""); + printk(LOG_LEVEL_MUTE, "%08x ", buffer[i]); + } + printk(LOG_LEVEL_MUTE, "\n"); + } +} \ No newline at end of file diff --git a/src/drivers/sun8iw21/sys-wdt.c b/src/drivers/sun8iw21/sys-wdt.c new file mode 100644 index 00000000..4bce8b1f --- /dev/null +++ b/src/drivers/sun8iw21/sys-wdt.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include +#include +#include + +#include + +void sys_reset() { + write32(0x020500a0 + 0x08, (0x16aa << 16) | (0x1 << 0)); +} \ No newline at end of file diff --git a/drivers/sys-dma.c b/src/drivers/sys-dma.c similarity index 100% rename from drivers/sys-dma.c rename to src/drivers/sys-dma.c diff --git a/drivers/sys-gpio.c b/src/drivers/sys-gpio.c similarity index 81% rename from drivers/sys-gpio.c rename to src/drivers/sys-gpio.c index 4d383e25..771278e6 100644 --- a/drivers/sys-gpio.c +++ b/src/drivers/sys-gpio.c @@ -7,10 +7,10 @@ #include #include -#include #include -#include "sys-gpio.h" +#include +#include enum { GPIO_CFG0 = 0x00, @@ -32,29 +32,7 @@ static inline uint32_t _port_num(gpio_t pin) { static uint32_t _port_base_get(gpio_t pin) { uint32_t port = pin >> PIO_NUM_IO_BITS; - - switch (port) { - case PORTA: - return 0x02000000; - break; - case PORTC: - return 0x02000060; - break; - case PORTD: - return 0x02000090; - break; - case PORTE: - return 0x020000c0; - break; - case PORTF: - return 0x020000f0; - break; - case PORTH: - return 0x02000150; - break; - } - - return 0; + return SUNXI_PIO_BASE + port * 0x30; } static inline uint32_t _pin_num(gpio_t pin) { diff --git a/drivers/sys-i2c.c b/src/drivers/sys-i2c.c similarity index 99% rename from drivers/sys-i2c.c rename to src/drivers/sys-i2c.c index 19b3b0d7..5c335a52 100644 --- a/drivers/sys-i2c.c +++ b/src/drivers/sys-i2c.c @@ -5,12 +5,14 @@ #include #include +#include + #include #include -#include "sys-i2c.h" -#include "sys-timer.h" +#include +#include "sys-i2c.h" #include "reg-ncat.h" #define I2C_WRITE 0 diff --git a/drivers/sys-rtc.c b/src/drivers/sys-rtc.c similarity index 87% rename from drivers/sys-rtc.c rename to src/drivers/sys-rtc.c index 45d02d1e..783b3a8e 100644 --- a/drivers/sys-rtc.c +++ b/src/drivers/sys-rtc.c @@ -11,6 +11,8 @@ #include +#include + #define EFEX_FLAG (0x5AA5A55A) #define RTC_FEL_INDEX 2 #define RTC_BOOT_INDEX 6 @@ -26,8 +28,7 @@ uint32_t rtc_read_data(int index) { void rtc_set_fel_flag(void) { do { rtc_write_data(RTC_FEL_INDEX, EFEX_FLAG); - asm volatile("DSB"); - asm volatile("ISB"); + data_sync_barrier(); } while (rtc_read_data(RTC_FEL_INDEX) != EFEX_FLAG); } @@ -38,16 +39,14 @@ uint32_t rtc_probe_fel_flag(void) { void rtc_clear_fel_flag(void) { do { rtc_write_data(RTC_FEL_INDEX, 0); - asm volatile("DSB"); - asm volatile("ISB"); + data_sync_barrier(); } while (rtc_read_data(RTC_FEL_INDEX) != 0); } int rtc_set_bootmode_flag(uint8_t flag) { do { rtc_write_data(RTC_BOOT_INDEX, flag); - asm volatile("DSB"); - asm volatile("ISB"); + data_sync_barrier(); } while (rtc_read_data(RTC_BOOT_INDEX) != flag); return 0; diff --git a/drivers/sys-sdcard.c b/src/drivers/sys-sdcard.c similarity index 99% rename from drivers/sys-sdcard.c rename to src/drivers/sys-sdcard.c index 09c58d12..45e3582b 100644 --- a/drivers/sys-sdcard.c +++ b/src/drivers/sys-sdcard.c @@ -9,6 +9,8 @@ #include +#include + #include "sys-sdcard.h" #define FALSE 0 diff --git a/drivers/sys-sdhci.c b/src/drivers/sys-sdhci.c similarity index 99% rename from drivers/sys-sdhci.c rename to src/drivers/sys-sdhci.c index 1d342146..b993e486 100644 --- a/drivers/sys-sdhci.c +++ b/src/drivers/sys-sdhci.c @@ -8,11 +8,11 @@ #include #include +#include #include #include #include -#include #include "sys-sdcard.h" #include "sys-sdhci.h" diff --git a/drivers/sys-spi-nand.c b/src/drivers/sys-spi-nand.c similarity index 99% rename from drivers/sys-spi-nand.c rename to src/drivers/sys-spi-nand.c index c86b07be..3889f059 100644 --- a/drivers/sys-spi-nand.c +++ b/src/drivers/sys-spi-nand.c @@ -7,12 +7,13 @@ #include #include +#include + #include #include #include #include -#include #include "sys-spi.h" #include "sys-spi-nand.h" diff --git a/drivers/sys-spi.c b/src/drivers/sys-spi.c similarity index 99% rename from drivers/sys-spi.c rename to src/drivers/sys-spi.c index 84468a9c..72437be1 100644 --- a/drivers/sys-spi.c +++ b/src/drivers/sys-spi.c @@ -7,12 +7,13 @@ #include #include +#include + #include #include #include #include -#include #include "sys-spi.h" diff --git a/drivers/sys-uart.c b/src/drivers/sys-uart.c similarity index 96% rename from drivers/sys-uart.c rename to src/drivers/sys-uart.c index 1a032126..6953307c 100644 --- a/drivers/sys-uart.c +++ b/src/drivers/sys-uart.c @@ -1,18 +1,16 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include #include #include #include #include #include +#include + #include +#include #include -#include "sys-uart.h" - void sunxi_serial_init(sunxi_serial_t *uart) { uint32_t addr; uint32_t val; diff --git a/src/fdt_wrapper.c b/src/fdt_wrapper.c index 3354508a..78a3c1b9 100644 --- a/src/fdt_wrapper.c +++ b/src/fdt_wrapper.c @@ -1,6 +1,4 @@ /* SPDX-License-Identifier: Apache-2.0 */ - -#include #include #include #include @@ -8,6 +6,8 @@ #include +#include "ctype.h" + #include "fdt_wrapper.h" #include "libfdt.h" diff --git a/src/log/log.c b/src/log/log.c index dc7c59fe..d5bdcddc 100644 --- a/src/log/log.c +++ b/src/log/log.c @@ -5,8 +5,6 @@ #include #include -#include "common.h" - #include "log.h" #include "uart.h" #include "xformat.h" diff --git a/src/sstdlib.c b/src/sstdlib.c index dedf4891..f3e3e7d8 100644 --- a/src/sstdlib.c +++ b/src/sstdlib.c @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include #include #include +#include "ctype.h" #include "sstdlib.h" static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) { diff --git a/src/string/string.c b/src/string.c similarity index 100% rename from src/string/string.c rename to src/string.c diff --git a/src/uart.c b/src/uart.c index 5534f8c2..3ac4c5f9 100644 --- a/src/uart.c +++ b/src/uart.c @@ -5,7 +5,8 @@ #include #include -#include +#include + #include #include