diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..6ca9bb89 --- /dev/null +++ b/.clang-format @@ -0,0 +1,10 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +ColumnLimit: 100 +BreakBeforeBraces: Attach +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +PointerAlignment: Right +SortIncludes: Never diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..c18900b6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{c,h,S}] +indent_style = space +indent_size = 4 + +[Makefile] +indent_style = tab diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index fbc1b11a..41c7f1b0 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -31,12 +31,26 @@ jobs: - name: Install pinned quality tools run: python3 -m pip install --requirement requirements/ci.txt + - name: Install clang-format + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends --yes clang-format-14 + - name: Validate dependency lock run: python3 scripts/dependency_lock.py --lock config/dependencies.lock.json - name: Lint Python run: ruff check . + - name: Check embedded C formatting policy + run: make sw-format-check + + - name: Check embedded C safety policy + run: make sw-policy-check + + - name: Run embedded C host tests + run: make sw-host-test + - name: Test scripts run: python3 -m pytest -q diff --git a/Makefile b/Makefile index ebeb8c91..9310dfc6 100644 --- a/Makefile +++ b/Makefile @@ -48,17 +48,19 @@ RTL_TOP ?= retrosoc_tb ISA ?= RV32IM HAVE_CSR ?= NO FIRMWARE_NAME ?= retrosoc_fw -PROG_TYPE ?= FULL +APP ?= shell LINK_TYPE ?= ld2_sram BUILD_ROOT ?= $(ROOT_PATH)/build CACHE_ROOT ?= $(ROOT_PATH)/.cache/retrosoc MAX_JOBS ?= 16 +HOST_CC ?= cc +CLANG_FORMAT ?= clang-format-14 JOBS ?= $(shell count=$$(nproc 2>/dev/null || printf '1'); \ if [ "$$count" -gt "$(MAX_JOBS)" ]; then printf '%s' '$(MAX_JOBS)'; \ else printf '%s' "$$count"; fi) CONFIG_KEY_VARS := SOC CORE IP PDK HAVE_PLL HAVE_SRAM_IF HAVE_SRAM_MACRO HAVE_SVA \ - ISA HAVE_CSR PROG_TYPE LINK_TYPE RTL_TOP FIRMWARE_NAME + ISA HAVE_CSR APP LINK_TYPE RTL_TOP FIRMWARE_NAME VARIANT_ID := $(strip $(shell python3 $(ROOT_PATH)/scripts/config_key.py \ --lock $(LOCK_FILE) --profile $(PROFILE_NAME) \ $(foreach var,$(CONFIG_KEY_VARS),--value $(var)=$($(var))))) @@ -88,7 +90,7 @@ VALID_STA := NONE OPENSTA VALID_PDK := ICS55 IHP130 SKY130 GF180 VALID_BOOL := YES NO VALID_ISA := RV32E RV32I RV32IM -VALID_PROG_TYPE := BASE FULL +VALID_APP := bringup shell VALID_LINK_TYPE := xip ld2_sram ld2_psram ld2_sdram define validate_value @@ -109,7 +111,7 @@ $(call validate_value,HAVE_SVA,$(VALID_BOOL)) $(call validate_value,WAVE,$(VALID_BOOL)) $(call validate_value,ISA,$(VALID_ISA)) $(call validate_value,HAVE_CSR,$(VALID_BOOL)) -$(call validate_value,PROG_TYPE,$(VALID_PROG_TYPE)) +$(call validate_value,APP,$(VALID_APP)) $(call validate_value,LINK_TYPE,$(VALID_LINK_TYPE)) ifeq ($(SYNTH),YOSYS) @@ -161,7 +163,7 @@ endif .PHONY: help config doctor setup setup-mpw setup-core setup-clusterip setup-ip setup-pdk setup-app \ clean-all purge-cache manifest check-warnings metrics check-metrics package \ - regress-pr regress-nightly sim-asm + regress-pr regress-nightly sim-asm sw-format sw-format-check sw-policy-check sw-host-test .NOTPARALLEL: setup help: @@ -178,6 +180,10 @@ help: ' config | manifest print/write the effective configuration' \ ' check-warnings | metrics analyze flow logs and reports' \ ' check-metrics apply the committed metrics policy' \ + ' sw-format apply clang-format to self-owned embedded C code' \ + ' sw-format-check check embedded C whitespace and line-ending policy' \ + ' sw-policy-check check embedded C API and naming policy' \ + ' sw-host-test run host tests for deterministic SDK utilities' \ ' regress-pr | regress-nightly run supported regression suites' \ ' package create checksummed source deliverables' \ ' clean | clean-all clean current flow or all build output' \ @@ -194,7 +200,7 @@ config: SIMU '$(SIMU)' SYNTH '$(SYNTH)' STA '$(STA)' PDK '$(PDK)' \ HAVE_PLL '$(HAVE_PLL)' HAVE_SRAM_IF '$(HAVE_SRAM_IF)' \ HAVE_SRAM_MACRO '$(HAVE_SRAM_MACRO)' HAVE_SVA '$(HAVE_SVA)' \ - ISA '$(ISA)' HAVE_CSR '$(HAVE_CSR)' PROG_TYPE '$(PROG_TYPE)' \ + ISA '$(ISA)' HAVE_CSR '$(HAVE_CSR)' APP '$(APP)' \ LINK_TYPE '$(LINK_TYPE)' doctor: @@ -251,6 +257,20 @@ check-metrics: metrics --policy $(ROOT_PATH)/quality/metrics/policy.json \ --baseline $(ROOT_PATH)/quality/metrics/baseline.json +sw-format: + python3 $(ROOT_PATH)/scripts/check_embedded_c.py --root $(ROOT_PATH) \ + --apply-format --clang-format $(CLANG_FORMAT) + +sw-format-check: + python3 $(ROOT_PATH)/scripts/check_embedded_c.py --root $(ROOT_PATH) --format-check \ + --clang-format-check --clang-format $(CLANG_FORMAT) + +sw-policy-check: + python3 $(ROOT_PATH)/scripts/check_embedded_c.py --root $(ROOT_PATH) --policy-check + +sw-host-test: + python3 $(ROOT_PATH)/scripts/run_c_tests.py --root $(ROOT_PATH) --cc $(HOST_CC) + package: $(MPW_VARIANT_STAMP) $(FILELIST_STAMP) manifest python3 $(ROOT_PATH)/scripts/package.py --root $(ROOT_PATH) --lock $(LOCK_FILE) \ --variant-root $(VARIANT_ROOT) --output-dir $(ROOT_PATH)/dist/$(VARIANT_ID) diff --git a/app/README.md b/app/README.md new file mode 100644 index 00000000..1496b610 --- /dev/null +++ b/app/README.md @@ -0,0 +1,87 @@ +# retroSoC Applications + +`app/` contains the firmware applications and the components assembled by those +applications. It builds on the freestanding SDK in [`../crt`](../crt) and keeps +application policy separate from common runtime and HAL code. + +## Layout + +| Path | Purpose | +| --- | --- | +| `apps/` | Selectable application profiles. Each profile owns `main.c` and an `app.mk` source manifest. | +| `board/` | Board-specific device drivers and public board headers. | +| `media/` | WAV, video, and visual-demo components with public media headers. | +| `middleware/` | Application middleware configuration and integration, including FatFs. | +| `network/` | Optional network or user-IP integration. | +| `ports/` | Ports and configuration for external libraries, such as LVGL. | +| `benchmark/` | Project integration for benchmark workloads, including CoreMark. | +| `asm/` | Standalone assembly firmware used by low-level simulation self-tests. | + +Versioned third-party source trees are managed by the setup flow. Do not +reformat or treat them as ordinary application code: use their integration +directory and setup tooling when updating FatFs, CoreMark, or LVGL. + +## Application Profiles + +The build selects an application with `APP=`. The supported profiles are: + +| Profile | Description | +| --- | --- | +| `bringup` | Minimal firmware used for startup and basic SoC regression. | +| `shell` | Interactive application that adds shell services, board drivers, media, FatFs, CoreMark, and UserIP integration. | + +The application manifest is loaded from `app/apps//app.mk`. It appends +`APP_SRCS` and, when necessary, `APP_INC_DIRS` to the SDK sources selected by +the central build. + +Build and simulate the supported profiles from the repository root: + +```sh +# Bringup firmware and Verilator simulation +make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk SIMU=VERILATOR firmware sim + +# Shell firmware and Verilator simulation +make CONFIG=configs/ci/hazard3-rv32im-ihp130-shell.mk SIMU=VERILATOR firmware sim +``` + +For a firmware-only build, omit `SIMU=VERILATOR sim`. + +## Adding an Application + +1. Create `app/apps//main.c` and `app/apps//app.mk`. +2. List the application-owned sources in `APP_SRCS` and export only required + include directories through `APP_INC_DIRS`. +3. Add `` to the allowed `APP` values in the top-level `Makefile`; this + keeps profile selection explicit and rejects misspellings. +4. Add a committed configuration profile under `configs/` that selects + `APP := ` and the required core, ISA, CSR, and linker options. +5. Add host tests for deterministic parsing or utility code, and add a + regression command when the application must execute in simulation. + +Applications should consume public SDK headers through ``. +Application-specific public headers belong below their own component include +directory, such as `board/include/retrosoc/board/` or +`media/include/retrosoc/media/`. + +## Quality Checks + +Run the shared checks from the repository root before submitting changes: + +```sh +make sw-format-check +make sw-policy-check +make sw-host-test +python3 -m pytest -q +``` + +The embedded-C checks apply to self-owned code and deliberately exclude managed +third-party source trees. Use the repository regression suites for end-to-end +firmware, RTL, netlist, synthesis, and timing coverage: + +```sh +make regress-pr +make regress-nightly +``` + +See the [repository README](../README.md) for prerequisites, supported +configurations, and build artifact locations. diff --git a/app/apps/bringup/app.mk b/app/apps/bringup/app.mk new file mode 100644 index 00000000..63379fee --- /dev/null +++ b/app/apps/bringup/app.mk @@ -0,0 +1 @@ +APP_SRCS += $(ROOT_PATH)/app/apps/bringup/main.c diff --git a/app/apps/bringup/main.c b/app/apps/bringup/main.c new file mode 100644 index 00000000..e1bd44ac --- /dev/null +++ b/app/apps/bringup/main.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +int main(void) { + uart0_init(CPU_FREQ, UART_BPS); + rs_app_info(); + ip_archinfo_test(0, 0); + return 0; +} diff --git a/app/apps/shell/app.mk b/app/apps/shell/app.mk new file mode 100644 index 00000000..1b3c7ec4 --- /dev/null +++ b/app/apps/shell/app.mk @@ -0,0 +1,17 @@ +APP_SRCS += $(ROOT_PATH)/app/apps/shell/main.c +APP_SRCS += $(ROOT_PATH)/crt/src/service/shell.c +APP_SRCS += $(ROOT_PATH)/crt/src/hal/i2s.c +APP_SRCS += $(ROOT_PATH)/app/board/src/at24cxx.c +APP_SRCS += $(ROOT_PATH)/app/board/src/pcf8563b.c +APP_SRCS += $(ROOT_PATH)/app/board/src/es8388.c +APP_SRCS += $(ROOT_PATH)/app/board/src/w25q128jvxim.c +APP_SRCS += $(ROOT_PATH)/app/media/src/wav_audio.c +APP_SRCS += $(ROOT_PATH)/app/media/src/video_player.c +APP_SRCS += $(ROOT_PATH)/app/media/src/donut.c + +APP_INC_DIRS += $(ROOT_PATH)/app/board/include +APP_INC_DIRS += $(ROOT_PATH)/app/media/include + +include $(ROOT_PATH)/app/middleware/fatfs/fatfs.mk +include $(ROOT_PATH)/app/benchmark/coremark/coremark.mk +include $(ROOT_PATH)/app/network/userip/userip.mk diff --git a/app/apps/shell/main.c b/app/apps/shell/main.c new file mode 100644 index 00000000..afb0da2b --- /dev/null +++ b/app/apps/shell/main.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void rs_app_info_command(int argc, char **argv) { + (void)argc; + (void)argv; + rs_app_info(); +} + +int main(void) { + uart0_init(CPU_FREQ, UART_BPS); + rs_booter(); + if (rs_i2c0_init((uint8_t)(CPU_FREQ / 2 - 1)) != RS_OK) { + return 1; + } + qspi_dev_init(); + lcd_init(); + + // lv_init(); + // tim1_init(); + // lv_tick_set_cb(my_get_millis); + + // lv_port_disp_init(); + + // lv_obj_t *label = lv_label_create(lv_scr_act()); + // lv_label_set_text(label,"Hello maksyuki!!!"); + // lv_obj_center(label); + + // while(1) { + // lv_timer_handler(); + // delay_ms(5); + // printf("hello\n"); + // } + + rs_shell_init(); + (void)rs_shell_register("app", "app info", true, rs_app_info_command); + (void)rs_shell_register("arch", "archinfo test", true, ip_archinfo_test); + (void)rs_shell_register("1wire", "1wire test", true, ip_1wire_test); + (void)rs_shell_register("tim", "timer test", true, ip_tim_test); + (void)rs_shell_register("gpio", "gpio test", true, ip_gpio_test); + (void)rs_shell_register("pwm", "pwm test", true, ip_pwm_test); + (void)rs_shell_register("rtc", "rtc test", true, ip_rtc_test); + (void)rs_shell_register("wdg", "wdg test", true, ip_wdg_test); + (void)rs_shell_register("rng", "rng test", true, ip_rng_test); + (void)rs_shell_register("crc", "crc test", true, ip_crc_test); + (void)rs_shell_register("ps2", "ps2 test", false, ip_ps2_test); + (void)rs_shell_register("lcd", "lcd test", true, ip_lcd_test); + (void)rs_shell_register("i2s", "i2s test", false, ip_i2s_test); + (void)rs_shell_register("nor", "nor flash test", false, ip_norflash_test); + (void)rs_shell_register("uart1", "uart1 test", false, ip_hpuart_test); + (void)rs_shell_register("pcf", "pcf8563b test", true, pcf8563b_test); +#ifdef CSR_ENABLE + (void)rs_shell_register("irq", "tmr/sw irq test", true, irq_test); +#endif + (void)rs_shell_register("donut", "donut test", false, donut_test); + rs_shell_batch_run(); + rs_shell_launch(); + // video_show(0x60000000); + // ip_norflash_test(); + // ip_lcd_test(0, NULL); + + // ip_spisd_read((uint32_t)0x51004000, (uint32_t)44); + // ip_spisd_test(); + // ip_dma_test(0, NULL); + // rs_bench(true, 0); + return 0; +} diff --git a/app/base/inc/at24cxx.h b/app/base/inc/at24cxx.h deleted file mode 100644 index 194196fc..00000000 --- a/app/base/inc/at24cxx.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef AT24C64_H__ -#define AT24C64_H__ - -#define I2C_TEST_NUM 24 -#define AT24C64_DEV_ADDR 0x50 - -void at24cxx_test(); - -#endif \ No newline at end of file diff --git a/app/base/inc/donut.h b/app/base/inc/donut.h deleted file mode 100644 index 7e28b137..00000000 --- a/app/base/inc/donut.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef DONUT_H__ -#define DONUT_H__ - -void donut_test(); - -#endif - diff --git a/app/base/inc/es8388.h b/app/base/inc/es8388.h deleted file mode 100644 index adc460af..00000000 --- a/app/base/inc/es8388.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ES8388_H__ -#define ES8388_H__ - -#define ES8388_DEV_ADDR 0x10 - -void es8388_init(); - -#endif \ No newline at end of file diff --git a/app/base/inc/pcf8563b.h b/app/base/inc/pcf8563b.h deleted file mode 100644 index d6b917ec..00000000 --- a/app/base/inc/pcf8563b.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef PCF8563B_H__ -#define PCF8563B_H__ - -#define PCF8563B_DEV_ADDR 0x51 - -#define PCF8563B_CTL_STATUS1 ((uint8_t)0x00) -#define PCF8563B_CTL_STATUS2 ((uint8_t)0x01) -#define PCF8563B_SECOND_REG ((uint8_t)0x02) -#define PCF8563B_MINUTE_REG ((uint8_t)0x03) -#define PCF8563B_HOUR_REG ((uint8_t)0x04) -#define PCF8563B_DAY_REG ((uint8_t)0x05) -#define PCF8563B_WEEKDAY_REG ((uint8_t)0x06) -#define PCF8563B_MONTH_REG ((uint8_t)0x07) -#define PCF8563B_YEAR_REG ((uint8_t)0x08) - -#define SECOND_MINUTE_REG_WIDTH ((uint8_t)0x7F) -#define HOUR_DAY_REG_WIDTH ((uint8_t)0x3F) -#define WEEKDAY_REG_WIDTH ((uint8_t)0x07) -#define MONTH_REG_WIDTH ((uint8_t)0x1F) -#define YEAR_REG_WIDTH ((uint8_t)0xFF) -#define BCD_Century ((uint8_t)0x80) - -typedef struct { - struct { - uint8_t second; - uint8_t minute; - uint8_t hour; - } time; - - struct { - uint8_t weekday; - uint8_t day; - uint8_t month; - uint8_t year; - } date; - -} PCF8563B_info_t; - -// helper functions -uint8_t pcf8563b_bcd2bin(uint8_t val,uint8_t reg_width); -uint8_t pcf8563b_bin2bcd(uint8_t val); - -void pcf8563b_wr_reg(PCF8563B_info_t *info); -PCF8563B_info_t pcf8563b_rd_reg(); - -void pcf8563b_test(int argc, char **argv); - -#endif diff --git a/app/base/inc/video_player.h b/app/base/inc/video_player.h deleted file mode 100644 index 0b5806b5..00000000 --- a/app/base/inc/video_player.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef VIDEO_PLAYER_H__ -#define VIDEO_PLAYER_H__ - -typedef struct { - uint32_t width; - uint32_t height; - uint32_t frame_count; - uint32_t reserved; -} VideoHeader_t; - - -void video_show(uint32_t addr); - -#endif \ No newline at end of file diff --git a/app/base/inc/w25q128jvxim.h b/app/base/inc/w25q128jvxim.h deleted file mode 100644 index 5482fd16..00000000 --- a/app/base/inc/w25q128jvxim.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef W25Q128JVXIM_H__ -#define W25Q128JVXIM_H__ - -void ip_norflash_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/app/base/inc/wav_audio.h b/app/base/inc/wav_audio.h deleted file mode 100644 index 45274f55..00000000 --- a/app/base/inc/wav_audio.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef WAV_AUDIO_H__ -#define WAV_AUDIO_H__ - -typedef struct { - char ChunkID[4]; - uint32_t ChunkSize; -} ChunkHeader_t; - -typedef struct { - char ChunkID[4]; // big endian - uint32_t ChunkSize; - char Format[4]; // big endian -} RIFFChunk_t; - -typedef struct { - char Subchunk1ID[4]; // big endian - uint32_t Subchunk1Size; - uint16_t AudioFormat; - uint16_t NumChannels; - uint32_t SampleRate; - uint32_t ByteRate; - uint16_t BlockAlign; - uint16_t BitsPerSample; -} FMTChunk_t; - -typedef struct { - char ChunkID[4]; - uint32_t ChunkSize; - char ChunkData[60]; // HACK: use flexible array + malloc -} LISTChunkItem_t; - -typedef struct { - char Subchunk2ID[4]; // big endian - uint32_t Subchunk2Size; -} DATAChunk_t; - -typedef struct { - RIFFChunk_t riff; - FMTChunk_t fmt; - DATAChunk_t data; - LISTChunkItem_t list[20]; - int info_num; -} WAVHeader_t; - - -// typedef struct { -// WAVHeader_t header; -// uint32_t addr; -// } WAVFile_t; - -typedef struct { - uint32_t addr; - uint32_t size; -} WAVFile_t; - -WAVFile_t wav_audio_parse(uint32_t start_addr); - -#endif \ No newline at end of file diff --git a/app/base/src/at24cxx.c b/app/base/src/at24cxx.c deleted file mode 100644 index 9c6e7a9d..00000000 --- a/app/base/src/at24cxx.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void at24cxx_test() { - printf("AT24C64 wr/rd test\n"); - // prepare ref data - uint8_t ref_data[I2C_TEST_NUM], rd_data[I2C_TEST_NUM]; - for(int i = 0; i < I2C_TEST_NUM; ++i) ref_data[i] = i; - // write AT24C64 - i2c0_wr_nbyte(AT24C64_DEV_ADDR, (uint16_t)0, I2C_DEV_ADDR_16BIT, I2C_TEST_NUM, ref_data); - // read AT24C64 - i2c0_rd_nbyte(AT24C64_DEV_ADDR, (uint16_t)0, I2C_DEV_ADDR_16BIT, I2C_TEST_NUM, rd_data); - // check data - for(int i = 0; i < I2C_TEST_NUM; ++i) { - printf("recv: %d expt: %d\n", rd_data[i], i); - if (rd_data[i] != i) printf("test fail\n"); - } - - i2c0_wr_nbyte(AT24C64_DEV_ADDR, (uint16_t)0, I2C_DEV_ADDR_16BIT, I2C_TEST_NUM, ref_data); - - printf("AT24C64 wr/rd test done\n"); -} diff --git a/app/base/src/donut.c b/app/base/src/donut.c deleted file mode 100644 index 9515ad42..00000000 --- a/app/base/src/donut.c +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2025 ECOS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// -- Adaptable modifications are redistributed under compatible License -- -// -// Copyright (c) 2023-2026 Yuchi Miao -// retroSoC is licensed under Mulan PSL v2. -// You can use this software according to the terms and conditions of the Mulan PSL v2. -// You may obtain a copy of Mulan PSL v2 at: -// http://license.coscl.org.cn/MulanPSL2 -// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -// See the Mulan PSL v2 for more details. - -#include -#include -#include -#include -#include - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#define GRAY_LEVELS 12 -// screen framebuffer (128x128) -#define scale_x 8 -#define scale_y 8 -#define DONUT_SIZE 16 -#define DONUT_WIDTH DONUT_SIZE * scale_x -#define DONUT_HEIGHT DONUT_SIZE * scale_y - -const uint32_t gray_colors[GRAY_LEVELS] = { - 0x00000000, // black (' ') - 0x10821082, // dark gray ('.') - 0x21042104, // Dark gray(',') - 0x31863186, // darker gray ('-') - 0x42084208, // medium dark gray ('~') - 0x528A528A, // medium gray(':') - 0x630C630C, // medium bright gray (';') - 0x738E738E, // lighter gray ('=') - 0x84108410, // bright gray('!') - 0x94929492, // very bright gray ('*') - 0xA514A514, // extremely bright gray ('#') - 0xB596B596 // brightest gray ('$') -}; - -uint32_t donut_framebuffer_32[DONUT_WIDTH * DONUT_HEIGHT]; - -// void screen_clear(void) { -// memset(donut_framebuffer_32, 0x00, sizeof(donut_framebuffer_32)); -// } - -// inline marco -#define R_OPT(mul,shift,x,y) \ - do { \ - int _temp = x; \ - x -= mul*y>>shift; \ - y += mul*_temp>>shift; \ - _temp = (3145728-x*x-y*y)>>11; \ - x = x*_temp>>10; \ - y = y*_temp>>10; \ - } while(0) - -// trigonometric function table (1024 = 1.0) - reserve 91 values -// static const int16_t sin_table[91] = { -// 0, 18, 36, 54, 71, 89, 107, 125, 143, 160, 178, 195, 213, 230, 248, 265, 282, 299, 316, 333, 350, 367, 384, 400, 416, 433, 449, 465, 481, 496, 512, 527, 542, 557, 572, 587, 601, 615, 629, 643, 657, 670, 683, 696, 709, 721, 733, 745, 757, 768, 779, 790, 801, 811, 821, 831, 841, 850, 859, 868, 876, 884, 892, 900, 907, 914, 921, 927, 933, 939, 945, 950, 955, 960, 964, 968, 972, 975, 978, 981, 984, 986, 988, 990, 991, 992, 993, 994, 994, 995, 995 -// }; - -// static const int16_t cos_table[91] = { -// 1024, 1023, 1023, 1022, 1021, 1019, 1017, 1014, 1011, 1007, 1003, 998, 993, 987, 981, 974, 967, 959, 951, 942, 933, 923, 913, 902, 891, 879, 867, 854, 841, 827, 813, 798, 783, 767, 751, 734, 717, 699, 681, 662, 643, 623, 603, 582, 561, 539, 517, 494, 471, 447, 423, 398, 373, 347, 321, 294, 267, 239, 211, 182, 153, 123, 93, 62, 31, 0, -31, -62, -93, -123, -153, -182, -211, -239, -267, -294, -321, -347, -373, -398, -423, -447, -471, -494, -517, -539, -561, -582, -603, -623, -643 -// }; - -static uint32_t pixel_buffer[DONUT_SIZE * DONUT_SIZE]; -static signed char z_buffer[DONUT_SIZE * DONUT_SIZE]; - -static inline void fast_pixel_write(uint32_t color, int x, int y) { - if (likely(x >= 0 && x < DONUT_SIZE && y >= 0 && y < DONUT_SIZE)) { - int index = y * DONUT_SIZE + x; - pixel_buffer[index] = color; - } -} - -static inline void fast_scaled_pixel_write(uint32_t color, int x, int y) { - if (likely(x >= 0 && x < DONUT_SIZE && y >= 0 && y < DONUT_SIZE)) { - int scaled_x = x * scale_x; - int scaled_y = y * scale_y; - - int base_index = scaled_y * DONUT_WIDTH + scaled_x; - - int row_index = base_index; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - row_index += DONUT_WIDTH; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - row_index += DONUT_WIDTH; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - row_index += DONUT_WIDTH; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - row_index += DONUT_WIDTH; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - row_index += DONUT_WIDTH; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - row_index += DONUT_WIDTH; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - row_index += DONUT_WIDTH; - donut_framebuffer_32[row_index/2] = color; - donut_framebuffer_32[row_index/2 + 1] = color; - donut_framebuffer_32[row_index/2 + 2] = color; - donut_framebuffer_32[row_index/2 + 3] = color; - - } -} - -void donut() { - register int sA = 1024, cA = 0, sB = 1024, cB = 0; - - const int R1 = 1, R2 = 1024, K2 = 4096*1024; - const int screen_center_x = DONUT_SIZE/2, screen_center_y = DONUT_SIZE/2; - const int scale_x_val = 12, scale_y_val = 12; - - while(1) { - // clean buffer - uint32_t *pixel_ptr = (uint32_t*)pixel_buffer; - uint32_t *z_ptr = (uint32_t*)z_buffer; - uint32_t *fb_ptr = (uint32_t*)donut_framebuffer_32; - - // clean zero - for (int i = 0; i < (DONUT_SIZE*DONUT_SIZE)/2; i++) { - pixel_ptr[i] = 0; - } - - // init z-buffer - for (int i = 0; i < (DONUT_SIZE*DONUT_SIZE)/4; i++) { - z_ptr[i] = 0x7F7F7F7F; // 127 in each byte - } - - // clean zero - for (int i = 0; i < (DONUT_WIDTH*DONUT_HEIGHT)/2; i++) { - fb_ptr[i] = 0; - } - - int sj = 0, cj = 1024; - for (int j = 0; j < 90; j++) { - int si = 0, ci = 1024; - - for (int i = 0; i < DONUT_SIZE*DONUT_SIZE; i++) { - int x0 = R1*cj + R2; - int x1 = ci*x0 >> 10; - int x2 = cA*sj >> 10; - int x3 = si*x0 >> 10; - int x4 = R1*x2 - (sA*x3 >> 10); - int x5 = sA*sj >> 10; - int x6 = K2 + R1*1024*x5 + cA*x3; - int x7 = cj*si >> 10; - - int x = screen_center_x + (scale_x_val*(cB*x1 - sB*x4)) / x6; - int y = screen_center_y + (scale_y_val*(cB*x4 + sB*x1)) / x6; - - int N = (((-cA*x7 - cB*((-sA*x7>>10) + x2) - ci*(cj*sB >> 10)) >> 10) - x5) >> 7; - - if (likely(y > 0 && y < DONUT_SIZE && x > 0 && x < DONUT_SIZE)) { - int o = x + DONUT_SIZE * y; - signed char zz = (x6-K2)>>15; - if (likely(zz < z_buffer[o])) { - z_buffer[o] = zz; - uint32_t color = gray_colors[N > 0 ? N : 0]; - pixel_buffer[o] = color; - } - } - R_OPT(5, 8, ci, si); - } - R_OPT(9, 7, cj, sj); - } - - R_OPT(5, 7, cA, sA); - R_OPT(5, 8, cB, sB); - for (int y = 0; y < DONUT_SIZE; y++) { - for (int x = 0; x < DONUT_SIZE; x++) { - int index = x + DONUT_SIZE * y; - uint32_t color = pixel_buffer[index]; - if (likely(color != 0)) { - fast_scaled_pixel_write(color, x, y); - } - } - } - - lcd_fill_image(0, 0, DONUT_WIDTH, DONUT_HEIGHT, donut_framebuffer_32); - } -} - -void donut_test(int argc, char **argv) { - (void) argc; - (void) argv; - - printf("donut test\n"); - donut(); -} diff --git a/app/base/src/pcf8563b.c b/app/base/src/pcf8563b.c deleted file mode 100644 index 5b967a86..00000000 --- a/app/base/src/pcf8563b.c +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -#include -#include -#include - -uint8_t pcf8563b_bin2bcd(uint8_t val) { - uint8_t bcdhigh = 0; - while (val >= 10) { - ++bcdhigh; - val -= 10; - } - return ((uint8_t)(bcdhigh << 4) | val); -} - -uint8_t pcf8563b_bcd2bin(uint8_t val,uint8_t reg_width) -{ - uint8_t res = 0; - res = (val & (reg_width & 0xF0)) >> 4; - res = res * 10 + (val & (reg_width & 0x0F)); - return res; -} - -void pcf8563b_wr_reg(PCF8563B_info_t *info) { - uint8_t wr_data[7] = {0}; - *wr_data = pcf8563b_bin2bcd(info->time.second); - *(wr_data + 1) = pcf8563b_bin2bcd(info->time.minute); - *(wr_data + 2) = pcf8563b_bin2bcd(info->time.hour); - *(wr_data + 3) = pcf8563b_bin2bcd(info->date.day); - *(wr_data + 4) = pcf8563b_bin2bcd(info->date.weekday); - *(wr_data + 5) = pcf8563b_bin2bcd(info->date.month); - *(wr_data + 6) = pcf8563b_bin2bcd(info->date.year); - i2c0_wr_nbyte(PCF8563B_DEV_ADDR, PCF8563B_SECOND_REG, I2C_DEV_ADDR_8BIT, 7, wr_data); -} - -PCF8563B_info_t pcf8563b_rd_reg() { - uint8_t rd_data[7] = {0}; - PCF8563B_info_t info = {0}; - i2c0_rd_nbyte(PCF8563B_DEV_ADDR, PCF8563B_SECOND_REG, I2C_DEV_ADDR_8BIT, 7, rd_data); - info.time.second = pcf8563b_bcd2bin(rd_data[0], SECOND_MINUTE_REG_WIDTH); - info.time.minute = pcf8563b_bcd2bin(rd_data[1], SECOND_MINUTE_REG_WIDTH); - info.time.hour = pcf8563b_bcd2bin(rd_data[2], HOUR_DAY_REG_WIDTH); - info.date.day = pcf8563b_bcd2bin(rd_data[3], HOUR_DAY_REG_WIDTH); - info.date.weekday = pcf8563b_bcd2bin(rd_data[4], WEEKDAY_REG_WIDTH); - info.date.month = pcf8563b_bcd2bin(rd_data[5], MONTH_REG_WIDTH); - info.date.year = pcf8563b_bcd2bin(rd_data[6], YEAR_REG_WIDTH); - return info; -} - -void pcf8563b_test(int argc, char **argv) { - (void) argc; - (void) argv; - - printf("PCF8563B test\n"); - PCF8563B_info_t init1_info = { - .time.second = 51, - .time.minute = 30, - .time.hour = 18, - .date.weekday = 3, - .date.day = 16, - .date.month = 9, - .date.year = 25 - }; - pcf8563b_wr_reg(&init1_info); - - PCF8563B_info_t rd_info = {0}; - for(int i = 0; i < 6; ++i) { - rd_info = pcf8563b_rd_reg(); - printf("[PCF8563B] %d-%d-%d %d %d:%d:%d\n", rd_info.date.year, rd_info.date.month, - rd_info.date.day, rd_info.date.weekday, - rd_info.time.hour, rd_info.time.minute, - rd_info.time.second); - delay_ms(1000); - } - - PCF8563B_info_t init2_info = { - .time.second = 23, - .time.minute = 22, - .time.hour = 12, - .date.weekday = 1, - .date.day = 19, - .date.month = 8, - .date.year = 24 - }; - pcf8563b_wr_reg(&init2_info); - for(int i = 0; i < 6; ++i) { - rd_info = pcf8563b_rd_reg(); - printf("[PCF8563B] %d-%d-%d %d %d:%d:%d\n", rd_info.date.year, rd_info.date.month, - rd_info.date.day, rd_info.date.weekday, - rd_info.time.hour, rd_info.time.minute, - rd_info.time.second); - delay_ms(1000); - } - - printf("PCF8563B test done\n"); -} diff --git a/app/base/src/video_player.c b/app/base/src/video_player.c deleted file mode 100644 index a8ead0cc..00000000 --- a/app/base/src/video_player.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -static VideoHeader_t video_header_parse(uint32_t addr) { - VideoHeader_t videoHeader; - spisd_mem_read((uint8_t *)&videoHeader, 1, sizeof(VideoHeader_t), addr); - - printf("================================\n"); - printf(" video bin file info \n"); - printf("width: %d\n", videoHeader.width); - printf("height: %d\n", videoHeader.height); - printf("frame count: %d\n", videoHeader.frame_count); - printf("================================\n"); - - return videoHeader; -} - - -void video_show(uint32_t addr) { - VideoHeader_t videoHeader = video_header_parse(addr); - uint32_t* ptr = (uint32_t*)(addr + 16); - uint32_t delta = videoHeader.width * videoHeader.height / 2; - - printf("addr: %x\n", addr); - for(uint32_t i = 0; i < videoHeader.frame_count; ++i) { - // lcd_addr_set(0, 0, 239, 134); // 240 - 1, 135 - 1 - // lcd_dc_set; - // qspi0_dma_xfer(ptr, delta); - lcd_fill_image(0, 0, videoHeader.width, videoHeader.height, ptr); - ptr += delta; - } -} diff --git a/app/base/src/w25q128jvxim.c b/app/base/src/w25q128jvxim.c deleted file mode 100644 index cb7377e8..00000000 --- a/app/base/src/w25q128jvxim.c +++ /dev/null @@ -1,364 +0,0 @@ -#include -#include -#include -#include -// #include -// #include - -static void norflash_spi_wr_en() { - uint32_t data[] = {0}; - - qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x06000000, - (uint32_t)0, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)0, (uint32_t)1, (uint32_t)2, - data); -} - -static void norflash_qpi_wr_en() { - uint32_t data[] = {0}; - - qspi0_wr((uint32_t)3, (uint32_t)1, (uint32_t)0x06000000, - (uint32_t)0, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)0, (uint32_t)1, (uint32_t)2, - data); -} - -static void norflash_spi_wr_data(uint32_t* data, uint32_t len) { - printf("len: %d\n", len); - qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x02000000, - (uint32_t)1, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)1, len, (uint32_t)4, - data); -} - -static void norflash_qspi_wr_data(uint32_t* data, uint32_t len) { - printf("len: %d\n", len); - qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x32000000, - (uint32_t)1, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)3, len, (uint32_t)4, - data); -} - -static void norflash_qpi_wr_data(uint32_t* data, uint32_t len) { - printf("len: %d\n", len); - qspi0_wr((uint32_t)3, (uint32_t)1, (uint32_t)0x02000000, - (uint32_t)3, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)3, len, (uint32_t)4, - data); -} - -static void norflash_spi_rd_data(uint32_t len) { - uint32_t data[64] = {0}; - - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x03000000, - (uint32_t)1, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)1, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); - - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x0B000000, - (uint32_t)1, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)8, - (uint32_t)1, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); -} - -static void norflash_dspi_rd_data(uint32_t len) { - printf("len: %d", len); - uint32_t data[64] = {0}; - - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x3B000000, - (uint32_t)1, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)8, - (uint32_t)2, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); - - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0xBB000000, - (uint32_t)2, (uint32_t)4, (uint32_t)0x000000F0, - (uint32_t)0, - (uint32_t)2, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); -} - -static void norflash_qspi_rd_data(uint32_t len) { - printf("len: %d", len); - uint32_t data[64] = {0}; - - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x6B000000, - (uint32_t)1, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)8, - (uint32_t)3, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); - - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0xEB000000, - (uint32_t)3, (uint32_t)4, (uint32_t)0x000000F0, - (uint32_t)4, - (uint32_t)3, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); -} - -static void norflash_qpi_rd_data(uint32_t len) { - printf("len: %d", len); - uint32_t data[64] = {0}; - - qspi0_rd((uint32_t)3, (uint32_t)1, (uint32_t)0x0B000000, - (uint32_t)3, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)2, - (uint32_t)3, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); - - qspi0_rd((uint32_t)3, (uint32_t)1, (uint32_t)0xEB000000, - (uint32_t)3, (uint32_t)4, (uint32_t)0x000000F0, - (uint32_t)4, - (uint32_t)3, len, (uint32_t)4, - data); - - printf("rd: "); - for(uint32_t i = 0; i < len; ++i) printf(" %x", data[i]); - printf("\n"); -} - -static void norflash_spi_id() { - // manu/dev id - uint32_t data[2]; - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x90000000, - (uint32_t)1, (uint32_t)3, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)1, (uint32_t)1, (uint32_t)2, - data); - printf("manu/dev id: %x\n", data[0]); - // uni id - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x4B000000, - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)32, - (uint32_t)1, (uint32_t)2, (uint32_t)4, - data); - printf("uni id: %x %x\n", data[0], data[1]); - // jedec id - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x9F000000, - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)1, (uint32_t)1, (uint32_t)3, - data); - printf("mem/cap id: %x\n", data[0]); -} - -static void norflash_dspi_id() { - // manu/dev id - uint32_t data[2]; - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x92000000, - (uint32_t)2, (uint32_t)4, (uint32_t)0x000000F0, - (uint32_t)0, - (uint32_t)2, (uint32_t)1, (uint32_t)2, - data); - printf("manu/dev id: %x\n", data[0]); -} - -static void norflash_qspi_id() { - uint32_t data[2]; - // manu/dev id - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x94000000, - (uint32_t)3, (uint32_t)4, (uint32_t)0x000000F0, - (uint32_t)4, - (uint32_t)3, (uint32_t)1, (uint32_t)2, - data); - printf("manu/dev id: %x\n", data[0]); -} - -static void norflash_qpi_id() { - uint32_t data[2]; - // jedec id - qspi0_rd((uint32_t)3, (uint32_t)1, (uint32_t)0x9F000000, - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)3, (uint32_t)1, (uint32_t)3, - data); - printf("mem/cap id: %x\n", data[0]); -} - -static void norflash_spi_status() { - uint32_t data[2]; - uint32_t cmd[] = {(uint32_t)0x05000000, (uint32_t)0x35000000, (uint32_t)0x15000000,}; - - for(int i = 0; i < 3; ++i) { - qspi0_rd((uint32_t)1, (uint32_t)1, cmd[i], - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)1, (uint32_t)1, (uint32_t)1, - data); - printf("status reg %d: %x\n", i, data[0]); - } -} - - -static void norflash_qpi_status() { - uint32_t data[2]; - uint32_t cmd[] = {(uint32_t)0x05000000, (uint32_t)0x35000000, (uint32_t)0x15000000,}; - - for(int i = 0; i < 3; ++i) { - qspi0_rd((uint32_t)3, (uint32_t)1, cmd[i], - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)3, (uint32_t)1, (uint32_t)1, - data); - printf("status reg %d: %x\n", i, data[0]); - } - - // qpis0_qpi_rd_data(val_list, dumlen=0, datalen=1); // 4-4-4(05/35/15h) -} - -static void norflash_enter_quad_mode() { - uint32_t data[] = {0}; - - qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x35000000, - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)1, (uint32_t)1, (uint32_t)1, - data); - - // set QE=1 in status reg 2 for QSPI/QPI - data[0] = (data[0] | 0x02) << 24; - printf("data[0]: %x\n", data[0]); - - norflash_spi_wr_en(); - qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x31000000, - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)1, (uint32_t)1, (uint32_t)1, - data); - - norflash_spi_status(); -} - -static void norflash_enter_qpi_mode() { - uint32_t data[] = {0}; - - norflash_spi_wr_en(); - qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x38000000, - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)0, (uint32_t)1, (uint32_t)1, - data); -} - -// need to assure in qpi mode before -static void norflash_quit_qpi_mode() { - uint32_t data[] = {0}; - - norflash_qpi_wr_en(); - qspi0_wr((uint32_t)3, (uint32_t)1, (uint32_t)0xFF000000, - (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, - (uint32_t)0, - (uint32_t)0, (uint32_t)1, (uint32_t)1, - data); -} - -static void norflash_spi_test() { - printf("\nnorflash spi test\n"); - uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; - - norflash_spi_id(); - norflash_spi_status(); - - norflash_spi_wr_en(); - norflash_spi_wr_data(wr_data, sizeof(wr_data)/sizeof(wr_data[0])); - norflash_spi_rd_data(sizeof(wr_data)/sizeof(wr_data[0])); -} - -static void norflash_dspi_test() { - printf("\nnorflash dspi test\n"); - uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; - - norflash_dspi_id(); - norflash_spi_wr_en(); - norflash_spi_wr_data(wr_data, sizeof(wr_data)/sizeof(wr_data[0])); - // rd - norflash_dspi_rd_data(sizeof(wr_data)/sizeof(wr_data[0])); -} - -static void norflash_qspi_test() { - printf("\nnorflash qspi test\n"); - uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; - - norflash_enter_quad_mode(); - norflash_qspi_id(); - - norflash_spi_wr_en(); - norflash_qspi_wr_data(wr_data, sizeof(wr_data)/sizeof(wr_data[0])); - // rd: - norflash_qspi_rd_data(sizeof(wr_data)/sizeof(wr_data[0])); -} - -static void norflash_qpi_test() { - printf("\nnorflash qpi test\n"); - uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; - - norflash_enter_quad_mode(); - norflash_enter_qpi_mode(); - norflash_qpi_id(); - norflash_qpi_status(); - - norflash_qpi_wr_en(); - norflash_qpi_wr_data(wr_data, sizeof(wr_data)/sizeof(wr_data[0])); - // rd - norflash_qpi_rd_data(sizeof(wr_data)/sizeof(wr_data[0])); - norflash_quit_qpi_mode(); -} - -void ip_norflash_test(int argc, char **argv) { - (void) argc; - (void) argv; - - printf("[NATV IP] qspi nor flash test\n"); - - QSPI0_InitStruct_t qspi0 = { - (uint32_t)0, - (uint32_t)0b0001, - (uint32_t)0, - (uint32_t)250, - (uint32_t)140, - (uint32_t)24, - (uint32_t)10, - (uint32_t)0, - }; - - qspi0_init(qspi0); - - norflash_spi_test(); - norflash_dspi_test(); - norflash_qspi_test(); - norflash_qpi_test(); -} diff --git a/app/base/src/wav_audio.c b/app/base/src/wav_audio.c deleted file mode 100644 index b37d5ba6..00000000 --- a/app/base/src/wav_audio.c +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static void printfln(char *buff, uint32_t len) { - for(uint32_t i = 0; i < len; ++i) printf("%c", buff[i]); - printf("\n"); -} - - -static void parseLISTChunk(WAVHeader_t *header, uint32_t addr) { - const char *info_tag[] = {"IART", "ICOP", "ICRD", "IGNR", "INAM", "IPRD", "IPRT", "ISFT", "ISRC", "ICMT", "ISBJ", "ITCH"}; - char info_tag_len = sizeof(info_tag) / sizeof(info_tag[0]); - ChunkHeader_t chunkHeader; - uint32_t info_num = 0; - - - // "LIST" - spisd_mem_read((uint8_t *)&chunkHeader, 1, sizeof(ChunkHeader_t), addr); - // printf("ChunkID: %.4s\n", chunkHeader.ChunkID); - uint32_t list_end = addr + chunkHeader.ChunkSize; - addr += sizeof(ChunkHeader_t); - - spisd_mem_read((uint8_t *)&chunkHeader, 1, sizeof(ChunkHeader_t) - 4, addr); - if (memcmp(chunkHeader.ChunkID, "INFO", 4) == 0) { - addr += 4; - while (addr < list_end) { - spisd_mem_read((uint8_t *)&chunkHeader, 1, sizeof(ChunkHeader_t), addr); - bool is_find = false; - for(int i = 0; i < info_tag_len; ++i) { - if (memcmp(chunkHeader.ChunkID, info_tag[i], 4) == 0) { - // printf("tag %.4s\n", chunkHeader.ChunkID); - // printf("ChunkID: %.4s\n", chunkHeader.ChunkID); - // printf("addr: %x\n", addr); - is_find = true; - spisd_mem_read((uint8_t *)&header->list[info_num++], 1, chunkHeader.ChunkSize + 8, addr); - addr += chunkHeader.ChunkSize + 8; - } - } - - if(!is_find) addr += 1; // for align the exten data - } - } - header->info_num = info_num; -} - - - -WAVFile_t wav_audio_parse(uint32_t start_addr) { - WAVHeader_t header; - ChunkHeader_t chunkHeader; - WAVFile_t res = {0, 0}; - - spisd_mem_read((uint8_t *)&header.riff, 1, sizeof(RIFFChunk_t), start_addr); - start_addr += sizeof(RIFFChunk_t); - - if (memcmp(header.riff.ChunkID, "RIFF", 4) != 0 || memcmp(header.riff.Format, "WAVE", 4) != 0) { - return res; - } - - while(1) { - spisd_mem_read((uint8_t *)&chunkHeader, 1, sizeof(ChunkHeader_t), start_addr); - // printf("start addr: %x\n", start_addr); - if (memcmp(chunkHeader.ChunkID, "fmt ", 4) == 0) { - spisd_mem_read((uint8_t *)&header.fmt, 1, sizeof(FMTChunk_t), start_addr); - start_addr += sizeof(FMTChunk_t); - } else if(memcmp(chunkHeader.ChunkID, "LIST", 4) == 0) { - parseLISTChunk(&header, start_addr); - start_addr += chunkHeader.ChunkSize + sizeof(ChunkHeader_t); - printf("start addr: %x\n", start_addr); - } else if(memcmp(chunkHeader.ChunkID, "data", 4) == 0) { - spisd_mem_read((uint8_t *)&header.data, 1, sizeof(DATAChunk_t), start_addr); - start_addr += sizeof(DATAChunk_t); - break; - } - } - - - // RIFF - printf("File size: %d bytes(~%d MiB)\n", header.riff.ChunkSize + 8, (header.riff.ChunkSize + 8) / 1024 / 1024); - printf("Format: %.4s\n", header.riff.Format); - // FMT - printf("AudioFormat: %d(PCM)\n", header.fmt.AudioFormat); // TODO: need to assign by looking up table - printf("NumChannels: %d channels\n", header.fmt.NumChannels); - printf("SampleRate: %d kHz\n", header.fmt.SampleRate); - printf("ByteRate: %d bps\n", header.fmt.ByteRate); - printf("BlockAlign: %d\n", header.fmt.BlockAlign); - printf("BitsPerSample: %d bits\n", header.fmt.BitsPerSample); - // LIST(optional) - for(int i = 0; i < header.info_num; ++i) { - printf("%.4s: ", header.list[i].ChunkID); - printfln(header.list[i].ChunkData, header.list[i].ChunkSize); - } - // data - printf("Data size: %d bytes(~%d MiB)\n", header.data.Subchunk2Size, (header.data.Subchunk2Size) / 1024 / 1024); - - res.addr = start_addr; - res.size = header.data.Subchunk2Size / 4; - return res; -} diff --git a/app/coremark/core_portme.c b/app/benchmark/coremark/core_portme.c similarity index 80% rename from app/coremark/core_portme.c rename to app/benchmark/coremark/core_portme.c index dc3a07a3..a092cc84 100644 --- a/app/coremark/core_portme.c +++ b/app/benchmark/coremark/core_portme.c @@ -18,7 +18,7 @@ Original Author: Shay Gal-on #include "coremark.h" #include "core_portme.h" #include -#include +#include #if VALIDATION_RUN volatile ee_s32 seed1_volatile = 0x3415; @@ -43,11 +43,10 @@ volatile ee_s32 seed5_volatile = 0; cpu clock cycles performance counter etc. Sample implementation for standard time.h and windows.h definitions included. */ -CORETIMETYPE -barebones_clock() -{ +static CORETIMETYPE barebones_clock(void) { return tim1_get_value(); -// #error // "You must implement a method to measure time in barebones_clock()! This function should return current time.\n" + // #error // "You must implement a method to measure time in barebones_clock()! This function + // should return current time.\n" } /* Define : TIMER_RES_DIVIDER Divider to trade off timer resolution and total time that can be @@ -57,12 +56,12 @@ barebones_clock() does not occur. If there are issues with the return value overflowing, increase this value. */ -#define CLOCKS_PER_SEC 72000000 -#define GETMYTIME(_t) (*_t = barebones_clock()) -#define MYTIMEDIFF(fin, ini) ((fin) - (ini)) -#define TIMER_RES_DIVIDER 1 +#define CLOCKS_PER_SEC 72000000 +#define GETMYTIME(_t) (*_t = barebones_clock()) +#define MYTIMEDIFF(fin, ini) ((fin) - (ini)) +#define TIMER_RES_DIVIDER 1 #define SAMPLE_TIME_IMPLEMENTATION 1 -#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER) +#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER) /** Define Host specific (POSIX), or target specific global time variables. */ static CORETIMETYPE start_time_val, stop_time_val; @@ -75,9 +74,7 @@ static CORETIMETYPE start_time_val, stop_time_val; example code) or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0. */ -void -start_time(void) -{ +void start_time(void) { GETMYTIME(&start_time_val); } /* Function : stop_time @@ -88,9 +85,7 @@ start_time(void) example code) or other system parameters - e.g. reading the current value of cpu cycles counter. */ -void -stop_time(void) -{ +void stop_time(void) { GETMYTIME(&stop_time_val); } /* Function : get_time @@ -103,10 +98,8 @@ stop_time(void) controlled by */ CORE_TICKS -get_time(void) -{ - CORE_TICKS elapsed - = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); +get_time(void) { + CORE_TICKS elapsed = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); return elapsed; } /* Function : time_in_secs @@ -116,9 +109,7 @@ get_time(void) floating point. Default implementation implemented by the EE_TICKS_PER_SEC macro above. */ -secs_ret -time_in_secs(CORE_TICKS ticks) -{ +secs_ret time_in_secs(CORE_TICKS ticks) { secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; return retval; } @@ -129,23 +120,19 @@ ee_u32 default_num_contexts = 1; Target specific initialization code Test for some common mistakes. */ -void -portable_init(core_portable *p, int *argc, char *argv[]) -{ - // #error "Call board initialization routines in portable init (if needed), in particular initialize UART!\n" +void portable_init(core_portable *p, int *argc, char *argv[]) { + // #error "Call board initialization routines in portable init (if needed), in particular + // initialize UART!\n" (void)argc; // prevent unused warning (void)argv; // prevent unused warning tim1_init(); - if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) - { - ee_printf( - "ERROR! Please define ee_ptr_int to a type that holds a " - "pointer!\n"); + if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) { + ee_printf("ERROR! Please define ee_ptr_int to a type that holds a " + "pointer!\n"); } - if (sizeof(ee_u32) != 4) - { + if (sizeof(ee_u32) != 4) { ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); } p->portable_id = 1; @@ -153,8 +140,6 @@ portable_init(core_portable *p, int *argc, char *argv[]) /* Function : portable_fini Target specific final code */ -void -portable_fini(core_portable *p) -{ +void portable_fini(core_portable *p) { p->portable_id = 0; } diff --git a/app/coremark/core_portme.h b/app/benchmark/coremark/core_portme.h similarity index 92% rename from app/coremark/core_portme.h rename to app/benchmark/coremark/core_portme.h index 3a3c7577..fa861696 100644 --- a/app/coremark/core_portme.h +++ b/app/benchmark/coremark/core_portme.h @@ -76,8 +76,7 @@ int core_main(void); #endif #endif #ifndef COMPILER_FLAGS -#define COMPILER_FLAGS \ - "-o3" /* "Please put compiler flags here (e.g. -o3)" */ +#define COMPILER_FLAGS "-o3" /* "Please put compiler flags here (e.g. -o3)" */ #endif #ifndef MEM_LOCATION #define MEM_LOCATION "STACK" @@ -91,14 +90,14 @@ int core_main(void); ee_ptr_int needs to be the data type used to hold pointers, otherwise coremark may fail!!! */ -typedef signed short ee_s16; +typedef signed short ee_s16; typedef unsigned short ee_u16; -typedef signed int ee_s32; -typedef double ee_f32; -typedef unsigned char ee_u8; -typedef unsigned int ee_u32; -typedef ee_u32 ee_ptr_int; -typedef size_t ee_size_t; +typedef signed int ee_s32; +typedef double ee_f32; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef ee_u32 ee_ptr_int; +typedef size_t ee_size_t; #define NULL ((void *)0) /* align_mem : This macro is used to align an offset to point to a 32b value. It is @@ -157,8 +156,8 @@ typedef ee_u32 CORE_TICKS; #ifndef MULTITHREAD #define MULTITHREAD 1 #define USE_PTHREAD 0 -#define USE_FORK 0 -#define USE_SOCKET 0 +#define USE_FORK 0 +#define USE_SOCKET 0 #endif /* Configuration : MAIN_HAS_NOARGC @@ -192,8 +191,7 @@ typedef ee_u32 CORE_TICKS; */ extern ee_u32 default_num_contexts; -typedef struct CORE_PORTABLE_S -{ +typedef struct CORE_PORTABLE_S { ee_u8 portable_id; } core_portable; @@ -201,8 +199,7 @@ typedef struct CORE_PORTABLE_S void portable_init(core_portable *p, int *argc, char *argv[]); void portable_fini(core_portable *p); -#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \ - && !defined(VALIDATION_RUN) +#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN) #if (TOTAL_DATA_SIZE == 1200) #define PROFILE_RUN 1 #elif (TOTAL_DATA_SIZE == 2000) diff --git a/app/benchmark/coremark/coremark.mk b/app/benchmark/coremark/coremark.mk new file mode 100644 index 00000000..daa91b9a --- /dev/null +++ b/app/benchmark/coremark/coremark.mk @@ -0,0 +1,9 @@ +APP_SRCS += $(ROOT_PATH)/app/coremark/coremark-main/core_main.c +APP_SRCS += $(ROOT_PATH)/app/coremark/coremark-main/core_list_join.c +APP_SRCS += $(ROOT_PATH)/app/coremark/coremark-main/core_matrix.c +APP_SRCS += $(ROOT_PATH)/app/coremark/coremark-main/core_state.c +APP_SRCS += $(ROOT_PATH)/app/coremark/coremark-main/core_util.c +APP_SRCS += $(ROOT_PATH)/app/benchmark/coremark/core_portme.c + +APP_INC_DIRS += $(ROOT_PATH)/app/coremark/coremark-main +APP_INC_DIRS += $(ROOT_PATH)/app/benchmark/coremark diff --git a/app/board/include/retrosoc/board/at24cxx.h b/app/board/include/retrosoc/board/at24cxx.h new file mode 100644 index 00000000..4b0a4dd9 --- /dev/null +++ b/app/board/include/retrosoc/board/at24cxx.h @@ -0,0 +1,9 @@ +#ifndef RETROSOC_BOARD_AT24CXX_H +#define RETROSOC_BOARD_AT24CXX_H + +#define I2C_TEST_NUM 24 +#define AT24C64_DEV_ADDR 0x50 + +void at24cxx_test(void); + +#endif diff --git a/app/board/include/retrosoc/board/es8388.h b/app/board/include/retrosoc/board/es8388.h new file mode 100644 index 00000000..3807955c --- /dev/null +++ b/app/board/include/retrosoc/board/es8388.h @@ -0,0 +1,8 @@ +#ifndef RETROSOC_BOARD_ES8388_H +#define RETROSOC_BOARD_ES8388_H + +#define ES8388_DEV_ADDR 0x10 + +void es8388_init(void); + +#endif diff --git a/app/board/include/retrosoc/board/pcf8563b.h b/app/board/include/retrosoc/board/pcf8563b.h new file mode 100644 index 00000000..11f9b4f6 --- /dev/null +++ b/app/board/include/retrosoc/board/pcf8563b.h @@ -0,0 +1,50 @@ +#ifndef RETROSOC_BOARD_PCF8563B_H +#define RETROSOC_BOARD_PCF8563B_H + +#include + +#define PCF8563B_DEV_ADDR 0x51 + +#define PCF8563B_CTL_STATUS1 ((uint8_t)0x00) +#define PCF8563B_CTL_STATUS2 ((uint8_t)0x01) +#define PCF8563B_SECOND_REG ((uint8_t)0x02) +#define PCF8563B_MINUTE_REG ((uint8_t)0x03) +#define PCF8563B_HOUR_REG ((uint8_t)0x04) +#define PCF8563B_DAY_REG ((uint8_t)0x05) +#define PCF8563B_WEEKDAY_REG ((uint8_t)0x06) +#define PCF8563B_MONTH_REG ((uint8_t)0x07) +#define PCF8563B_YEAR_REG ((uint8_t)0x08) + +#define SECOND_MINUTE_REG_WIDTH ((uint8_t)0x7F) +#define HOUR_DAY_REG_WIDTH ((uint8_t)0x3F) +#define WEEKDAY_REG_WIDTH ((uint8_t)0x07) +#define MONTH_REG_WIDTH ((uint8_t)0x1F) +#define YEAR_REG_WIDTH ((uint8_t)0xFF) +#define BCD_Century ((uint8_t)0x80) + +typedef struct { + struct { + uint8_t second; + uint8_t minute; + uint8_t hour; + } time; + + struct { + uint8_t weekday; + uint8_t day; + uint8_t month; + uint8_t year; + } date; + +} PCF8563B_info_t; + +// helper functions +uint8_t pcf8563b_bcd2bin(uint8_t val, uint8_t reg_width); +uint8_t pcf8563b_bin2bcd(uint8_t val); + +void pcf8563b_wr_reg(PCF8563B_info_t *info); +PCF8563B_info_t pcf8563b_rd_reg(void); + +void pcf8563b_test(int argc, char **argv); + +#endif diff --git a/app/board/include/retrosoc/board/w25q128jvxim.h b/app/board/include/retrosoc/board/w25q128jvxim.h new file mode 100644 index 00000000..aebeb39e --- /dev/null +++ b/app/board/include/retrosoc/board/w25q128jvxim.h @@ -0,0 +1,6 @@ +#ifndef RETROSOC_BOARD_W25Q128JVXIM_H +#define RETROSOC_BOARD_W25Q128JVXIM_H + +void ip_norflash_test(int argc, char **argv); + +#endif diff --git a/app/board/src/at24cxx.c b/app/board/src/at24cxx.c new file mode 100644 index 00000000..37880819 --- /dev/null +++ b/app/board/src/at24cxx.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +void at24cxx_test(void) { + printf("AT24C64 wr/rd test\n"); + // prepare ref data + uint8_t ref_data[I2C_TEST_NUM], rd_data[I2C_TEST_NUM]; + for (uint8_t i = 0U; i < I2C_TEST_NUM; ++i) { + ref_data[i] = i; + } + // write AT24C64 + if (rs_i2c0_write(AT24C64_DEV_ADDR, 0U, RS_I2C_DEVICE_ADDRESS_16BIT, I2C_TEST_NUM, ref_data, + RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("AT24C64 write timed out\n"); + return; + } + // read AT24C64 + if (rs_i2c0_read(AT24C64_DEV_ADDR, 0U, RS_I2C_DEVICE_ADDRESS_16BIT, I2C_TEST_NUM, rd_data, + RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("AT24C64 read timed out\n"); + return; + } + // check data + for (uint8_t i = 0U; i < I2C_TEST_NUM; ++i) { + printf("recv: %d expt: %d\n", rd_data[i], i); + if (rd_data[i] != i) + printf("test fail\n"); + } + + (void)rs_i2c0_write(AT24C64_DEV_ADDR, 0U, RS_I2C_DEVICE_ADDRESS_16BIT, I2C_TEST_NUM, ref_data, + RS_TIMEOUT_DEFAULT); + + printf("AT24C64 wr/rd test done\n"); +} diff --git a/app/base/src/es8388.c b/app/board/src/es8388.c similarity index 55% rename from app/base/src/es8388.c rename to app/board/src/es8388.c index cc8291ee..68f1a8c7 100644 --- a/app/base/src/es8388.c +++ b/app/board/src/es8388.c @@ -1,12 +1,12 @@ -#include -#include -#include -#include +#include +#include +#include +#include #define ES8388_PHONE_VOLUME 3 #define ES8388_SPEAK_VOLUME 3 -uint8_t es8388_init_cfg[] = { +static const uint8_t es8388_init_cfg[] = { (uint8_t)0, (uint8_t)0x80, (uint8_t)0, (uint8_t)0x00, (uint8_t)1, (uint8_t)0x58, @@ -38,16 +38,25 @@ uint8_t es8388_init_cfg[] = { (uint8_t)49, (uint8_t)ES8388_SPEAK_VOLUME, }; -void es8388_init() { - int init_cfg_len = sizeof(es8388_init_cfg)/sizeof(uint8_t); - printf("[ES8388] init cfg len: %d\n", init_cfg_len); - for(int i = 0; i < init_cfg_len; i += 2) { - i2c0_wr_nbyte(ES8388_DEV_ADDR, (uint16_t)es8388_init_cfg[i], I2C_DEV_ADDR_8BIT, 1, es8388_init_cfg + i + 1); +void es8388_init(void) { + const uint32_t init_cfg_len = sizeof(es8388_init_cfg) / sizeof(es8388_init_cfg[0]); + + printf("[ES8388] init cfg len: %u\n", init_cfg_len); + for (uint32_t i = 0U; i < init_cfg_len; i += 2U) { + if (rs_i2c0_write(ES8388_DEV_ADDR, (uint16_t)es8388_init_cfg[i], RS_I2C_DEVICE_ADDRESS_8BIT, + 1U, es8388_init_cfg + i + 1, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("[ES8388] write failed at register %d\n", es8388_init_cfg[i]); + return; + } } uint8_t rxdata[60] = {0}; - i2c0_rd_nbyte(ES8388_DEV_ADDR, (uint16_t)0, I2C_DEV_ADDR_8BIT, 53, rxdata); - for(int i = 0; i < 53; ++i) { + if (rs_i2c0_read(ES8388_DEV_ADDR, 0U, RS_I2C_DEVICE_ADDRESS_8BIT, 53U, rxdata, + RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("[ES8388] read failed\n"); + return; + } + for (uint32_t i = 0U; i < 53U; ++i) { printf("[ES8388] reg: %d val:%x\n", i, rxdata[i]); } } diff --git a/app/board/src/pcf8563b.c b/app/board/src/pcf8563b.c new file mode 100644 index 00000000..123846e4 --- /dev/null +++ b/app/board/src/pcf8563b.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +uint8_t pcf8563b_bin2bcd(uint8_t val) { + uint8_t bcdhigh = 0; + while (val >= 10) { + ++bcdhigh; + val -= 10; + } + return ((uint8_t)(bcdhigh << 4) | val); +} + +uint8_t pcf8563b_bcd2bin(uint8_t val, uint8_t reg_width) { + uint8_t res = 0; + res = (val & (reg_width & 0xF0)) >> 4; + res = res * 10 + (val & (reg_width & 0x0F)); + return res; +} + +void pcf8563b_wr_reg(PCF8563B_info_t *info) { + uint8_t wr_data[7] = {0}; + + if (info == NULL) { + return; + } + *wr_data = pcf8563b_bin2bcd(info->time.second); + *(wr_data + 1) = pcf8563b_bin2bcd(info->time.minute); + *(wr_data + 2) = pcf8563b_bin2bcd(info->time.hour); + *(wr_data + 3) = pcf8563b_bin2bcd(info->date.day); + *(wr_data + 4) = pcf8563b_bin2bcd(info->date.weekday); + *(wr_data + 5) = pcf8563b_bin2bcd(info->date.month); + *(wr_data + 6) = pcf8563b_bin2bcd(info->date.year); + if (rs_i2c0_write(PCF8563B_DEV_ADDR, PCF8563B_SECOND_REG, RS_I2C_DEVICE_ADDRESS_8BIT, 7U, + wr_data, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("[PCF8563B] write failed\n"); + } +} + +PCF8563B_info_t pcf8563b_rd_reg(void) { + uint8_t rd_data[7] = {0}; + PCF8563B_info_t info = {0}; + + if (rs_i2c0_read(PCF8563B_DEV_ADDR, PCF8563B_SECOND_REG, RS_I2C_DEVICE_ADDRESS_8BIT, 7U, + rd_data, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("[PCF8563B] read failed\n"); + return info; + } + info.time.second = pcf8563b_bcd2bin(rd_data[0], SECOND_MINUTE_REG_WIDTH); + info.time.minute = pcf8563b_bcd2bin(rd_data[1], SECOND_MINUTE_REG_WIDTH); + info.time.hour = pcf8563b_bcd2bin(rd_data[2], HOUR_DAY_REG_WIDTH); + info.date.day = pcf8563b_bcd2bin(rd_data[3], HOUR_DAY_REG_WIDTH); + info.date.weekday = pcf8563b_bcd2bin(rd_data[4], WEEKDAY_REG_WIDTH); + info.date.month = pcf8563b_bcd2bin(rd_data[5], MONTH_REG_WIDTH); + info.date.year = pcf8563b_bcd2bin(rd_data[6], YEAR_REG_WIDTH); + return info; +} + +void pcf8563b_test(int argc, char **argv) { + (void)argc; + (void)argv; + + printf("PCF8563B test\n"); + PCF8563B_info_t init1_info = {.time.second = 51, + .time.minute = 30, + .time.hour = 18, + .date.weekday = 3, + .date.day = 16, + .date.month = 9, + .date.year = 25}; + pcf8563b_wr_reg(&init1_info); + + PCF8563B_info_t rd_info = {0}; + for (int i = 0; i < 6; ++i) { + rd_info = pcf8563b_rd_reg(); + printf("[PCF8563B] %d-%d-%d %d %d:%d:%d\n", rd_info.date.year, rd_info.date.month, + rd_info.date.day, rd_info.date.weekday, rd_info.time.hour, rd_info.time.minute, + rd_info.time.second); + delay_ms(1000); + } + + PCF8563B_info_t init2_info = {.time.second = 23, + .time.minute = 22, + .time.hour = 12, + .date.weekday = 1, + .date.day = 19, + .date.month = 8, + .date.year = 24}; + pcf8563b_wr_reg(&init2_info); + for (int i = 0; i < 6; ++i) { + rd_info = pcf8563b_rd_reg(); + printf("[PCF8563B] %d-%d-%d %d %d:%d:%d\n", rd_info.date.year, rd_info.date.month, + rd_info.date.day, rd_info.date.weekday, rd_info.time.hour, rd_info.time.minute, + rd_info.time.second); + delay_ms(1000); + } + + printf("PCF8563B test done\n"); +} diff --git a/app/board/src/w25q128jvxim.c b/app/board/src/w25q128jvxim.c new file mode 100644 index 00000000..3e93f3a4 --- /dev/null +++ b/app/board/src/w25q128jvxim.c @@ -0,0 +1,299 @@ +#include +#include +#include +#include +#include +// #include +// #include + +static void norflash_spi_wr_en(void) { + uint32_t data[] = {0}; + + qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x06000000, (uint32_t)0, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)0, (uint32_t)1, (uint32_t)2, data); +} + +static void norflash_qpi_wr_en(void) { + uint32_t data[] = {0}; + + qspi0_wr((uint32_t)3, (uint32_t)1, (uint32_t)0x06000000, (uint32_t)0, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)0, (uint32_t)1, (uint32_t)2, data); +} + +static void norflash_spi_wr_data(uint32_t *data, uint32_t len) { + printf("len: %d\n", len); + qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x02000000, (uint32_t)1, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)1, len, (uint32_t)4, data); +} + +static void norflash_qspi_wr_data(uint32_t *data, uint32_t len) { + printf("len: %d\n", len); + qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x32000000, (uint32_t)1, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)3, len, (uint32_t)4, data); +} + +static void norflash_qpi_wr_data(uint32_t *data, uint32_t len) { + printf("len: %d\n", len); + qspi0_wr((uint32_t)3, (uint32_t)1, (uint32_t)0x02000000, (uint32_t)3, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)3, len, (uint32_t)4, data); +} + +static void norflash_spi_rd_data(uint32_t len) { + uint32_t data[64] = {0}; + + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x03000000, (uint32_t)1, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)1, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); + + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x0B000000, (uint32_t)1, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)8, (uint32_t)1, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); +} + +static void norflash_dspi_rd_data(uint32_t len) { + printf("len: %d", len); + uint32_t data[64] = {0}; + + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x3B000000, (uint32_t)1, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)8, (uint32_t)2, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); + + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0xBB000000, (uint32_t)2, (uint32_t)4, + (uint32_t)0x000000F0, (uint32_t)0, (uint32_t)2, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); +} + +static void norflash_qspi_rd_data(uint32_t len) { + printf("len: %d", len); + uint32_t data[64] = {0}; + + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x6B000000, (uint32_t)1, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)8, (uint32_t)3, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); + + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0xEB000000, (uint32_t)3, (uint32_t)4, + (uint32_t)0x000000F0, (uint32_t)4, (uint32_t)3, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); +} + +static void norflash_qpi_rd_data(uint32_t len) { + printf("len: %d", len); + uint32_t data[64] = {0}; + + qspi0_rd((uint32_t)3, (uint32_t)1, (uint32_t)0x0B000000, (uint32_t)3, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)2, (uint32_t)3, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); + + qspi0_rd((uint32_t)3, (uint32_t)1, (uint32_t)0xEB000000, (uint32_t)3, (uint32_t)4, + (uint32_t)0x000000F0, (uint32_t)4, (uint32_t)3, len, (uint32_t)4, data); + + printf("rd: "); + for (uint32_t i = 0; i < len; ++i) + printf(" %x", data[i]); + printf("\n"); +} + +static void norflash_spi_id(void) { + // manu/dev id + uint32_t data[2]; + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x90000000, (uint32_t)1, (uint32_t)3, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)1, (uint32_t)1, (uint32_t)2, data); + printf("manu/dev id: %x\n", data[0]); + // uni id + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x4B000000, (uint32_t)0, (uint32_t)0, + (uint32_t)0x00000000, (uint32_t)32, (uint32_t)1, (uint32_t)2, (uint32_t)4, data); + printf("uni id: %x %x\n", data[0], data[1]); + // jedec id + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x9F000000, (uint32_t)0, (uint32_t)0, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)1, (uint32_t)1, (uint32_t)3, data); + printf("mem/cap id: %x\n", data[0]); +} + +static void norflash_dspi_id(void) { + // manu/dev id + uint32_t data[2]; + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x92000000, (uint32_t)2, (uint32_t)4, + (uint32_t)0x000000F0, (uint32_t)0, (uint32_t)2, (uint32_t)1, (uint32_t)2, data); + printf("manu/dev id: %x\n", data[0]); +} + +static void norflash_qspi_id(void) { + uint32_t data[2]; + // manu/dev id + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x94000000, (uint32_t)3, (uint32_t)4, + (uint32_t)0x000000F0, (uint32_t)4, (uint32_t)3, (uint32_t)1, (uint32_t)2, data); + printf("manu/dev id: %x\n", data[0]); +} + +static void norflash_qpi_id(void) { + uint32_t data[2]; + // jedec id + qspi0_rd((uint32_t)3, (uint32_t)1, (uint32_t)0x9F000000, (uint32_t)0, (uint32_t)0, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)3, (uint32_t)1, (uint32_t)3, data); + printf("mem/cap id: %x\n", data[0]); +} + +static void norflash_spi_status(void) { + uint32_t data[2]; + uint32_t cmd[] = { + (uint32_t)0x05000000, + (uint32_t)0x35000000, + (uint32_t)0x15000000, + }; + + for (int i = 0; i < 3; ++i) { + qspi0_rd((uint32_t)1, (uint32_t)1, cmd[i], (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, + (uint32_t)0, (uint32_t)1, (uint32_t)1, (uint32_t)1, data); + printf("status reg %d: %x\n", i, data[0]); + } +} + +static void norflash_qpi_status(void) { + uint32_t data[2]; + uint32_t cmd[] = { + (uint32_t)0x05000000, + (uint32_t)0x35000000, + (uint32_t)0x15000000, + }; + + for (int i = 0; i < 3; ++i) { + qspi0_rd((uint32_t)3, (uint32_t)1, cmd[i], (uint32_t)0, (uint32_t)0, (uint32_t)0x00000000, + (uint32_t)0, (uint32_t)3, (uint32_t)1, (uint32_t)1, data); + printf("status reg %d: %x\n", i, data[0]); + } + + // qpis0_qpi_rd_data(val_list, dumlen=0, datalen=1); // 4-4-4(05/35/15h) +} + +static void norflash_enter_quad_mode(void) { + uint32_t data[] = {0}; + + qspi0_rd((uint32_t)1, (uint32_t)1, (uint32_t)0x35000000, (uint32_t)0, (uint32_t)0, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)1, (uint32_t)1, (uint32_t)1, data); + + // set QE=1 in status reg 2 for QSPI/QPI + data[0] = (data[0] | 0x02) << 24; + printf("data[0]: %x\n", data[0]); + + norflash_spi_wr_en(); + qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x31000000, (uint32_t)0, (uint32_t)0, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)1, (uint32_t)1, (uint32_t)1, data); + + norflash_spi_status(); +} + +static void norflash_enter_qpi_mode(void) { + uint32_t data[] = {0}; + + norflash_spi_wr_en(); + qspi0_wr((uint32_t)1, (uint32_t)1, (uint32_t)0x38000000, (uint32_t)0, (uint32_t)0, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)0, (uint32_t)1, (uint32_t)1, data); +} + +// need to assure in qpi mode before +static void norflash_quit_qpi_mode(void) { + uint32_t data[] = {0}; + + norflash_qpi_wr_en(); + qspi0_wr((uint32_t)3, (uint32_t)1, (uint32_t)0xFF000000, (uint32_t)0, (uint32_t)0, + (uint32_t)0x00000000, (uint32_t)0, (uint32_t)0, (uint32_t)1, (uint32_t)1, data); +} + +static void norflash_spi_test(void) { + printf("\nnorflash spi test\n"); + uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; + + norflash_spi_id(); + norflash_spi_status(); + + norflash_spi_wr_en(); + norflash_spi_wr_data(wr_data, sizeof(wr_data) / sizeof(wr_data[0])); + norflash_spi_rd_data(sizeof(wr_data) / sizeof(wr_data[0])); +} + +static void norflash_dspi_test(void) { + printf("\nnorflash dspi test\n"); + uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; + + norflash_dspi_id(); + norflash_spi_wr_en(); + norflash_spi_wr_data(wr_data, sizeof(wr_data) / sizeof(wr_data[0])); + // rd + norflash_dspi_rd_data(sizeof(wr_data) / sizeof(wr_data[0])); +} + +static void norflash_qspi_test(void) { + printf("\nnorflash qspi test\n"); + uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; + + norflash_enter_quad_mode(); + norflash_qspi_id(); + + norflash_spi_wr_en(); + norflash_qspi_wr_data(wr_data, sizeof(wr_data) / sizeof(wr_data[0])); + // rd: + norflash_qspi_rd_data(sizeof(wr_data) / sizeof(wr_data[0])); +} + +static void norflash_qpi_test(void) { + printf("\nnorflash qpi test\n"); + uint32_t wr_data[] = {0x23456788, 0x00FFEE30, 0x418461AB, 0xC252DE21, 0x00550022, 0x00002266}; + + norflash_enter_quad_mode(); + norflash_enter_qpi_mode(); + norflash_qpi_id(); + norflash_qpi_status(); + + norflash_qpi_wr_en(); + norflash_qpi_wr_data(wr_data, sizeof(wr_data) / sizeof(wr_data[0])); + // rd + norflash_qpi_rd_data(sizeof(wr_data) / sizeof(wr_data[0])); + norflash_quit_qpi_mode(); +} + +void ip_norflash_test(int argc, char **argv) { + (void)argc; + (void)argv; + + printf("[NATV IP] qspi nor flash test\n"); + + QSPI0_InitStruct_t qspi0 = { + (uint32_t)0, (uint32_t)0b0001, (uint32_t)0, (uint32_t)250, + (uint32_t)140, (uint32_t)24, (uint32_t)10, (uint32_t)0, + }; + + qspi0_init(qspi0); + + norflash_spi_test(); + norflash_dspi_test(); + norflash_qspi_test(); + norflash_qpi_test(); +} diff --git a/app/coremark/coremark.mk b/app/coremark/coremark.mk deleted file mode 100644 index 6952d001..00000000 --- a/app/coremark/coremark.mk +++ /dev/null @@ -1,9 +0,0 @@ -APP_PATH += $(ROOT_PATH)/app/coremark/coremark-main/core_main.c -APP_PATH += $(ROOT_PATH)/app/coremark/coremark-main/core_list_join.c -APP_PATH += $(ROOT_PATH)/app/coremark/coremark-main/core_matrix.c -APP_PATH += $(ROOT_PATH)/app/coremark/coremark-main/core_state.c -APP_PATH += $(ROOT_PATH)/app/coremark/coremark-main/core_util.c -APP_PATH += $(ROOT_PATH)/app/coremark/core_portme.c - -INC_PATH += -I$(ROOT_PATH)/app/coremark/coremark-main -INC_PATH += -I$(ROOT_PATH)/app/coremark \ No newline at end of file diff --git a/app/fatfs/diskio.c b/app/fatfs/diskio.c deleted file mode 100644 index 1d4f2436..00000000 --- a/app/fatfs/diskio.c +++ /dev/null @@ -1,173 +0,0 @@ -/*-----------------------------------------------------------------------*/ -/* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2025 */ -/*-----------------------------------------------------------------------*/ -/* If a working storage control module is available, it should be */ -/* attached to the FatFs via a glue function rather than modifying it. */ -/* This is an example of glue functions to attach various exsisting */ -/* storage control modules to the FatFs module with a defined API. */ -/*-----------------------------------------------------------------------*/ - -#include "ff.h" /* Basic definitions of FatFs */ -#include "diskio.h" /* Declarations FatFs MAI */ -#include - -#define DEV_TF 0 /* Map MMC/SD card to physical drive 1 */ -#define SD_BLOCKSIZE 512 -/*-----------------------------------------------------------------------*/ -/* Get Drive Status */ -/*-----------------------------------------------------------------------*/ -DSTATUS disk_status ( - BYTE pdrv /* Physical drive nmuber to identify the drive */ -) -{ - DSTATUS status = STA_NOINIT; - switch (pdrv) { - case DEV_TF: - status &= ~STA_NOINIT; - break; - default: - status = STA_NOINIT; - } - return status; -} - - -/*-----------------------------------------------------------------------*/ -/* Inidialize a Drive */ -/*-----------------------------------------------------------------------*/ -DSTATUS disk_initialize ( - BYTE pdrv /* Physical drive nmuber to identify the drive */ -) -{ - DSTATUS status = STA_NOINIT; - switch (pdrv) { - case DEV_TF: - status &= ~STA_NOINIT; - break; - default: - status = STA_NOINIT; - } - return status; -} - -/*-----------------------------------------------------------------------*/ -/* Read Sector(s) */ -/*-----------------------------------------------------------------------*/ -DRESULT disk_read ( - BYTE pdrv, /* Physical drive nmuber to identify the drive */ - BYTE *buff, /* Data buffer to store read data */ - LBA_t sector, /* Start sector in LBA */ - UINT count /* Number of sectors to read */ -) -{ - DRESULT status = RES_PARERR; - - if (!count) return RES_PARERR; /* Check parameter */ - switch (pdrv) { - case DEV_TF: - // if ((DWORD)buff&3) { - // DRESULT res = RES_OK; - // DWORD scratch[SD_BLOCKSIZE / 4]; - // while (count--) { - // res = disk_read(DEV_TF, (void *)scratch, sector++, 1); - // if (res != RES_OK) { - // break; - // } - // memcpy(buff, scratch, SD_BLOCKSIZE); - // buff += SD_BLOCKSIZE; - // } - // return res; - // } - spisd_sector_read(buff, sector, count); - status = RES_OK; - break; - default: - status = RES_PARERR; - } - return status; - - return status; -} - - - -/*-----------------------------------------------------------------------*/ -/* Write Sector(s) */ -/*-----------------------------------------------------------------------*/ -#if FF_FS_READONLY == 0 - - - -DRESULT disk_write ( - BYTE pdrv, /* Physical drive nmuber to identify the drive */ - const BYTE *buff, /* Data to be written */ - LBA_t sector, /* Start sector in LBA */ - UINT count /* Number of sectors to write */ -) -{ - DRESULT status = RES_PARERR; - - if (!count) return RES_PARERR; /* Check parameter */ - switch (pdrv) { - case DEV_TF: - spisd_sector_write(buff, sector, count); - status = RES_OK; - break; - default: - status = RES_PARERR; - } - return status; - - return status; -} - -#endif - - -/*-----------------------------------------------------------------------*/ -/* Miscellaneous Functions */ -/*-----------------------------------------------------------------------*/ - -DRESULT disk_ioctl ( - BYTE pdrv, /* Physical drive nmuber (0..) */ - BYTE cmd, /* Control code */ - void *buff /* Buffer to send/receive control data */ -) -{ - DRESULT status = RES_PARERR; - - switch (pdrv) { - case DEV_TF: - switch(cmd) { - case GET_SECTOR_SIZE: - *(WORD * )buff = SD_BLOCKSIZE; - break; - case GET_SECTOR_COUNT: - *(DWORD * )buff = 524288 * 4; // 1024MiB(mem access) - break; - case GET_BLOCK_SIZE: - *(WORD * )buff = 1; - break; - case CTRL_SYNC: - spisd_sector_sync(); - break; - } - status = RES_OK; - break; - default: - status = RES_PARERR; - } - return status; - - return status; -} - -DWORD get_fattime(void) { - // HACK: - return ((DWORD)(2025 - 1980) << 25) /* Year 2025 */ - | ((DWORD)1 << 21) /* Month 1 */ - | ((DWORD)1 << 16) /* Mday 1 */ - | ((DWORD)0 << 11) /* Hour 0 */ - | ((DWORD)0 << 5) /* Min 0 */ - | ((DWORD)0 >> 1); /* Sec 0 */ -} diff --git a/app/fatfs/fatfs.mk b/app/fatfs/fatfs.mk deleted file mode 100644 index a1040069..00000000 --- a/app/fatfs/fatfs.mk +++ /dev/null @@ -1,6 +0,0 @@ -APP_PATH += $(ROOT_PATH)/app/fatfs/ff16/source/diskio.c -APP_PATH += $(ROOT_PATH)/app/fatfs/ff16/source/ff.c -APP_PATH += $(ROOT_PATH)/app/fatfs/ff16/source/ffsystem.c -APP_PATH += $(ROOT_PATH)/app/fatfs/ff16/source/ffunicode.c - -INC_PATH += -I$(ROOT_PATH)/app/fatfs/ff16/source \ No newline at end of file diff --git a/app/lvgl/lvgl.mk b/app/lvgl/lvgl.mk deleted file mode 100644 index a2ec2c41..00000000 --- a/app/lvgl/lvgl.mk +++ /dev/null @@ -1,10 +0,0 @@ -APP_PATH += $(shell find $(ROOT_PATH)/app/lvgl/lvgl-main/src -type f -name '*.c') -APP_PATH += $(ROOT_PATH)/app/lvgl/lv_port_disp.c -APP_PATH += $(ROOT_PATH)/crt/libgcc/clzsi2.c -APP_PATH += $(ROOT_PATH)/crt/libgcc/ffssi2.c -APP_PATH += $(ROOT_PATH)/crt/libgcc/udivdi3.c -APP_PATH += $(ROOT_PATH)/crt/libgcc/divdi3.c -APP_PATH += $(ROOT_PATH)/crt/libgcc/umoddi3.c - -INC_PATH += -I$(ROOT_PATH)/app/lvgl/lvgl-main/ -INC_PATH += -I$(ROOT_PATH)/app/lvgl/ \ No newline at end of file diff --git a/app/media/include/retrosoc/media/donut.h b/app/media/include/retrosoc/media/donut.h new file mode 100644 index 00000000..e39118e5 --- /dev/null +++ b/app/media/include/retrosoc/media/donut.h @@ -0,0 +1,8 @@ +#ifndef RETROSOC_MEDIA_DONUT_H +#define RETROSOC_MEDIA_DONUT_H + +#include + +void donut_test(int argc, char **argv); + +#endif diff --git a/app/media/include/retrosoc/media/video_player.h b/app/media/include/retrosoc/media/video_player.h new file mode 100644 index 00000000..e4bc3d5b --- /dev/null +++ b/app/media/include/retrosoc/media/video_player.h @@ -0,0 +1,20 @@ +#ifndef RETROSOC_MEDIA_VIDEO_PLAYER_H +#define RETROSOC_MEDIA_VIDEO_PLAYER_H + +#include +#include + +#include + +typedef struct { + uint32_t width; + uint32_t height; + uint32_t frame_count; + uint32_t payload_offset; + uint32_t frame_size; +} rs_video_info_t; + +rs_status_t rs_video_parse(const void *data, size_t data_size, rs_video_info_t *info); +rs_status_t rs_video_show_spisd(uintptr_t start_address, uint32_t available_size); + +#endif diff --git a/app/media/include/retrosoc/media/wav_audio.h b/app/media/include/retrosoc/media/wav_audio.h new file mode 100644 index 00000000..90e7da70 --- /dev/null +++ b/app/media/include/retrosoc/media/wav_audio.h @@ -0,0 +1,33 @@ +#ifndef RETROSOC_MEDIA_WAV_AUDIO_H +#define RETROSOC_MEDIA_WAV_AUDIO_H + +#include +#include + +#include + +typedef rs_status_t (*rs_wav_read_fn)(void *context, uint32_t offset, void *buffer, + size_t byte_count); + +typedef struct { + rs_wav_read_fn read; + void *context; + uint32_t size; +} rs_wav_reader_t; + +typedef struct { + uint16_t audio_format; + uint16_t channel_count; + uint32_t sample_rate; + uint32_t byte_rate; + uint16_t block_align; + uint16_t bits_per_sample; + uint32_t data_offset; + uint32_t data_size; +} rs_wav_info_t; + +rs_status_t rs_wav_parse(const rs_wav_reader_t *reader, rs_wav_info_t *info); +rs_status_t rs_wav_parse_spisd(uintptr_t start_address, uint32_t available_size, + rs_wav_info_t *info); + +#endif diff --git a/app/media/src/donut.c b/app/media/src/donut.c new file mode 100644 index 00000000..36c8d4f9 --- /dev/null +++ b/app/media/src/donut.c @@ -0,0 +1,229 @@ +// Copyright 2025 ECOS Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// -- Adaptable modifications are redistributed under compatible License -- +// +// Copyright (c) 2023-2026 Yuchi Miao +// retroSoC is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#include +#include +#include +#include +#include +#include + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#define GRAY_LEVELS 12 +// screen framebuffer (128x128) +#define scale_x 8 +#define scale_y 8 +#define DONUT_SIZE 16 +#define DONUT_WIDTH DONUT_SIZE *scale_x +#define DONUT_HEIGHT DONUT_SIZE *scale_y +#define RS_DONUT_FRAME_COUNT 300U + +static const uint32_t gray_colors[GRAY_LEVELS] = { + 0x00000000, // black (' ') + 0x10821082, // dark gray ('.') + 0x21042104, // Dark gray(',') + 0x31863186, // darker gray ('-') + 0x42084208, // medium dark gray ('~') + 0x528A528A, // medium gray(':') + 0x630C630C, // medium bright gray (';') + 0x738E738E, // lighter gray ('=') + 0x84108410, // bright gray('!') + 0x94929492, // very bright gray ('*') + 0xA514A514, // extremely bright gray ('#') + 0xB596B596 // brightest gray ('$') +}; + +static uint32_t donut_framebuffer_32[DONUT_WIDTH * DONUT_HEIGHT]; + +// void screen_clear(void) { +// memset(donut_framebuffer_32, 0x00, sizeof(donut_framebuffer_32)); +// } + +// inline marco +#define R_OPT(mul, shift, x, y) \ + do { \ + int _temp = x; \ + x -= mul * y >> shift; \ + y += mul * _temp >> shift; \ + _temp = (3145728 - x * x - y * y) >> 11; \ + x = x * _temp >> 10; \ + y = y * _temp >> 10; \ + } while (0) + +// trigonometric function table (1024 = 1.0) - reserve 91 values +// static const int16_t sin_table[91] = { +// 0, 18, 36, 54, 71, 89, 107, 125, 143, 160, 178, 195, 213, 230, 248, 265, 282, 299, 316, 333, +// 350, 367, 384, 400, 416, 433, 449, 465, 481, 496, 512, 527, 542, 557, 572, 587, 601, 615, +// 629, 643, 657, 670, 683, 696, 709, 721, 733, 745, 757, 768, 779, 790, 801, 811, 821, 831, +// 841, 850, 859, 868, 876, 884, 892, 900, 907, 914, 921, 927, 933, 939, 945, 950, 955, 960, +// 964, 968, 972, 975, 978, 981, 984, 986, 988, 990, 991, 992, 993, 994, 994, 995, 995 +// }; + +// static const int16_t cos_table[91] = { +// 1024, 1023, 1023, 1022, 1021, 1019, 1017, 1014, 1011, 1007, 1003, 998, 993, 987, 981, 974, +// 967, 959, 951, 942, 933, 923, 913, 902, 891, 879, 867, 854, 841, 827, 813, 798, 783, 767, +// 751, 734, 717, 699, 681, 662, 643, 623, 603, 582, 561, 539, 517, 494, 471, 447, 423, 398, +// 373, 347, 321, 294, 267, 239, 211, 182, 153, 123, 93, 62, 31, 0, -31, -62, -93, -123, -153, +// -182, -211, -239, -267, -294, -321, -347, -373, -398, -423, -447, -471, -494, -517, -539, +// -561, -582, -603, -623, -643 +// }; + +static uint32_t pixel_buffer[DONUT_SIZE * DONUT_SIZE]; +static signed char z_buffer[DONUT_SIZE * DONUT_SIZE]; + +static inline void fast_scaled_pixel_write(uint32_t color, int x, int y) { + if (likely(x >= 0 && x < DONUT_SIZE && y >= 0 && y < DONUT_SIZE)) { + int scaled_x = x * scale_x; + int scaled_y = y * scale_y; + + int base_index = scaled_y * DONUT_WIDTH + scaled_x; + + int row_index = base_index; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + + row_index += DONUT_WIDTH; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + + row_index += DONUT_WIDTH; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + + row_index += DONUT_WIDTH; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + + row_index += DONUT_WIDTH; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + + row_index += DONUT_WIDTH; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + + row_index += DONUT_WIDTH; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + + row_index += DONUT_WIDTH; + donut_framebuffer_32[row_index / 2] = color; + donut_framebuffer_32[row_index / 2 + 1] = color; + donut_framebuffer_32[row_index / 2 + 2] = color; + donut_framebuffer_32[row_index / 2 + 3] = color; + } +} + +static void rs_donut_render(uint32_t frame_count) { + int sA = 1024; + int cA = 0; + int sB = 1024; + int cB = 0; + + const int R1 = 1, R2 = 1024, K2 = 4096 * 1024; + const int screen_center_x = DONUT_SIZE / 2, screen_center_y = DONUT_SIZE / 2; + const int scale_x_val = 12, scale_y_val = 12; + + for (uint32_t frame = 0U; frame < frame_count; ++frame) { + (void)memset(pixel_buffer, 0, sizeof(pixel_buffer)); + (void)memset(z_buffer, 0x7F, sizeof(z_buffer)); + (void)memset(donut_framebuffer_32, 0, sizeof(donut_framebuffer_32)); + + int sj = 0, cj = 1024; + for (int j = 0; j < 90; j++) { + int si = 0, ci = 1024; + + for (int i = 0; i < DONUT_SIZE * DONUT_SIZE; i++) { + int x0 = R1 * cj + R2; + int x1 = ci * x0 >> 10; + int x2 = cA * sj >> 10; + int x3 = si * x0 >> 10; + int x4 = R1 * x2 - (sA * x3 >> 10); + int x5 = sA * sj >> 10; + int x6 = K2 + R1 * 1024 * x5 + cA * x3; + int x7 = cj * si >> 10; + + int x = screen_center_x + (scale_x_val * (cB * x1 - sB * x4)) / x6; + int y = screen_center_y + (scale_y_val * (cB * x4 + sB * x1)) / x6; + + int N = (((-cA * x7 - cB * ((-sA * x7 >> 10) + x2) - ci * (cj * sB >> 10)) >> 10) - + x5) >> + 7; + + if (likely(y > 0 && y < DONUT_SIZE && x > 0 && x < DONUT_SIZE)) { + int o = x + DONUT_SIZE * y; + signed char zz = (x6 - K2) >> 15; + if (likely(zz < z_buffer[o])) { + z_buffer[o] = zz; + const uint32_t shade = + (N <= 0) ? 0U : ((N >= GRAY_LEVELS) ? GRAY_LEVELS - 1U : (uint32_t)N); + uint32_t color = gray_colors[shade]; + pixel_buffer[o] = color; + } + } + R_OPT(5, 8, ci, si); + } + R_OPT(9, 7, cj, sj); + } + + R_OPT(5, 7, cA, sA); + R_OPT(5, 8, cB, sB); + for (int y = 0; y < DONUT_SIZE; y++) { + for (int x = 0; x < DONUT_SIZE; x++) { + int index = x + DONUT_SIZE * y; + uint32_t color = pixel_buffer[index]; + if (likely(color != 0)) { + fast_scaled_pixel_write(color, x, y); + } + } + } + + lcd_fill_image(0, 0, DONUT_WIDTH, DONUT_HEIGHT, donut_framebuffer_32); + } +} + +void donut_test(int argc, char **argv) { + (void)argc; + (void)argv; + + printf("donut test\n"); + rs_donut_render(RS_DONUT_FRAME_COUNT); +} diff --git a/app/media/src/video_player.c b/app/media/src/video_player.c new file mode 100644 index 00000000..b2aa159c --- /dev/null +++ b/app/media/src/video_player.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +#define RS_VIDEO_HEADER_SIZE 16U + +static uint32_t rs_video_read_le32(const uint8_t *data) { + return (uint32_t)data[0] | ((uint32_t)data[1] << 8U) | ((uint32_t)data[2] << 16U) | + ((uint32_t)data[3] << 24U); +} + +static rs_status_t rs_video_decode_header(const uint8_t *bytes, uint32_t available_size, + rs_video_info_t *info) { + uint32_t pixels; + uint32_t frame_size; + uint32_t payload_size; + + if ((bytes == NULL) || (info == NULL) || (available_size < RS_VIDEO_HEADER_SIZE)) { + return RS_EINVAL; + } + *info = (rs_video_info_t){0}; + info->width = rs_video_read_le32(&bytes[0]); + info->height = rs_video_read_le32(&bytes[4]); + info->frame_count = rs_video_read_le32(&bytes[8]); + if ((info->width == 0U) || (info->height == 0U) || (info->frame_count == 0U) || + (info->width > (UINT32_MAX / info->height))) { + return RS_EFORMAT; + } + pixels = info->width * info->height; + if (((pixels & 1U) != 0U) || (pixels > (UINT32_MAX / 2U))) { + return RS_EFORMAT; + } + frame_size = pixels * 2U; + if ((frame_size == 0U) || + (info->frame_count > ((UINT32_MAX - RS_VIDEO_HEADER_SIZE) / frame_size))) { + return RS_EFORMAT; + } + payload_size = info->frame_count * frame_size; + if (payload_size > (available_size - RS_VIDEO_HEADER_SIZE)) { + return RS_EFORMAT; + } + info->payload_offset = RS_VIDEO_HEADER_SIZE; + info->frame_size = frame_size; + return RS_OK; +} + +rs_status_t rs_video_parse(const void *data, size_t data_size, rs_video_info_t *info) { + if ((data_size > UINT32_MAX) || (data == NULL)) { + return RS_EINVAL; + } + return rs_video_decode_header((const uint8_t *)data, (uint32_t)data_size, info); +} + +rs_status_t rs_video_show_spisd(uintptr_t start_address, uint32_t available_size) { + uint8_t header[RS_VIDEO_HEADER_SIZE]; + rs_video_info_t info; + rs_status_t status; + + status = rs_spisd_read_bytes(header, sizeof(header), start_address); + if (status != RS_OK) { + return status; + } + status = rs_video_decode_header(header, available_size, &info); + if (status != RS_OK) { + return status; + } + if ((info.width > LCD_W) || (info.height > LCD_H) || ((start_address & 3U) != 0U) || + ((uintptr_t)info.payload_offset > (UINTPTR_MAX - start_address))) { + return RS_EINVAL; + } + + for (uint32_t frame = 0U; frame < info.frame_count; ++frame) { + const uint32_t frame_offset = frame * info.frame_size; + const uintptr_t payload_address = start_address + info.payload_offset; + + if ((uintptr_t)frame_offset > (UINTPTR_MAX - payload_address)) { + return RS_EINVAL; + } + const uintptr_t frame_address = payload_address + frame_offset; + lcd_fill_image(0U, 0U, (uint16_t)info.width, (uint16_t)info.height, + (uint32_t *)frame_address); + } + return RS_OK; +} diff --git a/app/media/src/wav_audio.c b/app/media/src/wav_audio.c new file mode 100644 index 00000000..f7e35b3d --- /dev/null +++ b/app/media/src/wav_audio.c @@ -0,0 +1,133 @@ +#include + +#include +#include +#include + +static uint16_t rs_wav_read_le16(const uint8_t *data) { + return (uint16_t)((uint16_t)data[0] | ((uint16_t)data[1] << 8U)); +} + +static uint32_t rs_wav_read_le32(const uint8_t *data) { + return (uint32_t)data[0] | ((uint32_t)data[1] << 8U) | ((uint32_t)data[2] << 16U) | + ((uint32_t)data[3] << 24U); +} + +static bool rs_wav_tag_matches(const uint8_t *tag, const char *expected) { + return (tag[0] == (uint8_t)expected[0]) && (tag[1] == (uint8_t)expected[1]) && + (tag[2] == (uint8_t)expected[2]) && (tag[3] == (uint8_t)expected[3]); +} + +static rs_status_t rs_wav_read(const rs_wav_reader_t *reader, uint32_t offset, void *buffer, + size_t byte_count) { + if ((reader == NULL) || (reader->read == NULL) || (buffer == NULL) || (offset > reader->size) || + (byte_count > ((size_t)reader->size - offset))) { + return RS_EFORMAT; + } + return reader->read(reader->context, offset, buffer, byte_count); +} + +rs_status_t rs_wav_parse(const rs_wav_reader_t *reader, rs_wav_info_t *info) { + uint8_t riff[12]; + uint8_t chunk[8]; + uint8_t format[16]; + uint32_t offset = 12U; + uint32_t limit; + bool format_found = false; + + if ((reader == NULL) || (info == NULL) || (reader->size < sizeof(riff))) { + return RS_EINVAL; + } + *info = (rs_wav_info_t){0}; + if (rs_wav_read(reader, 0U, riff, sizeof(riff)) != RS_OK) { + return RS_EIO; + } + if (!rs_wav_tag_matches(riff, "RIFF") || !rs_wav_tag_matches(&riff[8], "WAVE")) { + return RS_EFORMAT; + } + if (rs_wav_read_le32(&riff[4]) > (reader->size - 8U)) { + return RS_EFORMAT; + } + limit = rs_wav_read_le32(&riff[4]) + 8U; + + while (offset < limit) { + uint32_t payload_offset; + uint32_t payload_size; + uint32_t padded_size; + + if ((limit - offset) < sizeof(chunk)) { + return RS_EFORMAT; + } + if (rs_wav_read(reader, offset, chunk, sizeof(chunk)) != RS_OK) { + return RS_EIO; + } + payload_size = rs_wav_read_le32(&chunk[4]); + payload_offset = offset + (uint32_t)sizeof(chunk); + if ((payload_offset > limit) || (payload_size > (limit - payload_offset))) { + return RS_EFORMAT; + } + padded_size = payload_size + (payload_size & 1U); + if ((padded_size < payload_size) || (padded_size > (limit - payload_offset))) { + return RS_EFORMAT; + } + + if (rs_wav_tag_matches(chunk, "fmt ")) { + uint32_t expected_block_align; + + if ((payload_size < sizeof(format)) || + (rs_wav_read(reader, payload_offset, format, sizeof(format)) != RS_OK)) { + return RS_EFORMAT; + } + info->audio_format = rs_wav_read_le16(&format[0]); + info->channel_count = rs_wav_read_le16(&format[2]); + info->sample_rate = rs_wav_read_le32(&format[4]); + info->byte_rate = rs_wav_read_le32(&format[8]); + info->block_align = rs_wav_read_le16(&format[12]); + info->bits_per_sample = rs_wav_read_le16(&format[14]); + if ((info->audio_format != 1U) || (info->channel_count == 0U) || + ((info->bits_per_sample != 8U) && (info->bits_per_sample != 16U) && + (info->bits_per_sample != 24U) && (info->bits_per_sample != 32U))) { + return RS_ENOTSUP; + } + expected_block_align = (uint32_t)info->channel_count * info->bits_per_sample / 8U; + if ((expected_block_align == 0U) || (expected_block_align > UINT16_MAX) || + (info->block_align != expected_block_align) || + (info->sample_rate > (UINT32_MAX / info->block_align)) || + (info->byte_rate != (info->sample_rate * info->block_align))) { + return RS_EFORMAT; + } + format_found = true; + } else if (rs_wav_tag_matches(chunk, "data")) { + if (!format_found || ((payload_size % info->block_align) != 0U)) { + return RS_EFORMAT; + } + info->data_offset = payload_offset; + info->data_size = payload_size; + return RS_OK; + } + offset = payload_offset + padded_size; + } + return RS_EFORMAT; +} + +typedef struct { + uintptr_t start_address; +} rs_wav_spisd_context_t; + +static rs_status_t rs_wav_spisd_read(void *context, uint32_t offset, void *buffer, + size_t byte_count) { + const rs_wav_spisd_context_t *spisd = (const rs_wav_spisd_context_t *)context; + + if ((spisd == NULL) || (offset > (UINTPTR_MAX - spisd->start_address))) { + return RS_EINVAL; + } + return rs_spisd_read_bytes(buffer, byte_count, spisd->start_address + offset); +} + +rs_status_t rs_wav_parse_spisd(uintptr_t start_address, uint32_t available_size, + rs_wav_info_t *info) { + rs_wav_spisd_context_t context = {start_address}; + const rs_wav_reader_t reader = {rs_wav_spisd_read, &context, available_size}; + + return rs_wav_parse(&reader, info); +} diff --git a/app/middleware/fatfs/diskio.c b/app/middleware/fatfs/diskio.c new file mode 100644 index 00000000..33bd68e4 --- /dev/null +++ b/app/middleware/fatfs/diskio.c @@ -0,0 +1,81 @@ +/* FatFs block-device adapter for the retroSoC SPISD memory window. */ + +#include + +#include "ff.h" +#include "diskio.h" + +#include +#include + +#define RS_FATFS_DRIVE_TF 0U + +static bool rs_fatfs_initialized; + +static DRESULT rs_fatfs_result(rs_status_t status) { + return (status == RS_OK) ? RES_OK : RES_ERROR; +} + +DSTATUS disk_status(BYTE pdrv) { + if (pdrv != RS_FATFS_DRIVE_TF) { + return STA_NOINIT; + } + return rs_fatfs_initialized ? 0U : STA_NOINIT; +} + +DSTATUS disk_initialize(BYTE pdrv) { + if (pdrv != RS_FATFS_DRIVE_TF) { + return STA_NOINIT; + } + rs_fatfs_initialized = true; + return 0U; +} + +DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) { + if ((pdrv != RS_FATFS_DRIVE_TF) || (buff == NULL) || (count == 0U) || + (disk_status(pdrv) != 0U) || (sector > UINT32_MAX)) { + return RES_PARERR; + } + return rs_fatfs_result(rs_spisd_sector_read(buff, (uint32_t)sector, (uint32_t)count)); +} + +#if FF_FS_READONLY == 0 +DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count) { + if ((pdrv != RS_FATFS_DRIVE_TF) || (buff == NULL) || (count == 0U) || + (disk_status(pdrv) != 0U) || (sector > UINT32_MAX)) { + return RES_PARERR; + } + return rs_fatfs_result(rs_spisd_sector_write(buff, (uint32_t)sector, (uint32_t)count)); +} +#endif + +DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) { + if ((pdrv != RS_FATFS_DRIVE_TF) || (disk_status(pdrv) != 0U)) { + return RES_NOTRDY; + } + + switch (cmd) { + case CTRL_SYNC: + return rs_fatfs_result(rs_spisd_sector_sync(RS_TIMEOUT_DEFAULT)); + case GET_SECTOR_SIZE: + if (buff == NULL) { + return RES_PARERR; + } + *(WORD *)buff = RS_SPISD_SECTOR_SIZE; + return RES_OK; + case GET_SECTOR_COUNT: + if (buff == NULL) { + return RES_PARERR; + } + *(LBA_t *)buff = (LBA_t)(TF_CARD_OFFST / RS_SPISD_SECTOR_SIZE); + return RES_OK; + case GET_BLOCK_SIZE: + if (buff == NULL) { + return RES_PARERR; + } + *(DWORD *)buff = 1U; + return RES_OK; + default: + return RES_PARERR; + } +} diff --git a/app/middleware/fatfs/fatfs.mk b/app/middleware/fatfs/fatfs.mk new file mode 100644 index 00000000..60d70818 --- /dev/null +++ b/app/middleware/fatfs/fatfs.mk @@ -0,0 +1,6 @@ +APP_SRCS += $(ROOT_PATH)/app/fatfs/ff16/source/diskio.c +APP_SRCS += $(ROOT_PATH)/app/fatfs/ff16/source/ff.c +APP_SRCS += $(ROOT_PATH)/app/fatfs/ff16/source/ffsystem.c +APP_SRCS += $(ROOT_PATH)/app/fatfs/ff16/source/ffunicode.c + +APP_INC_DIRS += $(ROOT_PATH)/app/fatfs/ff16/source diff --git a/app/fatfs/ffconf.h b/app/middleware/fatfs/ffconf.h similarity index 99% rename from app/fatfs/ffconf.h rename to app/middleware/fatfs/ffconf.h index 61d46215..3b23cc57 100644 --- a/app/fatfs/ffconf.h +++ b/app/middleware/fatfs/ffconf.h @@ -249,7 +249,7 @@ / Note that enabling exFAT discards ANSI C (C89) compatibility. */ -#define FF_FS_NORTC 0 +#define FF_FS_NORTC 1 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 #define FF_NORTC_YEAR 2025 diff --git a/app/userip/userip.c b/app/network/userip/userip.c similarity index 79% rename from app/userip/userip.c rename to app/network/userip/userip.c index f0cca622..b7009c1d 100644 --- a/app/userip/userip.c +++ b/app/network/userip/userip.c @@ -1,27 +1,27 @@ -#include -#include -#include +#include +#include +#include #include - void userip_main(int argc, char **argv) { // user custom area HACK: (void)argv; - if(argc == 0) { + if (argc == 0) { printf("[FIXED IP] archinfo test\n"); printf("[ARCHINFO SYS] %x\n", reg_user_ip_reg0); printf("[ARCHINFO IDL] %x\n", reg_user_ip_reg1); printf("[ARCHINFO IDH] %x\n", reg_user_ip_reg2); - } else if(argc == 1) { + } else if (argc == 1) { reg_user_ip_reg1 = 2; printf("div val: %x\n", reg_user_ip_reg1); reg_user_ip_reg2 = 0; - for(int i = 0; i < 6; ++i) printf("tim val: %d\n", reg_user_ip_reg2); - } else if(argc == 2) { + for (int i = 0; i < 6; ++i) + printf("tim val: %d\n", reg_user_ip_reg2); + } else if (argc == 2) { printf("[reg0] %x\n", reg_user_ip_reg0); reg_user_ip_reg1 = (uint32_t)0xfffe; printf("do val: %x\n", reg_user_ip_reg5); - for(int i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) { delay_ms(1); reg_user_ip_reg5 = ~reg_user_ip_reg5; printf("[%d]do val: %x\n", i, reg_user_ip_reg5); @@ -40,7 +40,7 @@ void userip_main(int argc, char **argv) { printf("pd val: %x\n", reg_user_ip_reg4); reg_user_ip_reg1 = (uint32_t)0xfffe; - for(int i = 0; i < 6; ++i) { + for (int i = 0; i < 6; ++i) { printf("[%d]di val: %x\n", i, reg_user_ip_reg6); } } diff --git a/app/userip/userip.h b/app/network/userip/userip.h similarity index 91% rename from app/userip/userip.h rename to app/network/userip/userip.h index 4b656740..032b91ea 100644 --- a/app/userip/userip.h +++ b/app/network/userip/userip.h @@ -2,4 +2,4 @@ #define USERIP_H__ void userip_main(int argc, char **argv); -#endif \ No newline at end of file +#endif diff --git a/app/network/userip/userip.mk b/app/network/userip/userip.mk new file mode 100644 index 00000000..08f74f07 --- /dev/null +++ b/app/network/userip/userip.mk @@ -0,0 +1,5 @@ +# User IP is optional and is linked only for MDD configurations. +ifeq ($(IP), MDD) +APP_SRCS += $(ROOT_PATH)/app/network/userip/userip.c +APP_INC_DIRS += $(ROOT_PATH)/app/network/userip +endif diff --git a/app/lvgl/lv_conf.h b/app/ports/lvgl/lv_conf.h similarity index 100% rename from app/lvgl/lv_conf.h rename to app/ports/lvgl/lv_conf.h diff --git a/app/lvgl/lv_port_disp.c b/app/ports/lvgl/lv_port_disp.c similarity index 98% rename from app/lvgl/lv_port_disp.c rename to app/ports/lvgl/lv_port_disp.c index 3eb88275..10fd0544 100644 --- a/app/lvgl/lv_port_disp.c +++ b/app/ports/lvgl/lv_port_disp.c @@ -11,8 +11,8 @@ *********************/ #include "lv_port_disp.h" #include -#include -#include +#include +#include #define MY_DISP_HOR_RES 240 #define MY_DISP_VER_RES 135 diff --git a/app/lvgl/lv_port_disp.h b/app/ports/lvgl/lv_port_disp.h similarity index 100% rename from app/lvgl/lv_port_disp.h rename to app/ports/lvgl/lv_port_disp.h diff --git a/app/lvgl/lv_port_indev.c b/app/ports/lvgl/lv_port_indev.c similarity index 100% rename from app/lvgl/lv_port_indev.c rename to app/ports/lvgl/lv_port_indev.c diff --git a/app/lvgl/lv_port_indev.h b/app/ports/lvgl/lv_port_indev.h similarity index 100% rename from app/lvgl/lv_port_indev.h rename to app/ports/lvgl/lv_port_indev.h diff --git a/app/ports/lvgl/lvgl.mk b/app/ports/lvgl/lvgl.mk new file mode 100644 index 00000000..2380f872 --- /dev/null +++ b/app/ports/lvgl/lvgl.mk @@ -0,0 +1,8 @@ +LVGL_SDK_DIR := $(ROOT_PATH)/app/lvgl/lvgl-main + +APP_SRCS += $(sort $(shell find $(LVGL_SDK_DIR)/src -type f -name '*.c')) +APP_SRCS += $(ROOT_PATH)/app/ports/lvgl/lv_port_disp.c +APP_SRCS += $(ROOT_PATH)/app/ports/lvgl/lv_port_indev.c + +APP_INC_DIRS += $(LVGL_SDK_DIR) +APP_INC_DIRS += $(ROOT_PATH)/app/ports/lvgl diff --git a/app/setup.py b/app/setup.py index 4fff3aa4..ac7712ed 100644 --- a/app/setup.py +++ b/app/setup.py @@ -14,7 +14,7 @@ from scripts.setup_helpers import atomic_write, download_file, ensure_git_repo APP_DIR = Path(__file__).resolve().parent -FATFS_DIR = APP_DIR / "fatfs" +FATFS_DIR = APP_DIR / "middleware/fatfs" COREMARK_DIR = APP_DIR / "coremark/coremark-main" @@ -30,9 +30,9 @@ def patch_fatfs(source: Path) -> None: fatfs_source = source / "ff.c" content = fatfs_source.read_text(encoding="utf-8") original_content = content - include = "#include " + include = "#include " if include not in content: - for legacy_include in ("#include ", "#include "): + for legacy_include in ("#include ", "#include ", "#include "): if legacy_include in content: content = content.replace(legacy_include, include) break @@ -46,10 +46,10 @@ def patch_coremark() -> None: header = COREMARK_DIR / "coremark.h" content = header.read_text(encoding="utf-8") original_content = content - include = "#include " - legacy_include = "#include " - if legacy_include in content: - content = content.replace(legacy_include, include) + include = "#include " + for legacy_include in ("#include ", "#include "): + if legacy_include in content: + content = content.replace(legacy_include, include) if include not in content: marker = '#include "core_portme.h"' if marker not in content: diff --git a/app/userip/userip.mk b/app/userip/userip.mk deleted file mode 100644 index 926b967b..00000000 --- a/app/userip/userip.mk +++ /dev/null @@ -1,6 +0,0 @@ -# user custom area -ifeq ($(IP), MDD) - APP_PATH += $(ROOT_PATH)/app/userip/userip.c - INC_PATH += -I$(ROOT_PATH)/app/userip - # add more user custom files into 'APP_PATH' -endif \ No newline at end of file diff --git a/configs/ci/hazard3-rv32im-ihp130-shell.mk b/configs/ci/hazard3-rv32im-ihp130-shell.mk new file mode 100644 index 00000000..45673f10 --- /dev/null +++ b/configs/ci/hazard3-rv32im-ihp130-shell.mk @@ -0,0 +1,12 @@ +SOC := MINI +CORE := HAZARD3 +IP := NONE +PDK := IHP130 +HAVE_PLL := NO +HAVE_SRAM_IF := NO +HAVE_SRAM_MACRO := NO +HAVE_SVA := NO +ISA := RV32IM +HAVE_CSR := YES +APP := shell +LINK_TYPE := ld2_psram diff --git a/configs/ci/hazard3-rv32im-ihp130.mk b/configs/ci/hazard3-rv32im-ihp130.mk index 9b6317d3..84a4aaa1 100644 --- a/configs/ci/hazard3-rv32im-ihp130.mk +++ b/configs/ci/hazard3-rv32im-ihp130.mk @@ -8,5 +8,5 @@ HAVE_SRAM_MACRO := NO HAVE_SVA := NO ISA := RV32IM HAVE_CSR := NO -PROG_TYPE := BASE +APP := bringup LINK_TYPE := ld2_psram diff --git a/configs/ci/mdd-rv32im-ihp130.mk b/configs/ci/mdd-rv32im-ihp130.mk index 9b0b98dd..20e12b54 100644 --- a/configs/ci/mdd-rv32im-ihp130.mk +++ b/configs/ci/mdd-rv32im-ihp130.mk @@ -8,5 +8,5 @@ HAVE_SRAM_MACRO := NO HAVE_SVA := NO ISA := RV32IM HAVE_CSR := NO -PROG_TYPE := BASE +APP := bringup LINK_TYPE := ld2_psram diff --git a/configs/cluster/hazard3-ics55.mk b/configs/cluster/hazard3-ics55.mk index 950fe8ca..0c4e754d 100644 --- a/configs/cluster/hazard3-ics55.mk +++ b/configs/cluster/hazard3-ics55.mk @@ -8,5 +8,5 @@ HAVE_SRAM_MACRO := NO HAVE_SVA := NO ISA := RV32IM HAVE_CSR := NO -PROG_TYPE := BASE +APP := bringup LINK_TYPE := ld2_psram diff --git a/configs/nightly/picorv32-rv32im-ihp130.mk b/configs/nightly/picorv32-rv32im-ihp130.mk index 81315a49..88e08dde 100644 --- a/configs/nightly/picorv32-rv32im-ihp130.mk +++ b/configs/nightly/picorv32-rv32im-ihp130.mk @@ -8,5 +8,5 @@ HAVE_SRAM_MACRO := NO HAVE_SVA := NO ISA := RV32IM HAVE_CSR := NO -PROG_TYPE := BASE +APP := bringup LINK_TYPE := ld2_psram diff --git a/crt/README.md b/crt/README.md new file mode 100644 index 00000000..f3403707 --- /dev/null +++ b/crt/README.md @@ -0,0 +1,81 @@ +# retroSoC Runtime and SDK + +`crt/` contains the freestanding RISC-V runtime and software development kit +used by every retroSoC firmware image. It provides startup code, linker +layouts, public SoC interfaces, hardware abstraction layers, and small runtime +services. It does not provide an application entry point; applications live in +[`../app`](../app). + +## Layout + +| Path | Purpose | +| --- | --- | +| `arch/riscv/` | RISC-V startup, interrupt assembly, compiler runtime helpers, and architecture-specific support. | +| `include/retrosoc/core/` | Public status, SoC, architecture, interrupt, and bounded-wait interfaces. | +| `include/retrosoc/hal/` | Public memory-mapped peripheral interfaces. | +| `include/retrosoc/lib/` | Freestanding console, formatting, string, and conversion interfaces. | +| `include/retrosoc/service/` | Public boot, shell, and benchmark service interfaces. | +| `src/core/`, `src/hal/`, `src/lib/`, `src/service/` | Implementations grouped by the same ownership boundary as the public headers. | +| `linker/` | Supported linker layouts, selected through `LINK_TYPE`. | + +The active public include root is `crt/include`. Include SDK headers through +the `retrosoc` namespace, for example: + +```c +#include +#include +#include +``` + +`crt/inc/` is legacy or generated compatibility material. It is not an active +public include root for the firmware build; new code must not add dependencies +on it. + +## Build Integration + +The central software build assembles the runtime sources in +[`../rtl/mini/mk/software.mk`](../rtl/mini/mk/software.mk). It selects the +RISC-V ISA, optional CSR interrupt support, linker layout, and the application +profile. Applications add their own sources after the common runtime is +selected. + +Start from a committed configuration profile: + +```sh +make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk setup +make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk firmware +``` + +The resulting firmware and generated headers are isolated under +`build/-/sw/`. Do not commit build outputs. + +## API and Contribution Rules + +- Keep public interfaces in the matching `include/retrosoc//` directory + and implementations in the corresponding `src//` directory. +- Use the `rs_` API namespace and `rs_status_t` for operations that can fail. +- Keep the runtime freestanding: do not add hosted-library, dynamic-allocation, + or operating-system dependencies. +- Prefer bounded APIs such as `rs_strlcpy`, `rs_strlcat`, `rs_snprintf`, and + timeout-based register waits over unbounded operations. +- Add deterministic host tests when new code does not require real registers, + timing, or board hardware. + +## Quality Checks + +Run the SDK checks from the repository root: + +```sh +make sw-format-check +make sw-policy-check +make sw-host-test +``` + +`sw-format-check` requires the project formatter version (`clang-format-14` in +CI). `sw-policy-check` enforces the self-owned embedded-C naming and unsafe API +policy. `sw-host-test` compiles deterministic runtime, parser, and compiler +helper tests with a host C compiler; it does not replace RTL simulation or +hardware validation. + +For the complete firmware, simulation, synthesis, and timing flow, see the +[repository README](../README.md). diff --git a/crt/arch/riscv/libgcc/clzsi2.c b/crt/arch/riscv/libgcc/clzsi2.c new file mode 100644 index 00000000..8e8cbd60 --- /dev/null +++ b/crt/arch/riscv/libgcc/clzsi2.c @@ -0,0 +1,14 @@ +int __clzsi2(unsigned int value); + +int __clzsi2(unsigned int value) { + int count = 0; + + if (value == 0U) { + return 32; + } + while ((value & 0x80000000U) == 0U) { + ++count; + value <<= 1U; + } + return count; +} diff --git a/crt/libgcc/div.S b/crt/arch/riscv/libgcc/div.S similarity index 100% rename from crt/libgcc/div.S rename to crt/arch/riscv/libgcc/div.S diff --git a/crt/arch/riscv/libgcc/divdi3.c b/crt/arch/riscv/libgcc/divdi3.c new file mode 100644 index 00000000..ace35515 --- /dev/null +++ b/crt/arch/riscv/libgcc/divdi3.c @@ -0,0 +1,21 @@ +#include +#include + +unsigned long long __udivdi3(unsigned long long dividend, unsigned long long divisor); +long long __divdi3(long long dividend, long long divisor); + +long long __divdi3(long long dividend, long long divisor) { + const bool dividend_negative = dividend < 0; + const bool divisor_negative = divisor < 0; + const unsigned long long unsigned_dividend = + dividend_negative ? 0U - (unsigned long long)dividend : (unsigned long long)dividend; + const unsigned long long unsigned_divisor = + divisor_negative ? 0U - (unsigned long long)divisor : (unsigned long long)divisor; + const unsigned long long quotient = __udivdi3(unsigned_dividend, unsigned_divisor); + + if (unsigned_divisor == 0U) { + return 0; + } + return (dividend_negative != divisor_negative) ? (long long)(0U - quotient) + : (long long)quotient; +} diff --git a/crt/arch/riscv/libgcc/ffssi2.c b/crt/arch/riscv/libgcc/ffssi2.c new file mode 100644 index 00000000..8bcbd0ee --- /dev/null +++ b/crt/arch/riscv/libgcc/ffssi2.c @@ -0,0 +1,14 @@ +int __ffssi2(unsigned int value); + +int __ffssi2(unsigned int value) { + int position = 1; + + if (value == 0U) { + return 0; + } + while ((value & 1U) == 0U) { + ++position; + value >>= 1U; + } + return position; +} diff --git a/crt/libgcc/muldi3.S b/crt/arch/riscv/libgcc/muldi3.S similarity index 100% rename from crt/libgcc/muldi3.S rename to crt/arch/riscv/libgcc/muldi3.S diff --git a/crt/arch/riscv/libgcc/mulsi3.c b/crt/arch/riscv/libgcc/mulsi3.c new file mode 100644 index 00000000..30ae67c1 --- /dev/null +++ b/crt/arch/riscv/libgcc/mulsi3.c @@ -0,0 +1,11 @@ +unsigned int __mulsi3(unsigned int a, unsigned int b) { + unsigned int r = 0; + + while (a) { + if (a & 1) + r += b; + a >>= 1; + b <<= 1; + } + return r; +} diff --git a/crt/arch/riscv/libgcc/udivdi3.c b/crt/arch/riscv/libgcc/udivdi3.c new file mode 100644 index 00000000..1b938ec6 --- /dev/null +++ b/crt/arch/riscv/libgcc/udivdi3.c @@ -0,0 +1,25 @@ +#include + +unsigned long long __udivdi3(unsigned long long dividend, unsigned long long divisor); + +unsigned long long __udivdi3(unsigned long long dividend, unsigned long long divisor) { + unsigned long long quotient = 0U; + unsigned long long quotient_bit = 1U; + + if (divisor == 0U) { + return 0U; + } + while ((divisor <= dividend) && ((divisor & (1ULL << 63U)) == 0U)) { + divisor <<= 1U; + quotient_bit <<= 1U; + } + while (quotient_bit != 0U) { + if (dividend >= divisor) { + dividend -= divisor; + quotient |= quotient_bit; + } + divisor >>= 1U; + quotient_bit >>= 1U; + } + return quotient; +} diff --git a/crt/arch/riscv/libgcc/umoddi3.c b/crt/arch/riscv/libgcc/umoddi3.c new file mode 100644 index 00000000..62546cc4 --- /dev/null +++ b/crt/arch/riscv/libgcc/umoddi3.c @@ -0,0 +1,23 @@ +#include + +unsigned long long __umoddi3(unsigned long long dividend, unsigned long long divisor); + +unsigned long long __umoddi3(unsigned long long dividend, unsigned long long divisor) { + unsigned long long quotient_bit = 1U; + + if (divisor == 0U) { + return 0U; + } + while ((divisor <= dividend) && ((divisor & (1ULL << 63U)) == 0U)) { + divisor <<= 1U; + quotient_bit <<= 1U; + } + while (quotient_bit != 0U) { + if (dividend >= divisor) { + dividend -= divisor; + } + divisor >>= 1U; + quotient_bit >>= 1U; + } + return dividend; +} diff --git a/crt/pico_irq/irq_gcc.S b/crt/arch/riscv/pico_irq/irq_gcc.S similarity index 100% rename from crt/pico_irq/irq_gcc.S rename to crt/arch/riscv/pico_irq/irq_gcc.S diff --git a/crt/pico_irq/irq_handler.c b/crt/arch/riscv/pico_irq/irq_handler.c similarity index 99% rename from crt/pico_irq/irq_handler.c rename to crt/arch/riscv/pico_irq/irq_handler.c index 0484cb20..39fbd2f8 100644 --- a/crt/pico_irq/irq_handler.c +++ b/crt/arch/riscv/pico_irq/irq_handler.c @@ -5,7 +5,7 @@ // binary, for any purpose, commercial or non-commercial, and by any // means. -#include +#include #include // user custom area diff --git a/crt/pico_irq/irq_opt.S b/crt/arch/riscv/pico_irq/irq_opt.S similarity index 100% rename from crt/pico_irq/irq_opt.S rename to crt/arch/riscv/pico_irq/irq_opt.S diff --git a/crt/startup.S b/crt/arch/riscv/startup.S similarity index 98% rename from crt/startup.S rename to crt/arch/riscv/startup.S index 56bfb163..134749d3 100644 --- a/crt/startup.S +++ b/crt/arch/riscv/startup.S @@ -2,7 +2,7 @@ .global _start .type _start,@function -#include "system_csr.h" +#include "retrosoc/arch/riscv/system_csr.h" _start: #ifdef CSR_ENABLE diff --git a/crt/system_irq.S b/crt/arch/riscv/system_irq.S similarity index 99% rename from crt/system_irq.S rename to crt/arch/riscv/system_irq.S index f76e56e6..a370d7e1 100644 --- a/crt/system_irq.S +++ b/crt/arch/riscv/system_irq.S @@ -27,7 +27,7 @@ // MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -#include +#include /** * \brief Global interrupt disabled diff --git a/crt/inc/firmware.h b/crt/inc/firmware.h deleted file mode 100644 index c0a6be19..00000000 --- a/crt/inc/firmware.h +++ /dev/null @@ -1,249 +0,0 @@ -#ifndef _RETROSOC_DEF_H_ -#define _RETROSOC_DEF_H_ - -#include -#include - -#ifdef CORE_PICORV32 -#define HW_CORE "PicoRV32" -#elif CORE_HAZARD3 -#define HW_CORE "HAZARD3" -#else -#define HW_CORE "none" -#endif - -#define CPU_FREQ 72 // unit: MHz -#define UART_BPS 921600 // unit: bps -#define PSRAM_NUM 4 -#define PSRAM_SCLK_MIN_FREQ 12 // unit: MHz -#define PSRAM_SCLK_MAX_FREQ 133 // unit: MHz -#define PSRAM_SCLK_FREQ (CPU_FREQ / 2) - -#define SPFS_MEM_START 0x00000000 -#define SPFS_MEM_OFFST 32 * 1024 * 1024 -#define NMI_MEM_START 0x10000000 -#define NMI_MEM_OFFST 256 * 1024 * 1024 -#define APB_MEM_START 0x20000000 -#define APB_MEM_OFFST 256 * 1024 * 1024 -#define SRAM_MEM_START 0x30000000 -#define SRAM_MEM_OFFST 128 * 1024 -#define SDRAM_MEM_START 0x38000000 -#define SDRAM_MEM_OFFST 64 * 1024 * 1024 -#define PSRAM_MEM_START 0x40000000 -#define PSRAM_MEM_OFFST 8 * 1024 * 1024 * PSRAM_NUM -#define OPIPSRAM_MEM_START 0x48000000 -#define OPIPSRAM_MEM_OFFST 32 * 1024 * 1024 -#define XPI_MEM_START 0x50000000 -#define XPI_MEM_OFFST 256 * 1024 * 1024 -#define TF_CARD_START (uint32_t)0x60000000 -#define TF_CARD_OFFST (uint32_t)0x40000000 - -// gpio -#define reg_gpio_oe (*(volatile uint32_t*)0x10000000) -#define reg_gpio_cs (*(volatile uint32_t*)0x10000004) -#define reg_gpio_pu (*(volatile uint32_t*)0x10000008) -#define reg_gpio_pd (*(volatile uint32_t*)0x1000000c) -#define reg_gpio_do (*(volatile uint32_t*)0x10000010) -#define reg_gpio_di (*(volatile uint32_t*)0x10000014) -#define reg_gpio_ien (*(volatile uint32_t*)0x10000018) -#define reg_gpio_itype0 (*(volatile uint32_t*)0x1000001c) -#define reg_gpio_itype1 (*(volatile uint32_t*)0x10000020) -#define reg_gpio_istat (*(volatile uint32_t*)0x10000024) -#define reg_gpio_iofcfg (*(volatile uint32_t*)0x10000028) -#define reg_gpio_pinmux (*(volatile uint32_t*)0x1000002c) -// uart0 -#define reg_uart0_clkdiv (*(volatile uint32_t*)0x10001000) -#define reg_uart0_data (*(volatile uint32_t*)0x10001004) -// tim0 -#define reg_tim0_cfg (*(volatile uint32_t*)0x10002000) -#define reg_tim0_rld (*(volatile uint32_t*)0x10002004) -#define reg_tim0_val (*(volatile uint32_t*)0x10002008) -// tim1 -#define reg_tim1_cfg (*(volatile uint32_t*)0x10003000) -#define reg_tim1_rld (*(volatile uint32_t*)0x10003004) -#define reg_tim1_val (*(volatile uint32_t*)0x10003008) -// psram -#define reg_psram_wait (*(volatile uint32_t*)0x10004000) -#define reg_psram_chd (*(volatile uint32_t*)0x10004004) -#define reg_psram_init (*(volatile uint32_t*)0x10004008) -// spisd -#define reg_spisd_mode (*(volatile uint32_t*)0x10005000) -#define reg_spisd_clkdiv (*(volatile uint32_t*)0x10005004) -#define reg_spisd_addr (*(volatile uint32_t*)0x10005008) -#define reg_spisd_txdata (*(volatile uint32_t*)0x1000500C) -#define reg_spisd_rxdata (*(volatile uint32_t*)0x10005010) -#define reg_spisd_status (*(volatile uint32_t*)0x10005014) -#define reg_spisd_sync (*(volatile uint32_t*)0x10005018) -// i2c0 -#define reg_i2c0_clkdiv (*(volatile uint32_t*)0x10006000) -#define reg_i2c0_devaddr (*(volatile uint32_t*)0x10006004) -#define reg_i2c0_regaddr (*(volatile uint32_t*)0x10006008) -#define reg_i2c0_txdata (*(volatile uint32_t*)0x1000600C) -#define reg_i2c0_rxdata (*(volatile uint32_t*)0x10006010) -#define reg_i2c0_xfer (*(volatile uint32_t*)0x10006014) -#define reg_i2c0_cfg (*(volatile uint32_t*)0x10006018) -#define reg_i2c0_status (*(volatile uint32_t*)0x1000601C) -// i2s -#define reg_i2s_mode (*(volatile uint32_t*)0x10007000) -#define reg_i2s_format (*(volatile uint32_t*)0x10007004) -#define reg_i2s_upbound (*(volatile uint32_t*)0x10007008) -#define reg_i2s_lowbound (*(volatile uint32_t*)0x1000700C) -#define reg_i2s_recven (*(volatile uint32_t*)0x10007010) -#define reg_i2s_txdata (*(volatile uint32_t*)0x10007014) -#define reg_i2s_rxdata (*(volatile uint32_t*)0x10007018) -#define reg_i2s_status (*(volatile uint32_t*)0x1000701C) -// onewire -#define reg_onewire_clkdiv (*(volatile uint32_t*)0x10008000) -#define reg_onewire_zerocnt (*(volatile uint32_t*)0x10008004) -#define reg_onewire_onecnt (*(volatile uint32_t*)0x10008008) -#define reg_onewire_rstcnt (*(volatile uint32_t*)0x1000800C) -#define reg_onewire_txdata (*(volatile uint32_t*)0x10008010) -#define reg_onewire_ctrl (*(volatile uint32_t*)0x10008014) -#define reg_onewire_status (*(volatile uint32_t*)0x10008018) -// xpi -#define reg_xpi_cfgidx (*(volatile uint32_t*)0x10009000) -#define reg_xpi_accmd (*(volatile uint32_t*)0x10009004) -#define reg_xpi_mmstad (*(volatile uint32_t*)0x10009008) -#define reg_xpi_mmoffst (*(volatile uint32_t*)0x1000900C) -#define reg_xpi_mode (*(volatile uint32_t*)0x10009010) -#define reg_xpi_nss (*(volatile uint32_t*)0x10009014) -#define reg_xpi_clkdiv (*(volatile uint32_t*)0x10009018) -#define reg_xpi_rdwr (*(volatile uint32_t*)0x1000901C) -#define reg_xpi_revdat (*(volatile uint32_t*)0x10009020) -#define reg_xpi_txupb (*(volatile uint32_t*)0x10009024) -#define reg_xpi_txlowb (*(volatile uint32_t*)0x10009028) -#define reg_xpi_rxupb (*(volatile uint32_t*)0x1000902C) -#define reg_xpi_rxlowb (*(volatile uint32_t*)0x10009030) -#define reg_xpi_flush (*(volatile uint32_t*)0x10009034) -#define reg_xpi_cmdtyp (*(volatile uint32_t*)0x10009038) -#define reg_xpi_cmdlen (*(volatile uint32_t*)0x1000903C) -#define reg_xpi_cmddat (*(volatile uint32_t*)0x10009040) -#define reg_xpi_adrtyp (*(volatile uint32_t*)0x10009044) -#define reg_xpi_adrlen (*(volatile uint32_t*)0x10009048) -#define reg_xpi_adrdat (*(volatile uint32_t*)0x1000904C) -#define reg_xpi_alttyp (*(volatile uint32_t*)0x10009050) -#define reg_xpi_altlen (*(volatile uint32_t*)0x10009054) -#define reg_xpi_altdat (*(volatile uint32_t*)0x10009058) -#define reg_xpi_tdulen (*(volatile uint32_t*)0x1000905C) -#define reg_xpi_rdulen (*(volatile uint32_t*)0x10009060) -#define reg_xpi_dattyp (*(volatile uint32_t*)0x10009064) -#define reg_xpi_datlen (*(volatile uint32_t*)0x10009068) -#define reg_xpi_datbit (*(volatile uint32_t*)0x1000906C) -#define reg_xpi_hlvlen (*(volatile uint32_t*)0x10009070) -#define reg_xpi_txdata (*(volatile uint32_t*)0x10009074) -#define reg_xpi_rxdata (*(volatile uint32_t*)0x10009078) -#define reg_xpi_start (*(volatile uint32_t*)0x1000907C) -#define reg_xpi_status (*(volatile uint32_t*)0x10009080) -// dma(32b xfer, hardware trigger by I2S fifo, QSPI fifo) -#define reg_dma_mode (*(volatile uint32_t*)0x1000A000) -#define reg_dma_srcaddr (*(volatile uint32_t*)0x1000A004) -#define reg_dma_srcincr (*(volatile uint32_t*)0x1000A008) -#define reg_dma_dstaddr (*(volatile uint32_t*)0x1000A00C) -#define reg_dma_dstincr (*(volatile uint32_t*)0x1000A010) -#define reg_dma_xferlen (*(volatile uint32_t*)0x1000A014) -#define reg_dma_start (*(volatile uint32_t*)0x1000A018) -#define reg_dma_stop (*(volatile uint32_t*)0x1000A01C) -#define reg_dma_reset (*(volatile uint32_t*)0x1000A020) -#define reg_dma_status (*(volatile uint32_t*)0x1000A024) -#define reg_dma_fsm (*(volatile uint32_t*)0x1000A028) -// sys ctrl -#define reg_sysctrl_coresel (*(volatile uint32_t*)0x1000B000) -#define reg_sysctrl_ipsel (*(volatile uint32_t*)0x1000B004) -#define reg_sysctrl_i2csel (*(volatile uint32_t*)0x1000B008) -#define reg_sysctrl_qspicsel (*(volatile uint32_t*)0x1000B00C) -// clint -#define reg_clint_mtimel (*(volatile uint32_t*)0x1000C000) -#define reg_clint_mtimeh (*(volatile uint32_t*)0x1000C004) -#define reg_clint_mtimecmpl (*(volatile uint32_t*)0x1000C008) -#define reg_clint_mtimecmph (*(volatile uint32_t*)0x1000C00C) -#define reg_clint_msip (*(volatile uint32_t*)0x1000C010) -#define reg_clint_clkdiv (*(volatile uint32_t*)0x1000C014) -// sdram -#define reg_sdram_clkdiv (*(volatile uint32_t*)0x1000D000) -#define reg_sdram_cfg (*(volatile uint32_t*)0x1000D004) -// dvp -#define reg_dvp_recven (*(volatile uint32_t*)0x1000E000) -#define reg_dvp_rxdata (*(volatile uint32_t*)0x1000E004) -#define reg_dvp_status (*(volatile uint32_t*)0x1000E008) -// sdio -#define reg_sdio_cfg (*(volatile uint32_t*)0x1000F000) -// opipsram -#define reg_opipsram_cfg (*(volatile uint32_t*)0x10010000) -// i2c1 -#define reg_i2c1_clkdiv (*(volatile uint32_t*)0x10011000) -#define reg_i2c1_devaddr (*(volatile uint32_t*)0x10011004) -#define reg_i2c1_regaddr (*(volatile uint32_t*)0x10011008) -#define reg_i2c1_txdata (*(volatile uint32_t*)0x1001100C) -#define reg_i2c1_rxdata (*(volatile uint32_t*)0x10011010) -#define reg_i2c1_xfer (*(volatile uint32_t*)0x10011014) -#define reg_i2c1_cfg (*(volatile uint32_t*)0x10011018) -#define reg_i2c1_status (*(volatile uint32_t*)0x1001101C) -// ga -#define reg_ga_cfg (*(volatile uint32_t*)0x10012000) -// apu -#define reg_apu_cfg (*(volatile uint32_t*)0x10013000) -// archinfo -#define reg_archinfo_sys (*(volatile uint32_t*)0x20000000) -#define reg_archinfo_idl (*(volatile uint32_t*)0x20000004) -#define reg_archinfo_idh (*(volatile uint32_t*)0x20000008) -// rng -#define reg_rng_ctrl (*(volatile uint32_t*)0x20001000) -#define reg_rng_seed (*(volatile uint32_t*)0x20001004) -#define reg_rng_val (*(volatile uint32_t*)0x20001008) -// uart -#define reg_uart1_lcr (*(volatile uint32_t*)0x20002000) -#define reg_uart1_div (*(volatile uint32_t*)0x20002004) -#define reg_uart1_trx (*(volatile uint32_t*)0x20002008) -#define reg_uart1_fcr (*(volatile uint32_t*)0x2000200c) -#define reg_uart1_lsr (*(volatile uint32_t*)0x20002010) -// pwm -#define reg_pwm_ctrl (*(volatile uint32_t*)0x20003000) -#define reg_pwm_pscr (*(volatile uint32_t*)0x20003004) -#define reg_pwm_cnt (*(volatile uint32_t*)0x20003008) -#define reg_pwm_cmp (*(volatile uint32_t*)0x2000300c) -#define reg_pwm_cr0 (*(volatile uint32_t*)0x20003010) -#define reg_pwm_cr1 (*(volatile uint32_t*)0x20003014) -#define reg_pwm_cr2 (*(volatile uint32_t*)0x20003018) -#define reg_pwm_cr3 (*(volatile uint32_t*)0x2000301c) -#define reg_pwm_stat (*(volatile uint32_t*)0x20003020) -// ps2 -#define reg_ps2_ctrl (*(volatile uint32_t*)0x20004000) -#define reg_ps2_data (*(volatile uint32_t*)0x20004004) -#define reg_ps2_stat (*(volatile uint32_t*)0x20004008) -// rtc -#define reg_rtc_ctrl (*(volatile uint32_t*)0x20005000) -#define reg_rtc_pscr (*(volatile uint32_t*)0x20005004) -#define reg_rtc_cnt (*(volatile uint32_t*)0x20005008) -#define reg_rtc_alrm (*(volatile uint32_t*)0x2000500C) -#define reg_rtc_ista (*(volatile uint32_t*)0x20005010) -#define reg_rtc_ssta (*(volatile uint32_t*)0x20005014) -// wdg -#define reg_wdg_ctrl (*(volatile uint32_t*)0x20006000) -#define reg_wdg_pscr (*(volatile uint32_t*)0x20006004) -#define reg_wdg_cnt (*(volatile uint32_t*)0x20006008) -#define reg_wdg_cmp (*(volatile uint32_t*)0x2000600C) -#define reg_wdg_stat (*(volatile uint32_t*)0x20006010) -#define reg_wdg_key (*(volatile uint32_t*)0x20006014) -#define reg_wdg_feed (*(volatile uint32_t*)0x20006018) -// crc -#define reg_crc_ctrl (*(volatile uint32_t*)0x20007000) -#define reg_crc_init (*(volatile uint32_t*)0x20007004) -#define reg_crc_xorv (*(volatile uint32_t*)0x20007008) -#define reg_crc_data (*(volatile uint32_t*)0x2000700C) -#define reg_crc_stat (*(volatile uint32_t*)0x20007010) -// tim3 -#define reg_tim3_ctrl (*(volatile uint32_t*)0x20008000) -#define reg_tim3_pscr (*(volatile uint32_t*)0x20008004) -#define reg_tim3_cnt (*(volatile uint32_t*)0x20008008) -#define reg_tim3_cmp (*(volatile uint32_t*)0x2000800C) -#define reg_tim3_stat (*(volatile uint32_t*)0x20008010) -// user ip design(example) -#define reg_user_ip_reg0 (*(volatile uint32_t*)0x2000F000) -#define reg_user_ip_reg1 (*(volatile uint32_t*)0x2000F004) -#define reg_user_ip_reg2 (*(volatile uint32_t*)0x2000F008) -#define reg_user_ip_reg3 (*(volatile uint32_t*)0x2000F00C) -#define reg_user_ip_reg4 (*(volatile uint32_t*)0x2000F010) -#define reg_user_ip_reg5 (*(volatile uint32_t*)0x2000F014) -#define reg_user_ip_reg6 (*(volatile uint32_t*)0x2000F018) -// ... user custom area ... -#endif \ No newline at end of file diff --git a/crt/inc/libdef.h b/crt/inc/libdef.h deleted file mode 100644 index b84e3382..00000000 --- a/crt/inc/libdef.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef LIBDEF_H__ -#define LIBDEF_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CSR_ENABLE -#include -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - -// uint32_t system_runtime() { -// uint32_t sys_cycle_val, sys_cycle_valh; -// __asm__ volatile("rdcycle %0" : "=r"(sys_cycle_val)); -// __asm__ volatile("rdcycleh %0" : "=r"(sys_cycle_valh)); - -// if(sys_cycle_valh == 0) return sys_cycle_val * CPU_FREQ / 1000; -// else return (sys_cycle_val) * CPU_FREQ / 1000; // unit: ms -// } - -uint32_t *irq_handler(uint32_t *regs, uint32_t irqs); - -#define putstr(s) \ - ({ for (const char *p = s; *p; p++) putch(*p); }) - -// assert.h -#define assert(cond) \ - do \ - { \ - if (!(cond)) \ - { \ - printf("Assertion fail at %s:%d\n", __FILE__, __LINE__); \ - halt(1); \ - } \ - } while (0) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/crt/inc/rs_1wire.h b/crt/inc/rs_1wire.h deleted file mode 100644 index a2931b4f..00000000 --- a/crt/inc/rs_1wire.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINY1WIRE_H__ -#define TINY1WIRE_H__ - -void ip_1wire_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_advtim.h b/crt/inc/rs_advtim.h deleted file mode 100644 index 2c5e45d3..00000000 --- a/crt/inc/rs_advtim.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYADVTIM_H__ -#define TINYADVTIM_H__ - -void ip_advtim_test(); -#endif \ No newline at end of file diff --git a/crt/inc/rs_archinfo.h b/crt/inc/rs_archinfo.h deleted file mode 100644 index 8b5bebe8..00000000 --- a/crt/inc/rs_archinfo.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYARCHINFO_H__ -#define TINYARCHINFO_H__ - -void ip_archinfo_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_bench.h b/crt/inc/rs_bench.h deleted file mode 100644 index b5c290ed..00000000 --- a/crt/inc/rs_bench.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef TINYBENCH_H__ -#define TINYBENCH_H__ - -#include - -uint32_t tinybench(bool verbose, uint32_t *instns_p); -#endif \ No newline at end of file diff --git a/crt/inc/rs_crc.h b/crt/inc/rs_crc.h deleted file mode 100644 index d6aedb49..00000000 --- a/crt/inc/rs_crc.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYCRC_H__ -#define TINYCRC_H__ - -void ip_crc_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_dma.h b/crt/inc/rs_dma.h deleted file mode 100644 index 5fc46af6..00000000 --- a/crt/inc/rs_dma.h +++ /dev/null @@ -1,12 +0,0 @@ - -#ifndef TINYDMA_H__ -#define TINYDMA_H__ - -void dma_config(uint32_t mode, uint32_t src, uint32_t srcincr, uint32_t dst, uint32_t dstincr, uint32_t xferlen); -void dma_start_xfer(); -void dma_stop_toggle(); -void dma_reset_xfer(); -void dma_wait_done(); -void ip_dma_test(); - -#endif \ No newline at end of file diff --git a/crt/inc/rs_gpio.h b/crt/inc/rs_gpio.h deleted file mode 100644 index c8ab411e..00000000 --- a/crt/inc/rs_gpio.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TINYGPIO_H__ -#define TINYGPIO_H__ - -void ip_gpio_test(int argc, char **argv); - -#endif \ No newline at end of file diff --git a/crt/inc/rs_hpuart.h b/crt/inc/rs_hpuart.h deleted file mode 100644 index 8d5743ea..00000000 --- a/crt/inc/rs_hpuart.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYHPUART_H__ -#define TINYHPUART_H__ - -void ip_hpuart_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_i2c.h b/crt/inc/rs_i2c.h deleted file mode 100644 index d44d9a1d..00000000 --- a/crt/inc/rs_i2c.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef TINYI2C_H__ -#define TINYI2C_H__ - -#define I2C0_XFER_WR 0b10 -#define I2C0_XFER_RD 0b11 - -#define I2C_DEV_ADDR_8BIT 0 -#define I2C_DEV_ADDR_16BIT 1 - -void i2c0_init(uint8_t clkdiv); -void i2c0_wr_nbyte(uint8_t dev_addr, uint16_t reg_addr, uint8_t type, uint8_t num, uint8_t *data); -void i2c0_rd_nbyte(uint8_t dev_addr, uint16_t reg_addr, uint8_t type, uint8_t num, uint8_t *data); - -#endif \ No newline at end of file diff --git a/crt/inc/rs_i2s.h b/crt/inc/rs_i2s.h deleted file mode 100644 index 9cf6f004..00000000 --- a/crt/inc/rs_i2s.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TINYI2S_H__ -#define TINYI2S_H__ - -void ip_i2s_test(int argc, char **argv); - -#endif \ No newline at end of file diff --git a/crt/inc/rs_irq.h b/crt/inc/rs_irq.h deleted file mode 100644 index 2f2a66dc..00000000 --- a/crt/inc/rs_irq.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TINYIRQ_H__ -#define TINYIRQ_H__ - -void irq_test(int argc, char **argv); -#endif - diff --git a/crt/inc/rs_lib.h b/crt/inc/rs_lib.h deleted file mode 100644 index d11a8c62..00000000 --- a/crt/inc/rs_lib.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef TINYLIB_H__ -#define TINYLIB_H__ - -#define RAND_MAX 32768 - -int atoi(const char *str); -char *itoa(unsigned int val, char *str, int base); -void *malloc(size_t size); -void free(void *ptr); -int abs(int x); -int rand(void); -void srand(unsigned int seed); - -#endif \ No newline at end of file diff --git a/crt/inc/rs_print.h b/crt/inc/rs_print.h deleted file mode 100644 index 296ed59e..00000000 --- a/crt/inc/rs_print.h +++ /dev/null @@ -1,11 +0,0 @@ - -#ifndef TINYPRINT_H__ -#define TINYPRINT_H__ - -#include - -void putchar(char c); -char getchar(); -void print(const char *p); - -#endif \ No newline at end of file diff --git a/crt/inc/rs_printf.h b/crt/inc/rs_printf.h deleted file mode 100644 index e4b61fd3..00000000 --- a/crt/inc/rs_printf.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef TINYPRINTF_H__ -#define TINYPRINTF_H__ - -#include -#include - -int printf(const char *format, ...); -int sprintf(char *str, const char *format, ...); -int snprintf(char *str, size_t size, const char *format, ...); -int vsprintf(char *str, const char *format, va_list ap); -int vsnprintf(char *str, size_t size, const char *format, va_list ap); - -#endif \ No newline at end of file diff --git a/crt/inc/rs_ps2.h b/crt/inc/rs_ps2.h deleted file mode 100644 index b5562183..00000000 --- a/crt/inc/rs_ps2.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYPS2_H__ -#define TINYPS2_H__ - -void ip_ps2_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_pwm.h b/crt/inc/rs_pwm.h deleted file mode 100644 index 15aba946..00000000 --- a/crt/inc/rs_pwm.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYPWM_H__ -#define TINYPWM_H__ - -void ip_pwm_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_qspi.h b/crt/inc/rs_qspi.h deleted file mode 100644 index 69d754e7..00000000 --- a/crt/inc/rs_qspi.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef TINYQSPI_H__ -#define TINYQSPI_H__ - -#define USE_QSPI0_DMA - -typedef struct { - uint32_t mode; - uint32_t nss; - uint32_t clkdiv; - uint32_t txub; - uint32_t txlb; - uint32_t rxub; - uint32_t rxlb; - uint32_t hlven; -} QSPI0_InitStruct_t; - -void qspi0_init(QSPI0_InitStruct_t val); - -void qspi0_wr(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, - uint32_t adrtyp, uint32_t adrlen, uint32_t adrdat, - uint32_t dumlen, - uint32_t dattyp, uint32_t datlen, uint32_t datbit, - uint32_t* dat_list); - -void qspi0_rd(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, - uint32_t adrtyp, uint32_t adrlen, uint32_t adrdat, - uint32_t dumlen, - uint32_t dattyp, uint32_t datlen, uint32_t datbit, - uint32_t* dat_list); - -void qspi0_xfer_config( - uint32_t rdwr, uint32_t revdat, uint32_t flush, - uint32_t cmdtyp, uint32_t cmdlen, - uint32_t adrtyp, uint32_t adrlen, - uint32_t dumlen, - uint32_t dattyp, uint32_t datlen, uint32_t datbit -); - -void qspi0_wr_cmd8(uint8_t dat); -void qspi0_wr_cmd16(uint16_t dat); - -void qspi0_wr_dat8(uint8_t dat); -void qspi0_wr_dat16(uint16_t dat); -void qspi0_wr_data32(uint32_t* dat, uint32_t len); -void qspi0_dma_xfer(uint32_t addr, uint32_t len); - -void qspi_dev_init(); -#endif \ No newline at end of file diff --git a/crt/inc/rs_rng.h b/crt/inc/rs_rng.h deleted file mode 100644 index db68180c..00000000 --- a/crt/inc/rs_rng.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYRNG_H__ -#define TINYRNG_H__ - -void ip_rng_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_rtc.h b/crt/inc/rs_rtc.h deleted file mode 100644 index 37d5d4a5..00000000 --- a/crt/inc/rs_rtc.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef TINYRTC_H__ -#define TINYRTC_H__ - -void ip_rtc_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_sh.h b/crt/inc/rs_sh.h deleted file mode 100644 index 6e69a785..00000000 --- a/crt/inc/rs_sh.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef TINYSH_H__ -#define TINYSH_H__ - -typedef void (*cmd_handler)(int argc, char **argv); - -typedef struct { - char *name; - char *info; - uint8_t batch; - cmd_handler handler; -} tinysh_cmd_t; - - -#define MAX_CMD_ARGC 16 -#define MAX_CMD_NUM 72 -#define MAX_CMD_LEN 100 -#define MAX_CMD_HIST 100 -#define MAX_PATH_LEN 128 -#define MAX_BUFFER_LEN 512 * 1024 - -uint8_t tinysh_register(char *name, char *info, uint8_t batch, void *handler); -void tinysh_init(); -void tinysh_batch_run(); -void tinysh_launch(); -#endif \ No newline at end of file diff --git a/crt/inc/rs_spisd.h b/crt/inc/rs_spisd.h deleted file mode 100644 index 3b8f2557..00000000 --- a/crt/inc/rs_spisd.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef TINYSPISD_H__ -#define TINYSPISD_H__ - -void spisd_mem_read(uint8_t *buff, uint32_t size, uint32_t count, uint32_t addr); -void spisd_sector_read(uint8_t *buff, uint32_t sector, uint32_t count); -void spisd_sector_write(const uint8_t *buff, uint32_t sector, uint32_t count); -void spisd_sector_sync(); -void ip_spisd_test(); -void ip_spisd_read(uint32_t addr, uint32_t len); -#endif \ No newline at end of file diff --git a/crt/inc/rs_string.h b/crt/inc/rs_string.h deleted file mode 100644 index 22ad0341..00000000 --- a/crt/inc/rs_string.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef TINYSTRING_H__ -#define TINYSTRING_H__ - -#include -#include - -void *memset(void *s, int c, size_t n); -void *memcpy(void *dst, const void *src, size_t n); -void *memmove(void *dst, const void *src, size_t n); -int memcmp(const void *s1, const void *s2, size_t n); -size_t strlen(const char *s); -char *strcat(char *dst, const char *src); -char *strcpy(char *dst, const char *src); -char *strncpy(char *dst, const char *src, size_t n); -int strcmp(const char *s1, const char *s2); -int strncmp(const char *s1, const char *s2, size_t n); -char *strchr(const char *s, int c); -void trim_whitespace(char *str); -void remove_suffix(char *dst, char *src, char sign); -#endif \ No newline at end of file diff --git a/crt/inc/rs_tim.h b/crt/inc/rs_tim.h deleted file mode 100644 index f3f33881..00000000 --- a/crt/inc/rs_tim.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef TINYTIM_H__ -#define TINYTIM_H__ - -void delay_ms(uint32_t val); -void tim1_init(); -uint32_t tim1_get_value(); -void ip_tim_test(int argc, char **argv); -#endif \ No newline at end of file diff --git a/crt/inc/rs_uart.h b/crt/inc/rs_uart.h deleted file mode 100644 index 45b1f128..00000000 --- a/crt/inc/rs_uart.h +++ /dev/null @@ -1,7 +0,0 @@ - -#ifndef TINYUART_H__ -#define TINYUART_H__ - -void uart0_init(uint32_t freq, uint32_t bps); -void putch(char ch); -#endif \ No newline at end of file diff --git a/crt/inc/system_bit.h b/crt/inc/system_bit.h deleted file mode 100644 index 1947feed..00000000 --- a/crt/inc/system_bit.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2019 Nuclei Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// -- Adaptable modifications are redistributed under compatible License -- -// -// Copyright (c) 2023-2026 Yuchi Miao -// retroSoC is licensed under Mulan PSL v2. -// You can use this software according to the terms and conditions of the Mulan PSL v2. -// You may obtain a copy of Mulan PSL v2 at: -// http://license.coscl.org.cn/MulanPSL2 -// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -// See the Mulan PSL v2 for more details. - -#ifndef __SYSTEM_BIT_H__ -#define __SYSTEM_BIT_H__ - - -#if __riscv_xlen == 64 -# define SLL32 sllw -# define STORE sd -# define LOAD ld -# define LWU lwu -# define LOG_REGBYTES 3 -#else -# define SLL32 sll -# define STORE sw -# define LOAD lw -# define LWU lw -# define LOG_REGBYTES 2 -#endif /* __riscv_xlen */ - -#define REGBYTES (1 << LOG_REGBYTES) - -#if __riscv_flen == 64 -# define FPSTORE fsd -# define FPLOAD fld -# define LOG_FPREGBYTES 3 -#else -# define FPSTORE fsw -# define FPLOAD flw -# define LOG_FPREGBYTES 2 -#endif /* __riscv_flen */ -#define FPREGBYTES (1 << LOG_FPREGBYTES) - -#define __rv_likely(x) __builtin_expect((x), 1) -#define __rv_unlikely(x) __builtin_expect((x), 0) - -#define __RV_ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) -#define __RV_ROUNDDOWN(a, b) ((a)/(b)*(b)) - -#define __RV_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define __RV_MIN(a, b) ((a) < (b) ? (a) : (b)) -#define __RV_CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) - -#define __RV_EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) -#define __RV_INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) - -#ifdef __ASSEMBLY__ -#define _AC(X,Y) X -#define _AT(T,X) X -#else -#define __AC(X,Y) (X##Y) -#define _AC(X,Y) __AC(X,Y) -#define _AT(T,X) ((T)(X)) -#endif - -#define _UL(x) (_AC(x, UL)) -#define _ULL(x) (_AC(x, ULL)) - -#define _BITUL(x) (_UL(1) << (x)) -#define _BITULL(x) (_ULL(1) << (x)) - -#define UL(x) (_UL(x)) -#define ULL(x) (_ULL(x)) - -#define STR(x) XSTR(x) -#define XSTR(x) #x -#define __STR(s) #s -#define STRINGIFY(s) __STR(s) - - -#endif \ No newline at end of file diff --git a/crt/inc/system_csr.h b/crt/inc/system_csr.h deleted file mode 100644 index f0993b3a..00000000 --- a/crt/inc/system_csr.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2019 Nuclei Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// -- Adaptable modifications are redistributed under compatible License -- -// -// Copyright (c) 2023-2026 Yuchi Miao -// retroSoC is licensed under Mulan PSL v2. -// You can use this software according to the terms and conditions of the Mulan PSL v2. -// You may obtain a copy of Mulan PSL v2 at: -// http://license.coscl.org.cn/MulanPSL2 -// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -// See the Mulan PSL v2 for more details. - -#ifndef __SYSTEM_CSR_H__ -#define __SYSTEM_CSR_H__ - -#include - -#define MSTATUS_UIE 0x00000001 -#define MSTATUS_SIE 0x00000002 -#define MSTATUS_HIE 0x00000004 -#define MSTATUS_MIE 0x00000008 -#define MSTATUS_UPIE 0x00000010 -#define MSTATUS_SPIE 0x00000020 -#define MSTATUS_HPIE 0x00000040 -#define MSTATUS_MPIE 0x00000080 -#define MSTATUS_SPP 0x00000100 -#define MSTATUS_MPP 0x00001800 -#define MSTATUS_FS 0x00006000 -#define MSTATUS_XS 0x00018000 -#define MSTATUS_MPRV 0x00020000 -#define MSTATUS_PUM 0x00040000 -#define MSTATUS_MXR 0x00080000 -#define MSTATUS_VM 0x1F000000 -#define MSTATUS32_SD 0x80000000 -#define MSTATUS64_SD 0x8000000000000000 - -#define MSTATUS_FS_INITIAL 0x00002000 -#define MSTATUS_FS_CLEAN 0x00004000 -#define MSTATUS_FS_DIRTY 0x00006000 - -#define SSTATUS_UIE 0x00000001 -#define SSTATUS_SIE 0x00000002 -#define SSTATUS_UPIE 0x00000010 -#define SSTATUS_SPIE 0x00000020 -#define SSTATUS_SPP 0x00000100 -#define SSTATUS_FS 0x00006000 -#define SSTATUS_XS 0x00018000 -#define SSTATUS_PUM 0x00040000 -#define SSTATUS32_SD 0x80000000 -#define SSTATUS64_SD 0x8000000000000000 - - -#define MCAUSE_INTERRUPT (1ULL<<((__riscv_xlen)-1)) - -#define MIP_SSIP (1 << IRQ_S_SOFT) -#define MIP_HSIP (1 << IRQ_H_SOFT) -#define MIP_MSIP (1 << IRQ_M_SOFT) -#define MIP_STIP (1 << IRQ_S_TIMER) -#define MIP_HTIP (1 << IRQ_H_TIMER) -#define MIP_MTIP (1 << IRQ_M_TIMER) -#define MIP_SEIP (1 << IRQ_S_EXT) -#define MIP_HEIP (1 << IRQ_H_EXT) -#define MIP_MEIP (1 << IRQ_M_EXT) - -#define MIE_SSIE MIP_SSIP -#define MIE_HSIE MIP_HSIP -#define MIE_MSIE MIP_MSIP -#define MIE_STIE MIP_STIP -#define MIE_HTIE MIP_HTIP -#define MIE_MTIE MIP_MTIP -#define MIE_SEIE MIP_SEIP -#define MIE_HEIE MIP_HEIP -#define MIE_MEIE MIP_MEIP - -#define WFE_WFE 0x1 - -#define MCOUNTINHIBIT_IR (1<<2) -#define MCOUNTINHIBIT_CY (1<<0) - -#define MMISC_CTL_NMI_CAUSE_FFF (1<<9) -#define MMISC_CTL_MISALIGN (1<<6) -#define MMISC_CTL_BPU (1<<3) - -#define SIP_SSIP MIP_SSIP -#define SIP_STIP MIP_STIP - -#define PRV_U 0 -#define PRV_S 1 -#define PRV_H 2 -#define PRV_M 3 - -#define VM_MBARE 0 -#define VM_MBB 1 -#define VM_MBBID 2 -#define VM_SV32 8 -#define VM_SV39 9 -#define VM_SV48 10 - -#define IRQ_S_SOFT 1 -#define IRQ_H_SOFT 2 -#define IRQ_M_SOFT 3 -#define IRQ_S_TIMER 5 -#define IRQ_H_TIMER 6 -#define IRQ_M_TIMER 7 -#define IRQ_S_EXT 9 -#define IRQ_H_EXT 10 -#define IRQ_M_EXT 11 -#define IRQ_COP 12 -#define IRQ_HOST 13 - -/* === FPU FRM Rounding Mode === */ -/** FPU Round to Nearest, ties to Even*/ -#define FRM_RNDMODE_RNE 0x0 -/** FPU Round Towards Zero */ -#define FRM_RNDMODE_RTZ 0x1 -/** FPU Round Down (towards -inf) */ -#define FRM_RNDMODE_RDN 0x2 -/** FPU Round Up (towards +inf) */ -#define FRM_RNDMODE_RUP 0x3 -/** FPU Round to nearest, ties to Max Magnitude */ -#define FRM_RNDMODE_RMM 0x4 -/** - * In instruction's rm, selects dynamic rounding mode. - * In Rounding Mode register, Invalid */ -#define FRM_RNDMODE_DYN 0x7 - -/* === FPU FFLAGS Accrued Exceptions === */ -/** FPU Inexact */ -#define FFLAGS_AE_NX (1<<0) -/** FPU Underflow */ -#define FFLAGS_AE_UF (1<<1) -/** FPU Overflow */ -#define FFLAGS_AE_OF (1<<2) -/** FPU Divide by Zero */ -#define FFLAGS_AE_DZ (1<<3) -/** FPU Invalid Operation */ -#define FFLAGS_AE_NV (1<<4) -/** Floating Point Register f0-f31, eg. f0 -> FREG(0) */ -#define FREG(idx) f##idx - - -#ifdef __riscv - -#ifdef __riscv64 -# define MSTATUS_SD MSTATUS64_SD -# define SSTATUS_SD SSTATUS64_SD -# define RISCV_PGLEVEL_BITS 9 -#else -# define MSTATUS_SD MSTATUS32_SD -# define SSTATUS_SD SSTATUS32_SD -# define RISCV_PGLEVEL_BITS 10 -#endif /* __riscv64 */ - -#define RISCV_PGSHIFT 12 -#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) - -#endif - -/* === Standard RISC-V CSR Registers === */ -#define CSR_USTATUS 0x0 -#define CSR_FFLAGS 0x1 -#define CSR_FRM 0x2 -#define CSR_FCSR 0x3 -#define CSR_CYCLE 0xc00 -#define CSR_TIME 0xc01 -#define CSR_INSTRET 0xc02 -#define CSR_SSTATUS 0x100 -#define CSR_SIE 0x104 -#define CSR_STVEC 0x105 -#define CSR_SSCRATCH 0x140 -#define CSR_SEPC 0x141 -#define CSR_SCAUSE 0x142 -#define CSR_SBADADDR 0x143 -#define CSR_SIP 0x144 -#define CSR_SPTBR 0x180 -#define CSR_MSTATUS 0x300 -#define CSR_MISA 0x301 -#define CSR_MEDELEG 0x302 -#define CSR_MIDELEG 0x303 -#define CSR_MIE 0x304 -#define CSR_MTVEC 0x305 -#define CSR_MCOUNTEREN 0x306 -#define CSR_MSCRATCH 0x340 -#define CSR_MEPC 0x341 -#define CSR_MCAUSE 0x342 -#define CSR_MBADADDR 0x343 -#define CSR_MIP 0x344 -#define CSR_MCYCLE 0xb00 -#define CSR_MINSTRET 0xb02 -#define CSR_MUCOUNTEREN 0x320 -#define CSR_MCOUNTINHIBIT 0x320 -#define CSR_MSCOUNTEREN 0x321 - -#define CSR_MVENDORID 0xf11 -#define CSR_MARCHID 0xf12 -#define CSR_MIMPID 0xf13 -#define CSR_MHARTID 0xf14 -#define CSR_CYCLEH 0xc80 -#define CSR_TIMEH 0xc81 -#define CSR_INSTRETH 0xc82 -#define CSR_MCYCLEH 0xb80 -#define CSR_MINSTRETH 0xb82 - -/* Exception Code in MCAUSE CSR */ -#define CAUSE_MISALIGNED_FETCH 0x0 -#define CAUSE_FAULT_FETCH 0x1 -#define CAUSE_ILLEGAL_INSTRUCTION 0x2 -#define CAUSE_BREAKPOINT 0x3 -#define CAUSE_MISALIGNED_LOAD 0x4 -#define CAUSE_FAULT_LOAD 0x5 -#define CAUSE_MISALIGNED_STORE 0x6 -#define CAUSE_FAULT_STORE 0x7 -#define CAUSE_USER_ECALL 0x8 -#define CAUSE_SUPERVISOR_ECALL 0x9 -#define CAUSE_HYPERVISOR_ECALL 0xa -#define CAUSE_MACHINE_ECALL 0xb - -#endif \ No newline at end of file diff --git a/crt/inc/system_base.h b/crt/include/retrosoc/arch/riscv/system_base.h similarity index 61% rename from crt/inc/system_base.h rename to crt/include/retrosoc/arch/riscv/system_base.h index 5997514a..4c6e3d0b 100644 --- a/crt/inc/system_base.h +++ b/crt/include/retrosoc/arch/riscv/system_base.h @@ -31,27 +31,26 @@ #define __SYSTEM_BASE_H__ #include -#include -#include -#include - +#include +#include +#include #ifndef __RISCV_XLEN - /** \brief Refer to the width of an integer register in bits(either 32 or 64) */ - #ifndef __riscv_xlen - #define __RISCV_XLEN 32 - #else - #define __RISCV_XLEN __riscv_xlen - #endif +/** \brief Refer to the width of an integer register in bits(either 32 or 64) */ +#ifndef __riscv_xlen +#define __RISCV_XLEN 32 +#else +#define __RISCV_XLEN __riscv_xlen +#endif #endif /* __RISCV_XLEN */ /** \brief Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V */ #if __RISCV_XLEN == 32 - typedef uint32_t rv_csr_t; +typedef uint32_t rv_csr_t; #elif __RISCV_XLEN == 64 - typedef uint64_t rv_csr_t; +typedef uint64_t rv_csr_t; #else - typedef uint32_t rv_csr_t; +typedef uint32_t rv_csr_t; #endif /** @@ -59,39 +58,41 @@ */ typedef union { struct { - rv_csr_t a:1; /*!< bit: 0 Atomic extension */ - rv_csr_t b:1; /*!< bit: 1 Tentatively reserved for Bit-Manipulation extension */ - rv_csr_t c:1; /*!< bit: 2 Compressed extension */ - rv_csr_t d:1; /*!< bit: 3 Double-precision floating-point extension */ - rv_csr_t e:1; /*!< bit: 4 RV32E base ISA */ - rv_csr_t f:1; /*!< bit: 5 Single-precision floating-point extension */ - rv_csr_t g:1; /*!< bit: 6 Additional standard extensions present */ - rv_csr_t h:1; /*!< bit: 7 Hypervisor extension */ - rv_csr_t i:1; /*!< bit: 8 RV32I/64I/128I base ISA */ - rv_csr_t j:1; /*!< bit: 9 Tentatively reserved for Dynamically Translated Languages extension */ - rv_csr_t _reserved1:1; /*!< bit: 10 Reserved */ - rv_csr_t l:1; /*!< bit: 11 Tentatively reserved for Decimal Floating-Point extension */ - rv_csr_t m:1; /*!< bit: 12 Integer Multiply/Divide extension */ - rv_csr_t n:1; /*!< bit: 13 User-level interrupts supported */ - rv_csr_t _reserved2:1; /*!< bit: 14 Reserved */ - rv_csr_t p:1; /*!< bit: 15 Tentatively reserved for Packed-SIMD extension */ - rv_csr_t q:1; /*!< bit: 16 Quad-precision floating-point extension */ - rv_csr_t _resreved3:1; /*!< bit: 17 Reserved */ - rv_csr_t s:1; /*!< bit: 18 Supervisor mode implemented */ - rv_csr_t t:1; /*!< bit: 19 Tentatively reserved for Transactional Memory extension */ - rv_csr_t u:1; /*!< bit: 20 User mode implemented */ - rv_csr_t v:1; /*!< bit: 21 Tentatively reserved for Vector extension */ - rv_csr_t _reserved4:1; /*!< bit: 22 Reserved */ - rv_csr_t x:1; /*!< bit: 23 Non-standard extensions present */ + rv_csr_t a : 1; /*!< bit: 0 Atomic extension */ + rv_csr_t b : 1; /*!< bit: 1 Tentatively reserved for Bit-Manipulation extension */ + rv_csr_t c : 1; /*!< bit: 2 Compressed extension */ + rv_csr_t d : 1; /*!< bit: 3 Double-precision floating-point extension */ + rv_csr_t e : 1; /*!< bit: 4 RV32E base ISA */ + rv_csr_t f : 1; /*!< bit: 5 Single-precision floating-point extension */ + rv_csr_t g : 1; /*!< bit: 6 Additional standard extensions present */ + rv_csr_t h : 1; /*!< bit: 7 Hypervisor extension */ + rv_csr_t i : 1; /*!< bit: 8 RV32I/64I/128I base ISA */ + rv_csr_t j : 1; /*!< bit: 9 Tentatively reserved for Dynamically Translated Languages + extension */ + rv_csr_t _reserved1 : 1; /*!< bit: 10 Reserved */ + rv_csr_t + l : 1; /*!< bit: 11 Tentatively reserved for Decimal Floating-Point extension */ + rv_csr_t m : 1; /*!< bit: 12 Integer Multiply/Divide extension */ + rv_csr_t n : 1; /*!< bit: 13 User-level interrupts supported */ + rv_csr_t _reserved2 : 1; /*!< bit: 14 Reserved */ + rv_csr_t p : 1; /*!< bit: 15 Tentatively reserved for Packed-SIMD extension */ + rv_csr_t q : 1; /*!< bit: 16 Quad-precision floating-point extension */ + rv_csr_t _resreved3 : 1; /*!< bit: 17 Reserved */ + rv_csr_t s : 1; /*!< bit: 18 Supervisor mode implemented */ + rv_csr_t t : 1; /*!< bit: 19 Tentatively reserved for Transactional Memory extension */ + rv_csr_t u : 1; /*!< bit: 20 User mode implemented */ + rv_csr_t v : 1; /*!< bit: 21 Tentatively reserved for Vector extension */ + rv_csr_t _reserved4 : 1; /*!< bit: 22 Reserved */ + rv_csr_t x : 1; /*!< bit: 23 Non-standard extensions present */ #if defined(__RISCV_XLEN) && __RISCV_XLEN == 64 - rv_csr_t _reserved5:38; /*!< bit: 24..61 Reserved */ - rv_csr_t mxl:2; /*!< bit: 62..63 Machine XLEN */ + rv_csr_t _reserved5 : 38; /*!< bit: 24..61 Reserved */ + rv_csr_t mxl : 2; /*!< bit: 62..63 Machine XLEN */ #else - rv_csr_t _reserved5:6; /*!< bit: 24..29 Reserved */ - rv_csr_t mxl:2; /*!< bit: 30..31 Machine XLEN */ + rv_csr_t _reserved5 : 6; /*!< bit: 24..29 Reserved */ + rv_csr_t mxl : 2; /*!< bit: 30..31 Machine XLEN */ #endif - } b; /*!< Structure used for bit access */ - rv_csr_t d; /*!< Type used for csr data access */ + } b; /*!< Structure used for bit access */ + rv_csr_t d; /*!< Type used for csr data access */ } CSR_MISA_Type; /** @@ -100,39 +101,39 @@ typedef union { typedef union { struct { #if defined(__RISCV_XLEN) && __RISCV_XLEN == 64 - rv_csr_t _reserved0:3; /*!< bit: 0..2 Reserved */ - rv_csr_t mie:1; /*!< bit: 3 Machine mode interrupt enable flag */ - rv_csr_t _reserved1:3; /*!< bit: 4..6 Reserved */ - rv_csr_t mpie:1; /*!< bit: 7 mirror of MIE flag */ - rv_csr_t _reserved2:3; /*!< bit: 8..10 Reserved */ - rv_csr_t mpp:2; /*!< bit: 11..12 mirror of Privilege Mode */ - rv_csr_t fs:2; /*!< bit: 13..14 FS status flag */ - rv_csr_t xs:2; /*!< bit: 15..16 XS status flag */ - rv_csr_t mprv:1; /*!< bit: Machine mode PMP */ - rv_csr_t _reserved3:14; /*!< bit: 18..31 Reserved */ - rv_csr_t uxl:2; /*!< bit: 32..33 user mode xlen */ - rv_csr_t _reserved6:29; /*!< bit: 34..62 Reserved */ - rv_csr_t sd:1; /*!< bit: Dirty status for XS or FS */ + rv_csr_t _reserved0 : 3; /*!< bit: 0..2 Reserved */ + rv_csr_t mie : 1; /*!< bit: 3 Machine mode interrupt enable flag */ + rv_csr_t _reserved1 : 3; /*!< bit: 4..6 Reserved */ + rv_csr_t mpie : 1; /*!< bit: 7 mirror of MIE flag */ + rv_csr_t _reserved2 : 3; /*!< bit: 8..10 Reserved */ + rv_csr_t mpp : 2; /*!< bit: 11..12 mirror of Privilege Mode */ + rv_csr_t fs : 2; /*!< bit: 13..14 FS status flag */ + rv_csr_t xs : 2; /*!< bit: 15..16 XS status flag */ + rv_csr_t mprv : 1; /*!< bit: Machine mode PMP */ + rv_csr_t _reserved3 : 14; /*!< bit: 18..31 Reserved */ + rv_csr_t uxl : 2; /*!< bit: 32..33 user mode xlen */ + rv_csr_t _reserved6 : 29; /*!< bit: 34..62 Reserved */ + rv_csr_t sd : 1; /*!< bit: Dirty status for XS or FS */ #else - rv_csr_t _reserved0:1; /*!< bit: 0 Reserved */ - rv_csr_t sie:1; /*!< bit: 1 supervisor interrupt enable flag */ - rv_csr_t _reserved1:1; /*!< bit: 2 Reserved */ - rv_csr_t mie:1; /*!< bit: 3 Machine mode interrupt enable flag */ - rv_csr_t _reserved2:1; /*!< bit: 4 Reserved */ - rv_csr_t spie:1; /*!< bit: 3 Supervisor Privilede mode interrupt enable flag */ - rv_csr_t _reserved3:1; /*!< bit: Reserved */ - rv_csr_t mpie:1; /*!< bit: mirror of MIE flag */ - rv_csr_t _reserved4:3; /*!< bit: Reserved */ - rv_csr_t mpp:2; /*!< bit: mirror of Privilege Mode */ - rv_csr_t fs:2; /*!< bit: FS status flag */ - rv_csr_t xs:2; /*!< bit: XS status flag */ - rv_csr_t mprv:1; /*!< bit: Machine mode PMP */ - rv_csr_t sum:1; /*!< bit: Supervisor Mode load and store protection */ - rv_csr_t _reserved6:12; /*!< bit: 19..30 Reserved */ - rv_csr_t sd:1; /*!< bit: Dirty status for XS or FS */ + rv_csr_t _reserved0 : 1; /*!< bit: 0 Reserved */ + rv_csr_t sie : 1; /*!< bit: 1 supervisor interrupt enable flag */ + rv_csr_t _reserved1 : 1; /*!< bit: 2 Reserved */ + rv_csr_t mie : 1; /*!< bit: 3 Machine mode interrupt enable flag */ + rv_csr_t _reserved2 : 1; /*!< bit: 4 Reserved */ + rv_csr_t spie : 1; /*!< bit: 3 Supervisor Privilede mode interrupt enable flag */ + rv_csr_t _reserved3 : 1; /*!< bit: Reserved */ + rv_csr_t mpie : 1; /*!< bit: mirror of MIE flag */ + rv_csr_t _reserved4 : 3; /*!< bit: Reserved */ + rv_csr_t mpp : 2; /*!< bit: mirror of Privilege Mode */ + rv_csr_t fs : 2; /*!< bit: FS status flag */ + rv_csr_t xs : 2; /*!< bit: XS status flag */ + rv_csr_t mprv : 1; /*!< bit: Machine mode PMP */ + rv_csr_t sum : 1; /*!< bit: Supervisor Mode load and store protection */ + rv_csr_t _reserved6 : 12; /*!< bit: 19..30 Reserved */ + rv_csr_t sd : 1; /*!< bit: Dirty status for XS or FS */ #endif - } b; /*!< Structure used for bit access */ - rv_csr_t d; /*!< Type used for csr data access */ + } b; /*!< Structure used for bit access */ + rv_csr_t d; /*!< Type used for csr data access */ } CSR_MSTATUS_Type; /** @@ -140,14 +141,14 @@ typedef union { */ typedef union { struct { - rv_csr_t mode:2; /*!< bit: 0..2 interrupt mode control */ + rv_csr_t mode : 2; /*!< bit: 0..2 interrupt mode control */ #if defined(__RISCV_XLEN) && __RISCV_XLEN == 64 - rv_csr_t addr:61; /*!< bit: 3..63 mtvec address */ + rv_csr_t addr : 61; /*!< bit: 3..63 mtvec address */ #else - rv_csr_t addr:29; /*!< bit: 3..31 mtvec address */ + rv_csr_t addr : 29; /*!< bit: 3..31 mtvec address */ #endif - } b; /*!< Structure used for bit access */ - rv_csr_t d; /*!< Type used for csr data access */ + } b; /*!< Structure used for bit access */ + rv_csr_t d; /*!< Type used for csr data access */ } CSR_MTVEC_Type; /** @@ -155,21 +156,23 @@ typedef union { */ typedef union { struct { - rv_csr_t exccode:12; /*!< bit: 11..0 exception or interrupt code */ - rv_csr_t _reserved0:4; /*!< bit: 15..12 Reserved */ - rv_csr_t mpil:8; /*!< bit: 23..16 Previous interrupt level */ - rv_csr_t _reserved1:3; /*!< bit: 26..24 Reserved */ - rv_csr_t mpie:1; /*!< bit: 27 Interrupt enable flag before enter interrupt */ - rv_csr_t mpp:2; /*!< bit: 29..28 Privilede mode flag before enter interrupt */ - rv_csr_t minhv:1; /*!< bit: 30 Machine interrupt vector table */ + rv_csr_t exccode : 12; /*!< bit: 11..0 exception or interrupt code */ + rv_csr_t _reserved0 : 4; /*!< bit: 15..12 Reserved */ + rv_csr_t mpil : 8; /*!< bit: 23..16 Previous interrupt level */ + rv_csr_t _reserved1 : 3; /*!< bit: 26..24 Reserved */ + rv_csr_t mpie : 1; /*!< bit: 27 Interrupt enable flag before enter interrupt */ + rv_csr_t mpp : 2; /*!< bit: 29..28 Privilede mode flag before enter interrupt */ + rv_csr_t minhv : 1; /*!< bit: 30 Machine interrupt vector table */ #if defined(__RISCV_XLEN) && __RISCV_XLEN == 64 - rv_csr_t _reserved2:32; /*!< bit: 31..62 Reserved */ - rv_csr_t interrupt:1; /*!< bit: 63 trap type. 0 means exception and 1 means interrupt */ + rv_csr_t _reserved2 : 32; /*!< bit: 31..62 Reserved */ + rv_csr_t + interrupt : 1; /*!< bit: 63 trap type. 0 means exception and 1 means interrupt */ #else - rv_csr_t interrupt:1; /*!< bit: 31 trap type. 0 means exception and 1 means interrupt */ + rv_csr_t + interrupt : 1; /*!< bit: 31 trap type. 0 means exception and 1 means interrupt */ #endif - } b; /*!< Structure used for bit access */ - rv_csr_t d; /*!< Type used for csr data access */ + } b; /*!< Structure used for bit access */ + rv_csr_t d; /*!< Type used for csr data access */ } CSR_MCAUSE_Type; /** @@ -177,19 +180,18 @@ typedef union { */ typedef union { struct { - rv_csr_t cy:1; /*!< bit: 0 1 means disable mcycle counter */ - rv_csr_t _reserved0:1; /*!< bit: 1 Reserved */ - rv_csr_t ir:1; /*!< bit: 2 1 means disable minstret counter */ + rv_csr_t cy : 1; /*!< bit: 0 1 means disable mcycle counter */ + rv_csr_t _reserved0 : 1; /*!< bit: 1 Reserved */ + rv_csr_t ir : 1; /*!< bit: 2 1 means disable minstret counter */ #if defined(__RISCV_XLEN) && __RISCV_XLEN == 64 - rv_csr_t _reserved1:61; /*!< bit: 3..63 Reserved */ + rv_csr_t _reserved1 : 61; /*!< bit: 3..63 Reserved */ #else - rv_csr_t _reserved1:29; /*!< bit: 3..31 Reserved */ + rv_csr_t _reserved1 : 29; /*!< bit: 3..31 Reserved */ #endif - } b; /*!< Structure used for bit access */ - rv_csr_t d; /*!< Type used for csr data access */ + } b; /*!< Structure used for bit access */ + rv_csr_t d; /*!< Type used for csr data access */ } CSR_MCOUNTINHIBIT_Type; - #ifndef __ASSEMBLY__ /** * \brief CSR operation Macro for csrrw instruction. @@ -201,14 +203,11 @@ typedef union { * \param val value to store into the CSR register * \return the CSR register value before written */ -#define __RV_CSR_SWAP(csr, val) \ - ({ \ - register rv_csr_t __v = (unsigned long)(val); \ - __ASM volatile("csrrw %0, " STRINGIFY(csr) ", %1" \ - : "=r"(__v) \ - : "rK"(__v) \ - : "memory"); \ - __v; \ +#define __RV_CSR_SWAP(csr, val) \ + ({ \ + register rv_csr_t __v = (unsigned long)(val); \ + __ASM volatile("csrrw %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \ + __v; \ }) /** @@ -219,14 +218,11 @@ typedef union { * \ref NMSIS_Core_CSR_Registers, eg. \ref CSR_MSTATUS * \return the CSR register value */ -#define __RV_CSR_READ(csr) \ - ({ \ - register rv_csr_t __v; \ - __ASM volatile("csrr %0, " STRINGIFY(csr) \ - : "=r"(__v) \ - : \ - : "memory"); \ - __v; \ +#define __RV_CSR_READ(csr) \ + ({ \ + register rv_csr_t __v; \ + __ASM volatile("csrr %0, " STRINGIFY(csr) : "=r"(__v) : : "memory"); \ + __v; \ }) /** @@ -237,13 +233,10 @@ typedef union { * \ref NMSIS_Core_CSR_Registers, eg. \ref CSR_MSTATUS * \param val value to store into the CSR register */ -#define __RV_CSR_WRITE(csr, val) \ - ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ - __ASM volatile("csrw " STRINGIFY(csr) ", %0" \ - : \ - : "rK"(__v) \ - : "memory"); \ +#define __RV_CSR_WRITE(csr, val) \ + ({ \ + register rv_csr_t __v = (rv_csr_t)(val); \ + __ASM volatile("csrw " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \ }) /** @@ -256,14 +249,11 @@ typedef union { * \param val Mask value to be used wih csrrs instruction * \return the CSR register value before written */ -#define __RV_CSR_READ_SET(csr, val) \ - ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ - __ASM volatile("csrrs %0, " STRINGIFY(csr) ", %1" \ - : "=r"(__v) \ - : "rK"(__v) \ - : "memory"); \ - __v; \ +#define __RV_CSR_READ_SET(csr, val) \ + ({ \ + register rv_csr_t __v = (rv_csr_t)(val); \ + __ASM volatile("csrrs %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \ + __v; \ }) /** @@ -274,13 +264,10 @@ typedef union { * \ref NMSIS_Core_CSR_Registers, eg. \ref CSR_MSTATUS * \param val Mask value to be used wih csrs instruction */ -#define __RV_CSR_SET(csr, val) \ - ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ - __ASM volatile("csrs " STRINGIFY(csr) ", %0" \ - : \ - : "rK"(__v) \ - : "memory"); \ +#define __RV_CSR_SET(csr, val) \ + ({ \ + register rv_csr_t __v = (rv_csr_t)(val); \ + __ASM volatile("csrs " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \ }) /** @@ -293,14 +280,11 @@ typedef union { * \param val Mask value to be used wih csrrc instruction * \return the CSR register value before written */ -#define __RV_CSR_READ_CLEAR(csr, val) \ - ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ - __ASM volatile("csrrc %0, " STRINGIFY(csr) ", %1" \ - : "=r"(__v) \ - : "rK"(__v) \ - : "memory"); \ - __v; \ +#define __RV_CSR_READ_CLEAR(csr, val) \ + ({ \ + register rv_csr_t __v = (rv_csr_t)(val); \ + __ASM volatile("csrrc %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \ + __v; \ }) /** @@ -311,13 +295,10 @@ typedef union { * \ref NMSIS_Core_CSR_Registers, eg. \ref CSR_MSTATUS * \param val Mask value to be used wih csrc instruction */ -#define __RV_CSR_CLEAR(csr, val) \ - ({ \ - register rv_csr_t __v = (rv_csr_t)(val); \ - __ASM volatile("csrc " STRINGIFY(csr) ", %0" \ - : \ - : "rK"(__v) \ - : "memory"); \ +#define __RV_CSR_CLEAR(csr, val) \ + ({ \ + register rv_csr_t __v = (rv_csr_t)(val); \ + __ASM volatile("csrc " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \ }) #endif /* __ASSEMBLY__ */ @@ -431,7 +412,6 @@ __STATIC_FORCEINLINE uint32_t __get_core_irq_pending(uint32_t irq) { return ((__RV_CSR_READ(CSR_MIP) >> irq) & 0x1); } - /** * \brief Clear Core IRQ Interrupt Pending status * \details Clear Core IRQ interrupt pending status of irq bit. @@ -522,7 +502,6 @@ __STATIC_FORCEINLINE uint64_t __get_rv_time(void) { #endif } - /** * \brief NOP Instruction * \details @@ -610,7 +589,7 @@ __STATIC_FORCEINLINE void __disable_minstret_counter(void) { * Clear the IR and CY bit of MCOUNTINHIBIT to 1 to enable MINSTRET & MCYCLE Counter */ __STATIC_FORCEINLINE void __enable_all_counter(void) { - __RV_CSR_CLEAR(CSR_MCOUNTINHIBIT, MCOUNTINHIBIT_IR|MCOUNTINHIBIT_CY); + __RV_CSR_CLEAR(CSR_MCOUNTINHIBIT, MCOUNTINHIBIT_IR | MCOUNTINHIBIT_CY); } /** @@ -619,7 +598,7 @@ __STATIC_FORCEINLINE void __enable_all_counter(void) { * Set the IR and CY bit of MCOUNTINHIBIT to 1 to disable MINSTRET & MCYCLE Counter */ __STATIC_FORCEINLINE void __disable_all_counter(void) { - __RV_CSR_SET(CSR_MCOUNTINHIBIT, MCOUNTINHIBIT_IR|MCOUNTINHIBIT_CY); + __RV_CSR_SET(CSR_MCOUNTINHIBIT, MCOUNTINHIBIT_IR | MCOUNTINHIBIT_CY); } /** @@ -627,12 +606,11 @@ __STATIC_FORCEINLINE void __disable_all_counter(void) { * \details * the FENCE instruction ensures that all memory accesses from instructions preceding * the fence in program order (the `predecessor set`) appear earlier in the global memory order than - * memory accesses from instructions appearing after the fence in program order (the `successor set`). - * For details, please refer to The RISC-V Instruction Set Manual - * \param p predecessor set, such as iorw, rw, r, w - * \param s successor set, such as iorw, rw, r, w + * memory accesses from instructions appearing after the fence in program order (the `successor + *set`). For details, please refer to The RISC-V Instruction Set Manual \param p predecessor + *set, such as iorw, rw, r, w \param s successor set, such as iorw, rw, r, w **/ -#define __FENCE(p, s) __ASM volatile ("fence " #p "," #s : : : "memory") +#define __FENCE(p, s) __ASM volatile("fence " #p "," #s : : : "memory") /** * \brief Fence.i Instruction @@ -645,20 +623,19 @@ __STATIC_FORCEINLINE void __FENCE_I(void) { } /** \brief Read & Write Memory barrier */ -#define __RWMB() __FENCE(iorw,iorw) +#define __RWMB() __FENCE(iorw, iorw) /** \brief Read Memory barrier */ -#define __RMB() __FENCE(ir,ir) +#define __RMB() __FENCE(ir, ir) /** \brief Write Memory barrier */ -#define __WMB() __FENCE(ow,ow) +#define __WMB() __FENCE(ow, ow) /** \brief SMP Read & Write Memory barrier */ -#define __SMP_RWMB() __FENCE(rw,rw) +#define __SMP_RWMB() __FENCE(rw, rw) /** \brief SMP Read Memory barrier */ -#define __SMP_RMB() __FENCE(r,r) +#define __SMP_RMB() __FENCE(r, r) /** \brief SMP Write Memory barrier */ -#define __SMP_WMB() __FENCE(w,w) +#define __SMP_WMB() __FENCE(w, w) /** \brief CPU relax for busy loop */ -#define __CPU_RELAX() __ASM volatile ("" : : : "memory") - +#define __CPU_RELAX() __ASM volatile("" : : : "memory") /* ===== Load/Store Operations ===== */ /** @@ -669,7 +646,7 @@ __STATIC_FORCEINLINE void __FENCE_I(void) { */ __STATIC_FORCEINLINE uint8_t __LB(volatile void *addr) { uint8_t result; - __ASM volatile ("lb %0, 0(%1)" : "=r" (result) : "r" (addr)); + __ASM volatile("lb %0, 0(%1)" : "=r"(result) : "r"(addr)); return result; } @@ -681,7 +658,7 @@ __STATIC_FORCEINLINE uint8_t __LB(volatile void *addr) { */ __STATIC_FORCEINLINE uint16_t __LH(volatile void *addr) { uint16_t result; - __ASM volatile ("lh %0, 0(%1)" : "=r" (result) : "r" (addr)); + __ASM volatile("lh %0, 0(%1)" : "=r"(result) : "r"(addr)); return result; } @@ -693,7 +670,7 @@ __STATIC_FORCEINLINE uint16_t __LH(volatile void *addr) { */ __STATIC_FORCEINLINE uint32_t __LW(volatile void *addr) { uint32_t result; - __ASM volatile ("lw %0, 0(%1)" : "=r" (result) : "r" (addr)); + __ASM volatile("lw %0, 0(%1)" : "=r"(result) : "r"(addr)); return result; } @@ -707,7 +684,7 @@ __STATIC_FORCEINLINE uint32_t __LW(volatile void *addr) { */ __STATIC_FORCEINLINE uint64_t __LD(volatile void *addr) { uint64_t result; - __ASM volatile ("ld %0, 0(%1)" : "=r" (result) : "r" (addr)); + __ASM volatile("ld %0, 0(%1)" : "=r"(result) : "r"(addr)); return result; } #endif @@ -719,7 +696,7 @@ __STATIC_FORCEINLINE uint64_t __LD(volatile void *addr) { * \param [in] val Value to set */ __STATIC_FORCEINLINE void __SB(volatile void *addr, uint8_t val) { - __ASM volatile ("sb %0, 0(%1)" : : "r" (val), "r" (addr)); + __ASM volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr)); } /** @@ -729,7 +706,7 @@ __STATIC_FORCEINLINE void __SB(volatile void *addr, uint8_t val) { * \param [in] val Value to set */ __STATIC_FORCEINLINE void __SH(volatile void *addr, uint16_t val) { - __ASM volatile ("sh %0, 0(%1)" : : "r" (val), "r" (addr)); + __ASM volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr)); } /** @@ -739,7 +716,7 @@ __STATIC_FORCEINLINE void __SH(volatile void *addr, uint16_t val) { * \param [in] val Value to set */ __STATIC_FORCEINLINE void __SW(volatile void *addr, uint32_t val) { - __ASM volatile ("sw %0, 0(%1)" : : "r" (val), "r" (addr)); + __ASM volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr)); } #if __RISCV_XLEN != 32 @@ -750,7 +727,7 @@ __STATIC_FORCEINLINE void __SW(volatile void *addr, uint32_t val) { * \param [in] val Value to set */ __STATIC_FORCEINLINE void __SD(volatile void *addr, uint64_t val) { - __ASM volatile ("sd %0, 0(%1)" : : "r" (val), "r" (addr)); + __ASM volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr)); } #endif diff --git a/crt/include/retrosoc/arch/riscv/system_bit.h b/crt/include/retrosoc/arch/riscv/system_bit.h new file mode 100644 index 00000000..f2719979 --- /dev/null +++ b/crt/include/retrosoc/arch/riscv/system_bit.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019 Nuclei Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// -- Adaptable modifications are redistributed under compatible License -- +// +// Copyright (c) 2023-2026 Yuchi Miao +// retroSoC is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#ifndef __SYSTEM_BIT_H__ +#define __SYSTEM_BIT_H__ + +#if __riscv_xlen == 64 +#define SLL32 sllw +#define STORE sd +#define LOAD ld +#define LWU lwu +#define LOG_REGBYTES 3 +#else +#define SLL32 sll +#define STORE sw +#define LOAD lw +#define LWU lw +#define LOG_REGBYTES 2 +#endif /* __riscv_xlen */ + +#define REGBYTES (1 << LOG_REGBYTES) + +#if __riscv_flen == 64 +#define FPSTORE fsd +#define FPLOAD fld +#define LOG_FPREGBYTES 3 +#else +#define FPSTORE fsw +#define FPLOAD flw +#define LOG_FPREGBYTES 2 +#endif /* __riscv_flen */ +#define FPREGBYTES (1 << LOG_FPREGBYTES) + +#define __rv_likely(x) __builtin_expect((x), 1) +#define __rv_unlikely(x) __builtin_expect((x), 0) + +#define __RV_ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b)) +#define __RV_ROUNDDOWN(a, b) ((a) / (b) * (b)) + +#define __RV_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define __RV_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define __RV_CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) + +#define __RV_EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) +#define __RV_INSERT_FIELD(val, which, fieldval) \ + (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) + +#ifdef __ASSEMBLY__ +#define _AC(X, Y) X +#define _AT(T, X) X +#else +#define __AC(X, Y) (X##Y) +#define _AC(X, Y) __AC(X, Y) +#define _AT(T, X) ((T)(X)) +#endif + +#define _UL(x) (_AC(x, UL)) +#define _ULL(x) (_AC(x, ULL)) + +#define _BITUL(x) (_UL(1) << (x)) +#define _BITULL(x) (_ULL(1) << (x)) + +#define UL(x) (_UL(x)) +#define ULL(x) (_ULL(x)) + +#define STR(x) XSTR(x) +#define XSTR(x) #x +#define __STR(s) #s +#define STRINGIFY(s) __STR(s) + +#endif diff --git a/crt/include/retrosoc/arch/riscv/system_csr.h b/crt/include/retrosoc/arch/riscv/system_csr.h new file mode 100644 index 00000000..4b3411fc --- /dev/null +++ b/crt/include/retrosoc/arch/riscv/system_csr.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2019 Nuclei Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// -- Adaptable modifications are redistributed under compatible License -- +// +// Copyright (c) 2023-2026 Yuchi Miao +// retroSoC is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#ifndef __SYSTEM_CSR_H__ +#define __SYSTEM_CSR_H__ + +#include + +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_HPIE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_PUM 0x00040000 +#define MSTATUS_MXR 0x00080000 +#define MSTATUS_VM 0x1F000000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS64_SD 0x8000000000000000 + +#define MSTATUS_FS_INITIAL 0x00002000 +#define MSTATUS_FS_CLEAN 0x00004000 +#define MSTATUS_FS_DIRTY 0x00006000 + +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_PUM 0x00040000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define MCAUSE_INTERRUPT (1ULL << ((__riscv_xlen)-1)) + +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_HSIP (1 << IRQ_H_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_HTIP (1 << IRQ_H_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_HEIP (1 << IRQ_H_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) + +#define MIE_SSIE MIP_SSIP +#define MIE_HSIE MIP_HSIP +#define MIE_MSIE MIP_MSIP +#define MIE_STIE MIP_STIP +#define MIE_HTIE MIP_HTIP +#define MIE_MTIE MIP_MTIP +#define MIE_SEIE MIP_SEIP +#define MIE_HEIE MIP_HEIP +#define MIE_MEIE MIP_MEIP + +#define WFE_WFE 0x1 + +#define MCOUNTINHIBIT_IR (1 << 2) +#define MCOUNTINHIBIT_CY (1 << 0) + +#define MMISC_CTL_NMI_CAUSE_FFF (1 << 9) +#define MMISC_CTL_MISALIGN (1 << 6) +#define MMISC_CTL_BPU (1 << 3) + +#define SIP_SSIP MIP_SSIP +#define SIP_STIP MIP_STIP + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_H 2 +#define PRV_M 3 + +#define VM_MBARE 0 +#define VM_MBB 1 +#define VM_MBBID 2 +#define VM_SV32 8 +#define VM_SV39 9 +#define VM_SV48 10 + +#define IRQ_S_SOFT 1 +#define IRQ_H_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_H_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_S_EXT 9 +#define IRQ_H_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_COP 12 +#define IRQ_HOST 13 + +/* === FPU FRM Rounding Mode === */ +/** FPU Round to Nearest, ties to Even*/ +#define FRM_RNDMODE_RNE 0x0 +/** FPU Round Towards Zero */ +#define FRM_RNDMODE_RTZ 0x1 +/** FPU Round Down (towards -inf) */ +#define FRM_RNDMODE_RDN 0x2 +/** FPU Round Up (towards +inf) */ +#define FRM_RNDMODE_RUP 0x3 +/** FPU Round to nearest, ties to Max Magnitude */ +#define FRM_RNDMODE_RMM 0x4 +/** + * In instruction's rm, selects dynamic rounding mode. + * In Rounding Mode register, Invalid */ +#define FRM_RNDMODE_DYN 0x7 + +/* === FPU FFLAGS Accrued Exceptions === */ +/** FPU Inexact */ +#define FFLAGS_AE_NX (1 << 0) +/** FPU Underflow */ +#define FFLAGS_AE_UF (1 << 1) +/** FPU Overflow */ +#define FFLAGS_AE_OF (1 << 2) +/** FPU Divide by Zero */ +#define FFLAGS_AE_DZ (1 << 3) +/** FPU Invalid Operation */ +#define FFLAGS_AE_NV (1 << 4) +/** Floating Point Register f0-f31, eg. f0 -> FREG(0) */ +#define FREG(idx) f##idx + +#ifdef __riscv + +#ifdef __riscv64 +#define MSTATUS_SD MSTATUS64_SD +#define SSTATUS_SD SSTATUS64_SD +#define RISCV_PGLEVEL_BITS 9 +#else +#define MSTATUS_SD MSTATUS32_SD +#define SSTATUS_SD SSTATUS32_SD +#define RISCV_PGLEVEL_BITS 10 +#endif /* __riscv64 */ + +#define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) + +#endif + +/* === Standard RISC-V CSR Registers === */ +#define CSR_USTATUS 0x0 +#define CSR_FFLAGS 0x1 +#define CSR_FRM 0x2 +#define CSR_FCSR 0x3 +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_SBADADDR 0x143 +#define CSR_SIP 0x144 +#define CSR_SPTBR 0x180 +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MCOUNTEREN 0x306 +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MBADADDR 0x343 +#define CSR_MIP 0x344 +#define CSR_MCYCLE 0xb00 +#define CSR_MINSTRET 0xb02 +#define CSR_MUCOUNTEREN 0x320 +#define CSR_MCOUNTINHIBIT 0x320 +#define CSR_MSCOUNTEREN 0x321 + +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_MCYCLEH 0xb80 +#define CSR_MINSTRETH 0xb82 + +/* Exception Code in MCAUSE CSR */ +#define CAUSE_MISALIGNED_FETCH 0x0 +#define CAUSE_FAULT_FETCH 0x1 +#define CAUSE_ILLEGAL_INSTRUCTION 0x2 +#define CAUSE_BREAKPOINT 0x3 +#define CAUSE_MISALIGNED_LOAD 0x4 +#define CAUSE_FAULT_LOAD 0x5 +#define CAUSE_MISALIGNED_STORE 0x6 +#define CAUSE_FAULT_STORE 0x7 +#define CAUSE_USER_ECALL 0x8 +#define CAUSE_SUPERVISOR_ECALL 0x9 +#define CAUSE_HYPERVISOR_ECALL 0xa +#define CAUSE_MACHINE_ECALL 0xb + +#endif diff --git a/crt/inc/system_gcc.h b/crt/include/retrosoc/arch/riscv/system_gcc.h similarity index 63% rename from crt/inc/system_gcc.h rename to crt/include/retrosoc/arch/riscv/system_gcc.h index f0c43717..9c550f9d 100644 --- a/crt/inc/system_gcc.h +++ b/crt/include/retrosoc/arch/riscv/system_gcc.h @@ -31,118 +31,116 @@ #define __SYSTEM_GCC_H__ #include -#include - +#include /* Fallback for __has_builtin */ #ifndef __has_builtin - #define __has_builtin(x) (0) +#define __has_builtin(x) (0) #endif /* NMSIS compiler specific defines */ /** \brief Pass information from the compiler to the assembler. */ -#ifndef __ASM - #define __ASM __asm +#ifndef __ASM +#define __ASM __asm #endif /** \brief Recommend that function should be inlined by the compiler. */ -#ifndef __INLINE - #define __INLINE inline +#ifndef __INLINE +#define __INLINE inline #endif /** \brief Define a static function that may be inlined by the compiler. */ -#ifndef __STATIC_INLINE - #define __STATIC_INLINE static inline +#ifndef __STATIC_INLINE +#define __STATIC_INLINE static inline #endif /** \brief Define a static function that should be always inlined by the compiler. */ -#ifndef __STATIC_FORCEINLINE - #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#ifndef __STATIC_FORCEINLINE +#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline #endif /** \brief Inform the compiler that a function does not return. */ -#ifndef __NO_RETURN - #define __NO_RETURN __attribute__((__noreturn__)) +#ifndef __NO_RETURN +#define __NO_RETURN __attribute__((__noreturn__)) #endif /** \brief Inform that a variable shall be retained in executable image. */ -#ifndef __USED - #define __USED __attribute__((used)) +#ifndef __USED +#define __USED __attribute__((used)) #endif /** \brief restrict pointer qualifier to enable additional optimizations. */ -#ifndef __WEAK - #define __WEAK __attribute__((weak)) +#ifndef __WEAK +#define __WEAK __attribute__((weak)) #endif /** \brief specified the vector size of the variable, measured in bytes */ -#ifndef __VECTOR_SIZE - #define __VECTOR_SIZE(x) __attribute__((vector_size(x))) +#ifndef __VECTOR_SIZE +#define __VECTOR_SIZE(x) __attribute__((vector_size(x))) #endif /** \brief Request smallest possible alignment. */ -#ifndef __PACKED - #define __PACKED __attribute__((packed, aligned(1))) +#ifndef __PACKED +#define __PACKED __attribute__((packed, aligned(1))) #endif /** \brief Request smallest possible alignment for a structure. */ -#ifndef __PACKED_STRUCT - #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#ifndef __PACKED_STRUCT +#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) #endif /** \brief Request smallest possible alignment for a union. */ -#ifndef __PACKED_UNION - #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#ifndef __PACKED_UNION +#define __PACKED_UNION union __attribute__((packed, aligned(1))) #endif /** \brief Minimum `x` bytes alignment for a variable. */ -#ifndef __ALIGNED - #define __ALIGNED(x) __attribute__((aligned(x))) +#ifndef __ALIGNED +#define __ALIGNED(x) __attribute__((aligned(x))) #endif /** \brief restrict pointer qualifier to enable additional optimizations. */ -#ifndef __RESTRICT - #define __RESTRICT __restrict +#ifndef __RESTRICT +#define __RESTRICT __restrict #endif /** \brief Barrier to prevent compiler from reordering instructions. */ -#ifndef __COMPILER_BARRIER - #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#ifndef __COMPILER_BARRIER +#define __COMPILER_BARRIER() __ASM volatile("" ::: "memory") #endif /** \brief provide the compiler with branch prediction information, the branch is usually true */ -#ifndef __USUALLY - #define __USUALLY(exp) __builtin_expect((exp), 1) +#ifndef __USUALLY +#define __USUALLY(exp) __builtin_expect((exp), 1) #endif /** \brief provide the compiler with branch prediction information, the branch is rarely true */ -#ifndef __RARELY - #define __RARELY(exp) __builtin_expect((exp), 0) +#ifndef __RARELY +#define __RARELY(exp) __builtin_expect((exp), 0) #endif /** \brief Use this attribute to indicate that the specified function is an interrupt handler. */ -#ifndef __INTERRUPT - #define __INTERRUPT +#ifndef __INTERRUPT +#define __INTERRUPT #endif - /** \brief Defines 'read only' permissions */ #ifdef __cplusplus - #define __I volatile +#define __I volatile #else - #define __I volatile const +#define __I volatile const #endif /** \brief Defines 'write only' permissions */ -#define __O volatile +#define __O volatile /** \brief Defines 'read / write' permissions */ -#define __IO volatile +#define __IO volatile /* following defines should be used for structure members */ /** \brief Defines 'read only' structure member permissions */ -#define __IM volatile const +#define __IM volatile const /** \brief Defines 'write only' structure member permissions */ -#define __OM volatile +#define __OM volatile /** \brief Defines 'read/write' structure member permissions */ -#define __IOM volatile +#define __IOM volatile -#endif \ No newline at end of file +#endif diff --git a/crt/inc/system_timer.h b/crt/include/retrosoc/arch/riscv/system_timer.h similarity index 81% rename from crt/inc/system_timer.h rename to crt/include/retrosoc/arch/riscv/system_timer.h index 9e3e91c1..0d7ef89e 100644 --- a/crt/inc/system_timer.h +++ b/crt/include/retrosoc/arch/riscv/system_timer.h @@ -30,8 +30,8 @@ #ifndef __SYSTEM_TIMER_H__ #define __SYSTEM_TIMER_H__ -#include -#include +#include +#include typedef struct { __IOM uint64_t mtime; @@ -40,24 +40,23 @@ typedef struct { __IOM uint32_t clkdiv; } SysTimer_Type; - /* Timer Control / Status Register Definitions */ -#define SysTimer_MSIP_MSIP_POS 0U /*!< SysTick Timer msip: msip bit Position */ -#define SysTimer_MSIP_MSIP_MASK (1UL << SysTimer_MSIP_MSIP_POS) /*!< SysTick Timer msip: msip Mask */ +#define SysTimer_MSIP_MSIP_POS 0U /*!< SysTick Timer msip: msip bit Position */ +#define SysTimer_MSIP_MSIP_MASK \ + (1UL << SysTimer_MSIP_MSIP_POS) /*!< SysTick Timer msip: msip Mask */ -#define SysTimer_MTIMER_MASK (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMER value Mask */ -#define SysTimer_MTIMERCMP_MASK (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMERCMP value Mask */ -#define SysTimer_MSIP_MASK (0xFFFFFFFFUL) /*!< SysTick Timer msip value Mask */ +#define SysTimer_MTIMER_MASK (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMER value Mask */ +#define SysTimer_MTIMERCMP_MASK (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMERCMP value Mask */ +#define SysTimer_MSIP_MASK (0xFFFFFFFFUL) /*!< SysTick Timer msip value Mask */ -#define __SYSTIMER_BASEADDR 0x1000C000 +#define __SYSTIMER_BASEADDR 0x1000C000 #ifndef __SYSTIMER_BASEADDR /* Base address of SYSTIMER(__SYSTIMER_BASEADDR) should be defined in */ #error "__SYSTIMER_BASEADDR is not defined, please check!" #endif /* System Timer Memory mapping of Device */ -#define SysTimer_BASE __SYSTIMER_BASEADDR /*!< SysTick Base Address */ -#define SysTimer ((SysTimer_Type *) SysTimer_BASE) /*!< SysTick configuration struct */ - +#define SysTimer_BASE __SYSTIMER_BASEADDR /*!< SysTick Base Address */ +#define SysTimer ((SysTimer_Type *)SysTimer_BASE) /*!< SysTick configuration struct */ /** * \defgroup NMSIS_Core_SysTimer SysTimer Functions @@ -171,15 +170,14 @@ __STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip) { /** * \brief System Tick Configuration - * \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer. + * \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick + * Timer. * - * In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt - * when it matchs the ticks user set, during the timer interrupt user should reload the system tick using \ref SysTick_Reload function - * or similar function written by user, so it can produce period timer interrupt. - * \param [in] ticks Number of ticks between two interrupts. - * \return 0 Function succeeded. - * \return 1 Function failed. - * \sa + * In our default implementation, the timer counter will be set to zero, and it will start a timer + * compare non-vector interrupt when it matchs the ticks user set, during the timer interrupt user + * should reload the system tick using \ref SysTick_Reload function or similar function written by + * user, so it can produce period timer interrupt. \param [in] ticks Number of ticks between two + * interrupts. \return 0 Function succeeded. \return 1 Function failed. \sa * - \ref SysTimer_SetCompareValue; SysTimer_SetLoadValue */ __STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks) { diff --git a/crt/include/retrosoc/core/archinfo.h b/crt/include/retrosoc/core/archinfo.h new file mode 100644 index 00000000..9df44645 --- /dev/null +++ b/crt/include/retrosoc/core/archinfo.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_ARCHINFO_H +#define RETROSOC_ARCHINFO_H + +void ip_archinfo_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/core/irq.h b/crt/include/retrosoc/core/irq.h new file mode 100644 index 00000000..4147cb11 --- /dev/null +++ b/crt/include/retrosoc/core/irq.h @@ -0,0 +1,19 @@ +#ifndef RETROSOC_CORE_IRQ_H +#define RETROSOC_CORE_IRQ_H + +#include + +#include + +typedef void (*rs_trap_handler_t)(uintptr_t mcause, uintptr_t stack_pointer); + +rs_status_t rs_irq_register_exception(uint32_t id, rs_trap_handler_t handler); +rs_status_t rs_irq_register_core(uint32_t id, rs_trap_handler_t handler); +rs_status_t rs_irq_register_external(uint32_t id, rs_trap_handler_t handler); +rs_status_t rs_irq_enable_core(uint32_t id, rs_trap_handler_t handler); + +void irq_test(int argc, char **argv); +uint32_t system_trap_handler(uintptr_t mcause, uintptr_t stack_pointer); +void _premain_init(void); + +#endif diff --git a/crt/include/retrosoc/core/soc.h b/crt/include/retrosoc/core/soc.h new file mode 100644 index 00000000..49dcedb3 --- /dev/null +++ b/crt/include/retrosoc/core/soc.h @@ -0,0 +1,249 @@ +#ifndef _RETROSOC_DEF_H_ +#define _RETROSOC_DEF_H_ + +#include +#include + +#ifdef CORE_PICORV32 +#define HW_CORE "PicoRV32" +#elif CORE_HAZARD3 +#define HW_CORE "HAZARD3" +#else +#define HW_CORE "none" +#endif + +#define CPU_FREQ 72 // unit: MHz +#define UART_BPS 921600 // unit: bps +#define PSRAM_NUM 4 +#define PSRAM_SCLK_MIN_FREQ 12 // unit: MHz +#define PSRAM_SCLK_MAX_FREQ 133 // unit: MHz +#define PSRAM_SCLK_FREQ (CPU_FREQ / 2) + +#define SPFS_MEM_START 0x00000000 +#define SPFS_MEM_OFFST 32 * 1024 * 1024 +#define NMI_MEM_START 0x10000000 +#define NMI_MEM_OFFST 256 * 1024 * 1024 +#define APB_MEM_START 0x20000000 +#define APB_MEM_OFFST 256 * 1024 * 1024 +#define SRAM_MEM_START 0x30000000 +#define SRAM_MEM_OFFST 128 * 1024 +#define SDRAM_MEM_START 0x38000000 +#define SDRAM_MEM_OFFST 64 * 1024 * 1024 +#define PSRAM_MEM_START 0x40000000 +#define PSRAM_MEM_OFFST 8 * 1024 * 1024 * PSRAM_NUM +#define OPIPSRAM_MEM_START 0x48000000 +#define OPIPSRAM_MEM_OFFST 32 * 1024 * 1024 +#define XPI_MEM_START 0x50000000 +#define XPI_MEM_OFFST 256 * 1024 * 1024 +#define TF_CARD_START (uint32_t)0x60000000 +#define TF_CARD_OFFST (uint32_t)0x40000000 + +// gpio +#define reg_gpio_oe (*(volatile uint32_t *)0x10000000) +#define reg_gpio_cs (*(volatile uint32_t *)0x10000004) +#define reg_gpio_pu (*(volatile uint32_t *)0x10000008) +#define reg_gpio_pd (*(volatile uint32_t *)0x1000000c) +#define reg_gpio_do (*(volatile uint32_t *)0x10000010) +#define reg_gpio_di (*(volatile uint32_t *)0x10000014) +#define reg_gpio_ien (*(volatile uint32_t *)0x10000018) +#define reg_gpio_itype0 (*(volatile uint32_t *)0x1000001c) +#define reg_gpio_itype1 (*(volatile uint32_t *)0x10000020) +#define reg_gpio_istat (*(volatile uint32_t *)0x10000024) +#define reg_gpio_iofcfg (*(volatile uint32_t *)0x10000028) +#define reg_gpio_pinmux (*(volatile uint32_t *)0x1000002c) +// uart0 +#define reg_uart0_clkdiv (*(volatile uint32_t *)0x10001000) +#define reg_uart0_data (*(volatile uint32_t *)0x10001004) +// tim0 +#define reg_tim0_cfg (*(volatile uint32_t *)0x10002000) +#define reg_tim0_rld (*(volatile uint32_t *)0x10002004) +#define reg_tim0_val (*(volatile uint32_t *)0x10002008) +// tim1 +#define reg_tim1_cfg (*(volatile uint32_t *)0x10003000) +#define reg_tim1_rld (*(volatile uint32_t *)0x10003004) +#define reg_tim1_val (*(volatile uint32_t *)0x10003008) +// psram +#define reg_psram_wait (*(volatile uint32_t *)0x10004000) +#define reg_psram_chd (*(volatile uint32_t *)0x10004004) +#define reg_psram_init (*(volatile uint32_t *)0x10004008) +// spisd +#define reg_spisd_mode (*(volatile uint32_t *)0x10005000) +#define reg_spisd_clkdiv (*(volatile uint32_t *)0x10005004) +#define reg_spisd_addr (*(volatile uint32_t *)0x10005008) +#define reg_spisd_txdata (*(volatile uint32_t *)0x1000500C) +#define reg_spisd_rxdata (*(volatile uint32_t *)0x10005010) +#define reg_spisd_status (*(volatile uint32_t *)0x10005014) +#define reg_spisd_sync (*(volatile uint32_t *)0x10005018) +// i2c0 +#define reg_i2c0_clkdiv (*(volatile uint32_t *)0x10006000) +#define reg_i2c0_devaddr (*(volatile uint32_t *)0x10006004) +#define reg_i2c0_regaddr (*(volatile uint32_t *)0x10006008) +#define reg_i2c0_txdata (*(volatile uint32_t *)0x1000600C) +#define reg_i2c0_rxdata (*(volatile uint32_t *)0x10006010) +#define reg_i2c0_xfer (*(volatile uint32_t *)0x10006014) +#define reg_i2c0_cfg (*(volatile uint32_t *)0x10006018) +#define reg_i2c0_status (*(volatile uint32_t *)0x1000601C) +// i2s +#define reg_i2s_mode (*(volatile uint32_t *)0x10007000) +#define reg_i2s_format (*(volatile uint32_t *)0x10007004) +#define reg_i2s_upbound (*(volatile uint32_t *)0x10007008) +#define reg_i2s_lowbound (*(volatile uint32_t *)0x1000700C) +#define reg_i2s_recven (*(volatile uint32_t *)0x10007010) +#define reg_i2s_txdata (*(volatile uint32_t *)0x10007014) +#define reg_i2s_rxdata (*(volatile uint32_t *)0x10007018) +#define reg_i2s_status (*(volatile uint32_t *)0x1000701C) +// onewire +#define reg_onewire_clkdiv (*(volatile uint32_t *)0x10008000) +#define reg_onewire_zerocnt (*(volatile uint32_t *)0x10008004) +#define reg_onewire_onecnt (*(volatile uint32_t *)0x10008008) +#define reg_onewire_rstcnt (*(volatile uint32_t *)0x1000800C) +#define reg_onewire_txdata (*(volatile uint32_t *)0x10008010) +#define reg_onewire_ctrl (*(volatile uint32_t *)0x10008014) +#define reg_onewire_status (*(volatile uint32_t *)0x10008018) +// xpi +#define reg_xpi_cfgidx (*(volatile uint32_t *)0x10009000) +#define reg_xpi_accmd (*(volatile uint32_t *)0x10009004) +#define reg_xpi_mmstad (*(volatile uint32_t *)0x10009008) +#define reg_xpi_mmoffst (*(volatile uint32_t *)0x1000900C) +#define reg_xpi_mode (*(volatile uint32_t *)0x10009010) +#define reg_xpi_nss (*(volatile uint32_t *)0x10009014) +#define reg_xpi_clkdiv (*(volatile uint32_t *)0x10009018) +#define reg_xpi_rdwr (*(volatile uint32_t *)0x1000901C) +#define reg_xpi_revdat (*(volatile uint32_t *)0x10009020) +#define reg_xpi_txupb (*(volatile uint32_t *)0x10009024) +#define reg_xpi_txlowb (*(volatile uint32_t *)0x10009028) +#define reg_xpi_rxupb (*(volatile uint32_t *)0x1000902C) +#define reg_xpi_rxlowb (*(volatile uint32_t *)0x10009030) +#define reg_xpi_flush (*(volatile uint32_t *)0x10009034) +#define reg_xpi_cmdtyp (*(volatile uint32_t *)0x10009038) +#define reg_xpi_cmdlen (*(volatile uint32_t *)0x1000903C) +#define reg_xpi_cmddat (*(volatile uint32_t *)0x10009040) +#define reg_xpi_adrtyp (*(volatile uint32_t *)0x10009044) +#define reg_xpi_adrlen (*(volatile uint32_t *)0x10009048) +#define reg_xpi_adrdat (*(volatile uint32_t *)0x1000904C) +#define reg_xpi_alttyp (*(volatile uint32_t *)0x10009050) +#define reg_xpi_altlen (*(volatile uint32_t *)0x10009054) +#define reg_xpi_altdat (*(volatile uint32_t *)0x10009058) +#define reg_xpi_tdulen (*(volatile uint32_t *)0x1000905C) +#define reg_xpi_rdulen (*(volatile uint32_t *)0x10009060) +#define reg_xpi_dattyp (*(volatile uint32_t *)0x10009064) +#define reg_xpi_datlen (*(volatile uint32_t *)0x10009068) +#define reg_xpi_datbit (*(volatile uint32_t *)0x1000906C) +#define reg_xpi_hlvlen (*(volatile uint32_t *)0x10009070) +#define reg_xpi_txdata (*(volatile uint32_t *)0x10009074) +#define reg_xpi_rxdata (*(volatile uint32_t *)0x10009078) +#define reg_xpi_start (*(volatile uint32_t *)0x1000907C) +#define reg_xpi_status (*(volatile uint32_t *)0x10009080) +// dma(32b xfer, hardware trigger by I2S fifo, QSPI fifo) +#define reg_dma_mode (*(volatile uint32_t *)0x1000A000) +#define reg_dma_srcaddr (*(volatile uint32_t *)0x1000A004) +#define reg_dma_srcincr (*(volatile uint32_t *)0x1000A008) +#define reg_dma_dstaddr (*(volatile uint32_t *)0x1000A00C) +#define reg_dma_dstincr (*(volatile uint32_t *)0x1000A010) +#define reg_dma_xferlen (*(volatile uint32_t *)0x1000A014) +#define reg_dma_start (*(volatile uint32_t *)0x1000A018) +#define reg_dma_stop (*(volatile uint32_t *)0x1000A01C) +#define reg_dma_reset (*(volatile uint32_t *)0x1000A020) +#define reg_dma_status (*(volatile uint32_t *)0x1000A024) +#define reg_dma_fsm (*(volatile uint32_t *)0x1000A028) +// sys ctrl +#define reg_sysctrl_coresel (*(volatile uint32_t *)0x1000B000) +#define reg_sysctrl_ipsel (*(volatile uint32_t *)0x1000B004) +#define reg_sysctrl_i2csel (*(volatile uint32_t *)0x1000B008) +#define reg_sysctrl_qspicsel (*(volatile uint32_t *)0x1000B00C) +// clint +#define reg_clint_mtimel (*(volatile uint32_t *)0x1000C000) +#define reg_clint_mtimeh (*(volatile uint32_t *)0x1000C004) +#define reg_clint_mtimecmpl (*(volatile uint32_t *)0x1000C008) +#define reg_clint_mtimecmph (*(volatile uint32_t *)0x1000C00C) +#define reg_clint_msip (*(volatile uint32_t *)0x1000C010) +#define reg_clint_clkdiv (*(volatile uint32_t *)0x1000C014) +// sdram +#define reg_sdram_clkdiv (*(volatile uint32_t *)0x1000D000) +#define reg_sdram_cfg (*(volatile uint32_t *)0x1000D004) +// dvp +#define reg_dvp_recven (*(volatile uint32_t *)0x1000E000) +#define reg_dvp_rxdata (*(volatile uint32_t *)0x1000E004) +#define reg_dvp_status (*(volatile uint32_t *)0x1000E008) +// sdio +#define reg_sdio_cfg (*(volatile uint32_t *)0x1000F000) +// opipsram +#define reg_opipsram_cfg (*(volatile uint32_t *)0x10010000) +// i2c1 +#define reg_i2c1_clkdiv (*(volatile uint32_t *)0x10011000) +#define reg_i2c1_devaddr (*(volatile uint32_t *)0x10011004) +#define reg_i2c1_regaddr (*(volatile uint32_t *)0x10011008) +#define reg_i2c1_txdata (*(volatile uint32_t *)0x1001100C) +#define reg_i2c1_rxdata (*(volatile uint32_t *)0x10011010) +#define reg_i2c1_xfer (*(volatile uint32_t *)0x10011014) +#define reg_i2c1_cfg (*(volatile uint32_t *)0x10011018) +#define reg_i2c1_status (*(volatile uint32_t *)0x1001101C) +// ga +#define reg_ga_cfg (*(volatile uint32_t *)0x10012000) +// apu +#define reg_apu_cfg (*(volatile uint32_t *)0x10013000) +// archinfo +#define reg_archinfo_sys (*(volatile uint32_t *)0x20000000) +#define reg_archinfo_idl (*(volatile uint32_t *)0x20000004) +#define reg_archinfo_idh (*(volatile uint32_t *)0x20000008) +// rng +#define reg_rng_ctrl (*(volatile uint32_t *)0x20001000) +#define reg_rng_seed (*(volatile uint32_t *)0x20001004) +#define reg_rng_val (*(volatile uint32_t *)0x20001008) +// uart +#define reg_uart1_lcr (*(volatile uint32_t *)0x20002000) +#define reg_uart1_div (*(volatile uint32_t *)0x20002004) +#define reg_uart1_trx (*(volatile uint32_t *)0x20002008) +#define reg_uart1_fcr (*(volatile uint32_t *)0x2000200c) +#define reg_uart1_lsr (*(volatile uint32_t *)0x20002010) +// pwm +#define reg_pwm_ctrl (*(volatile uint32_t *)0x20003000) +#define reg_pwm_pscr (*(volatile uint32_t *)0x20003004) +#define reg_pwm_cnt (*(volatile uint32_t *)0x20003008) +#define reg_pwm_cmp (*(volatile uint32_t *)0x2000300c) +#define reg_pwm_cr0 (*(volatile uint32_t *)0x20003010) +#define reg_pwm_cr1 (*(volatile uint32_t *)0x20003014) +#define reg_pwm_cr2 (*(volatile uint32_t *)0x20003018) +#define reg_pwm_cr3 (*(volatile uint32_t *)0x2000301c) +#define reg_pwm_stat (*(volatile uint32_t *)0x20003020) +// ps2 +#define reg_ps2_ctrl (*(volatile uint32_t *)0x20004000) +#define reg_ps2_data (*(volatile uint32_t *)0x20004004) +#define reg_ps2_stat (*(volatile uint32_t *)0x20004008) +// rtc +#define reg_rtc_ctrl (*(volatile uint32_t *)0x20005000) +#define reg_rtc_pscr (*(volatile uint32_t *)0x20005004) +#define reg_rtc_cnt (*(volatile uint32_t *)0x20005008) +#define reg_rtc_alrm (*(volatile uint32_t *)0x2000500C) +#define reg_rtc_ista (*(volatile uint32_t *)0x20005010) +#define reg_rtc_ssta (*(volatile uint32_t *)0x20005014) +// wdg +#define reg_wdg_ctrl (*(volatile uint32_t *)0x20006000) +#define reg_wdg_pscr (*(volatile uint32_t *)0x20006004) +#define reg_wdg_cnt (*(volatile uint32_t *)0x20006008) +#define reg_wdg_cmp (*(volatile uint32_t *)0x2000600C) +#define reg_wdg_stat (*(volatile uint32_t *)0x20006010) +#define reg_wdg_key (*(volatile uint32_t *)0x20006014) +#define reg_wdg_feed (*(volatile uint32_t *)0x20006018) +// crc +#define reg_crc_ctrl (*(volatile uint32_t *)0x20007000) +#define reg_crc_init (*(volatile uint32_t *)0x20007004) +#define reg_crc_xorv (*(volatile uint32_t *)0x20007008) +#define reg_crc_data (*(volatile uint32_t *)0x2000700C) +#define reg_crc_stat (*(volatile uint32_t *)0x20007010) +// tim3 +#define reg_tim3_ctrl (*(volatile uint32_t *)0x20008000) +#define reg_tim3_pscr (*(volatile uint32_t *)0x20008004) +#define reg_tim3_cnt (*(volatile uint32_t *)0x20008008) +#define reg_tim3_cmp (*(volatile uint32_t *)0x2000800C) +#define reg_tim3_stat (*(volatile uint32_t *)0x20008010) +// user ip design(example) +#define reg_user_ip_reg0 (*(volatile uint32_t *)0x2000F000) +#define reg_user_ip_reg1 (*(volatile uint32_t *)0x2000F004) +#define reg_user_ip_reg2 (*(volatile uint32_t *)0x2000F008) +#define reg_user_ip_reg3 (*(volatile uint32_t *)0x2000F00C) +#define reg_user_ip_reg4 (*(volatile uint32_t *)0x2000F010) +#define reg_user_ip_reg5 (*(volatile uint32_t *)0x2000F014) +#define reg_user_ip_reg6 (*(volatile uint32_t *)0x2000F018) +// ... user custom area ... +#endif diff --git a/crt/include/retrosoc/core/status.h b/crt/include/retrosoc/core/status.h new file mode 100644 index 00000000..5cee6728 --- /dev/null +++ b/crt/include/retrosoc/core/status.h @@ -0,0 +1,21 @@ +#ifndef RETROSOC_CORE_STATUS_H +#define RETROSOC_CORE_STATUS_H + +#include + +typedef enum { + RS_OK = 0, + RS_EINVAL = -1, + RS_ENOMEM = -2, + RS_ENOSPC = -3, + RS_ETIMEOUT = -4, + RS_EIO = -5, + RS_ENOTSUP = -6, + RS_EFORMAT = -7, +} rs_status_t; + +typedef uint32_t rs_timeout_t; + +#define RS_TIMEOUT_DEFAULT ((rs_timeout_t)1000000U) + +#endif diff --git a/crt/include/retrosoc/core/wait.h b/crt/include/retrosoc/core/wait.h new file mode 100644 index 00000000..ee70f2e8 --- /dev/null +++ b/crt/include/retrosoc/core/wait.h @@ -0,0 +1,50 @@ +#ifndef RETROSOC_CORE_WAIT_H +#define RETROSOC_CORE_WAIT_H + +#include +#include + +#include + +static inline rs_status_t rs_wait_mask(volatile const uint32_t *reg, uint32_t mask, + uint32_t expected, rs_timeout_t timeout) { + if ((reg == NULL) || (mask == 0U)) { + return RS_EINVAL; + } + + while (timeout-- != 0U) { + if ((*reg & mask) == expected) { + return RS_OK; + } + } + + return RS_ETIMEOUT; +} + +static inline rs_status_t rs_wait_value(volatile const uint32_t *reg, uint32_t expected, + rs_timeout_t timeout) { + if (reg == NULL) { + return RS_EINVAL; + } + while (timeout-- != 0U) { + if (*reg == expected) { + return RS_OK; + } + } + return RS_ETIMEOUT; +} + +static inline rs_status_t rs_wait_not_value(volatile const uint32_t *reg, uint32_t value, + rs_timeout_t timeout) { + if (reg == NULL) { + return RS_EINVAL; + } + while (timeout-- != 0U) { + if (*reg != value) { + return RS_OK; + } + } + return RS_ETIMEOUT; +} + +#endif diff --git a/crt/include/retrosoc/hal/advanced_timer.h b/crt/include/retrosoc/hal/advanced_timer.h new file mode 100644 index 00000000..b98db352 --- /dev/null +++ b/crt/include/retrosoc/hal/advanced_timer.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_ADVTIM_H +#define RETROSOC_ADVTIM_H + +void ip_advtim_test(void); +#endif diff --git a/crt/include/retrosoc/hal/crc.h b/crt/include/retrosoc/hal/crc.h new file mode 100644 index 00000000..1e847f22 --- /dev/null +++ b/crt/include/retrosoc/hal/crc.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_CRC_H +#define RETROSOC_CRC_H + +void ip_crc_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/hal/dma.h b/crt/include/retrosoc/hal/dma.h new file mode 100644 index 00000000..d27bb3b4 --- /dev/null +++ b/crt/include/retrosoc/hal/dma.h @@ -0,0 +1,17 @@ +#ifndef RETROSOC_HAL_DMA_H +#define RETROSOC_HAL_DMA_H + +#include + +#include + +rs_status_t rs_dma_config(uint32_t mode, uintptr_t source, uint32_t source_increment, + uintptr_t destination, uint32_t destination_increment, + uint32_t transfer_words); +rs_status_t rs_dma_start(void); +rs_status_t rs_dma_stop(void); +rs_status_t rs_dma_reset(void); +rs_status_t rs_dma_wait(rs_timeout_t timeout); +void ip_dma_test(void); + +#endif diff --git a/crt/include/retrosoc/hal/gpio.h b/crt/include/retrosoc/hal/gpio.h new file mode 100644 index 00000000..6a21df4a --- /dev/null +++ b/crt/include/retrosoc/hal/gpio.h @@ -0,0 +1,6 @@ +#ifndef RETROSOC_GPIO_H +#define RETROSOC_GPIO_H + +void ip_gpio_test(int argc, char **argv); + +#endif diff --git a/crt/include/retrosoc/hal/hpuart.h b/crt/include/retrosoc/hal/hpuart.h new file mode 100644 index 00000000..0ef4017c --- /dev/null +++ b/crt/include/retrosoc/hal/hpuart.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_HPUART_H +#define RETROSOC_HPUART_H + +void ip_hpuart_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/hal/i2c.h b/crt/include/retrosoc/hal/i2c.h new file mode 100644 index 00000000..e7e0746b --- /dev/null +++ b/crt/include/retrosoc/hal/i2c.h @@ -0,0 +1,19 @@ +#ifndef RETROSOC_HAL_I2C_H +#define RETROSOC_HAL_I2C_H + +#include + +#include + +#define RS_I2C_XFER_WRITE 0x2U +#define RS_I2C_XFER_READ 0x3U +#define RS_I2C_DEVICE_ADDRESS_8BIT 0U +#define RS_I2C_DEVICE_ADDRESS_16BIT 1U + +rs_status_t rs_i2c0_init(uint8_t clock_divider); +rs_status_t rs_i2c0_write(uint8_t device_address, uint16_t register_address, uint8_t address_width, + uint8_t count, const uint8_t *data, rs_timeout_t timeout); +rs_status_t rs_i2c0_read(uint8_t device_address, uint16_t register_address, uint8_t address_width, + uint8_t count, uint8_t *data, rs_timeout_t timeout); + +#endif diff --git a/crt/include/retrosoc/hal/i2s.h b/crt/include/retrosoc/hal/i2s.h new file mode 100644 index 00000000..d265a6c1 --- /dev/null +++ b/crt/include/retrosoc/hal/i2s.h @@ -0,0 +1,6 @@ +#ifndef RETROSOC_I2S_H +#define RETROSOC_I2S_H + +void ip_i2s_test(int argc, char **argv); + +#endif diff --git a/crt/inc/rs_lcd.h b/crt/include/retrosoc/hal/lcd.h similarity index 74% rename from crt/inc/rs_lcd.h rename to crt/include/retrosoc/hal/lcd.h index 0f71b1a5..1a8049cb 100644 --- a/crt/inc/rs_lcd.h +++ b/crt/include/retrosoc/hal/lcd.h @@ -1,10 +1,10 @@ -#ifndef TINYLCD_H__ -#define TINYLCD_H__ +#ifndef RETROSOC_LCD_H +#define RETROSOC_LCD_H #include -#define lcd_dc_clr (reg_gpio_do = (uint32_t)0b000) -#define lcd_dc_set (reg_gpio_do = (uint32_t)0b100) +#define lcd_dc_clr (reg_gpio_do = (uint32_t)0b000) +#define lcd_dc_set (reg_gpio_do = (uint32_t)0b100) #define USE_HORIZONTAL 2 @@ -18,9 +18,9 @@ #define USE_SPISD_DMA -void lcd_init(); +void lcd_init(void); void ip_lcd_test(int argc, char **argv); void lcd_addr_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void lcd_fill_image(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint32_t *data); void lcd_fill_video(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint32_t *data); -#endif \ No newline at end of file +#endif diff --git a/crt/include/retrosoc/hal/onewire.h b/crt/include/retrosoc/hal/onewire.h new file mode 100644 index 00000000..5ec6e24d --- /dev/null +++ b/crt/include/retrosoc/hal/onewire.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_1WIRE_H +#define RETROSOC_1WIRE_H + +void ip_1wire_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/hal/ps2.h b/crt/include/retrosoc/hal/ps2.h new file mode 100644 index 00000000..6406ee59 --- /dev/null +++ b/crt/include/retrosoc/hal/ps2.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_PS2_H +#define RETROSOC_PS2_H + +void ip_ps2_test(int argc, char **argv); +#endif diff --git a/crt/inc/rs_psram.h b/crt/include/retrosoc/hal/psram.h similarity index 58% rename from crt/inc/rs_psram.h rename to crt/include/retrosoc/hal/psram.h index 26a65bd0..bd4e2af5 100644 --- a/crt/inc/rs_psram.h +++ b/crt/include/retrosoc/hal/psram.h @@ -1,9 +1,9 @@ -#ifndef TINYPSRAM_H__ -#define TINYPSRAM_H__ +#ifndef RETROSOC_PSRAM_H +#define RETROSOC_PSRAM_H #include -void ip_psram_boot(); +void ip_psram_boot(void); uint32_t xorshift32(uint32_t *state); void ip_psram_selftest(uint32_t addr, uint32_t range); -#endif \ No newline at end of file +#endif diff --git a/crt/include/retrosoc/hal/pwm.h b/crt/include/retrosoc/hal/pwm.h new file mode 100644 index 00000000..ab71112d --- /dev/null +++ b/crt/include/retrosoc/hal/pwm.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_PWM_H +#define RETROSOC_PWM_H + +void ip_pwm_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/hal/qspi.h b/crt/include/retrosoc/hal/qspi.h new file mode 100644 index 00000000..f0dd547f --- /dev/null +++ b/crt/include/retrosoc/hal/qspi.h @@ -0,0 +1,42 @@ +#ifndef RETROSOC_QSPI_H +#define RETROSOC_QSPI_H + +#include + +#define USE_QSPI0_DMA + +typedef struct { + uint32_t mode; + uint32_t nss; + uint32_t clkdiv; + uint32_t txub; + uint32_t txlb; + uint32_t rxub; + uint32_t rxlb; + uint32_t hlven; +} QSPI0_InitStruct_t; + +void qspi0_init(QSPI0_InitStruct_t val); + +void qspi0_wr(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, uint32_t adrtyp, uint32_t adrlen, + uint32_t adrdat, uint32_t dumlen, uint32_t dattyp, uint32_t datlen, uint32_t datbit, + uint32_t *dat_list); + +void qspi0_rd(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, uint32_t adrtyp, uint32_t adrlen, + uint32_t adrdat, uint32_t dumlen, uint32_t dattyp, uint32_t datlen, uint32_t datbit, + uint32_t *dat_list); + +void qspi0_xfer_config(uint32_t rdwr, uint32_t revdat, uint32_t flush, uint32_t cmdtyp, + uint32_t cmdlen, uint32_t adrtyp, uint32_t adrlen, uint32_t dumlen, + uint32_t dattyp, uint32_t datlen, uint32_t datbit); + +void qspi0_wr_cmd8(uint8_t dat); +void qspi0_wr_cmd16(uint16_t dat); + +void qspi0_wr_dat8(uint8_t dat); +void qspi0_wr_dat16(uint16_t dat); +void qspi0_wr_data32(uint32_t *dat, uint32_t len); +void qspi0_dma_xfer(uint32_t addr, uint32_t len); + +void qspi_dev_init(void); +#endif diff --git a/crt/include/retrosoc/hal/rng.h b/crt/include/retrosoc/hal/rng.h new file mode 100644 index 00000000..c3372428 --- /dev/null +++ b/crt/include/retrosoc/hal/rng.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_RNG_H +#define RETROSOC_RNG_H + +void ip_rng_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/hal/rtc.h b/crt/include/retrosoc/hal/rtc.h new file mode 100644 index 00000000..52bebfba --- /dev/null +++ b/crt/include/retrosoc/hal/rtc.h @@ -0,0 +1,5 @@ +#ifndef RETROSOC_RTC_H +#define RETROSOC_RTC_H + +void ip_rtc_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/hal/spisd.h b/crt/include/retrosoc/hal/spisd.h new file mode 100644 index 00000000..67172a17 --- /dev/null +++ b/crt/include/retrosoc/hal/spisd.h @@ -0,0 +1,18 @@ +#ifndef RETROSOC_HAL_SPISD_H +#define RETROSOC_HAL_SPISD_H + +#include +#include + +#include + +#define RS_SPISD_SECTOR_SIZE 512U + +rs_status_t rs_spisd_read_bytes(void *buffer, size_t byte_count, uintptr_t address); +rs_status_t rs_spisd_sector_read(uint8_t *buffer, uint32_t sector, uint32_t count); +rs_status_t rs_spisd_sector_write(const uint8_t *buffer, uint32_t sector, uint32_t count); +rs_status_t rs_spisd_sector_sync(rs_timeout_t timeout); +void ip_spisd_test(void); +void ip_spisd_read(uint32_t address, uint32_t length); + +#endif diff --git a/crt/include/retrosoc/hal/timer.h b/crt/include/retrosoc/hal/timer.h new file mode 100644 index 00000000..1802adc6 --- /dev/null +++ b/crt/include/retrosoc/hal/timer.h @@ -0,0 +1,10 @@ +#ifndef RETROSOC_TIM_H +#define RETROSOC_TIM_H + +#include + +void delay_ms(uint32_t val); +void tim1_init(void); +uint32_t tim1_get_value(void); +void ip_tim_test(int argc, char **argv); +#endif diff --git a/crt/include/retrosoc/hal/uart.h b/crt/include/retrosoc/hal/uart.h new file mode 100644 index 00000000..ac596141 --- /dev/null +++ b/crt/include/retrosoc/hal/uart.h @@ -0,0 +1,9 @@ + +#ifndef RETROSOC_UART_H +#define RETROSOC_UART_H + +#include + +void uart0_init(uint32_t freq, uint32_t bps); +void putch(char ch); +#endif diff --git a/crt/inc/rs_wdg.h b/crt/include/retrosoc/hal/watchdog.h similarity index 53% rename from crt/inc/rs_wdg.h rename to crt/include/retrosoc/hal/watchdog.h index 6faf5de4..c2aea5b6 100644 --- a/crt/inc/rs_wdg.h +++ b/crt/include/retrosoc/hal/watchdog.h @@ -1,7 +1,9 @@ -#ifndef TINYWDG_H__ -#define TINYWDG_H__ +#ifndef RETROSOC_WDG_H +#define RETROSOC_WDG_H + +#include #define WDG_MAGIC_NUM (uint32_t)0x5F3759DF void ip_wdg_test(int argc, char **argv); -#endif \ No newline at end of file +#endif diff --git a/crt/include/retrosoc/lib/console.h b/crt/include/retrosoc/lib/console.h new file mode 100644 index 00000000..233fe3fd --- /dev/null +++ b/crt/include/retrosoc/lib/console.h @@ -0,0 +1,11 @@ + +#ifndef RETROSOC_PRINT_H +#define RETROSOC_PRINT_H + +#include + +void putchar(char c); +char getchar(void); +void print(const char *p); + +#endif diff --git a/crt/include/retrosoc/lib/printf.h b/crt/include/retrosoc/lib/printf.h new file mode 100644 index 00000000..167ca991 --- /dev/null +++ b/crt/include/retrosoc/lib/printf.h @@ -0,0 +1,16 @@ +#ifndef RETROSOC_LIB_PRINTF_H +#define RETROSOC_LIB_PRINTF_H + +#include +#include + +int rs_printf(const char *format, ...); +int rs_vsnprintf(char *dst, size_t dst_size, const char *format, va_list args); +int rs_snprintf(char *dst, size_t dst_size, const char *format, ...); + +/* Freestanding libc compatibility required by FatFs and CoreMark ports. */ +int printf(const char *format, ...); +int vsnprintf(char *dst, size_t dst_size, const char *format, va_list args); +int snprintf(char *dst, size_t dst_size, const char *format, ...); + +#endif diff --git a/crt/include/retrosoc/lib/stdlib.h b/crt/include/retrosoc/lib/stdlib.h new file mode 100644 index 00000000..022e5ab8 --- /dev/null +++ b/crt/include/retrosoc/lib/stdlib.h @@ -0,0 +1,20 @@ +#ifndef RETROSOC_LIB_STDLIB_H +#define RETROSOC_LIB_STDLIB_H + +#include + +#include + +#ifndef RAND_MAX +#define RAND_MAX 32767 +#endif + +rs_status_t rs_strtoi32(const char *str, int32_t *value); +rs_status_t rs_utoa(uint32_t value, char *dst, uint32_t base); +int atoi(const char *str); +char *itoa(unsigned int value, char *dst, int base); +int abs(int value); +int rand(void); +void srand(unsigned int seed); + +#endif diff --git a/crt/include/retrosoc/lib/string.h b/crt/include/retrosoc/lib/string.h new file mode 100644 index 00000000..b6d4657a --- /dev/null +++ b/crt/include/retrosoc/lib/string.h @@ -0,0 +1,24 @@ +#ifndef RETROSOC_LIB_STRING_H +#define RETROSOC_LIB_STRING_H + +#include +#include + +void *memset(void *dst, int value, size_t count); +void *memcpy(void *dst, const void *src, size_t count); +void *memmove(void *dst, const void *src, size_t count); +int memcmp(const void *lhs, const void *rhs, size_t count); +size_t strlen(const char *str); +char *strcpy(char *dst, const char *src); +char *strncpy(char *dst, const char *src, size_t count); +char *strcat(char *dst, const char *src); +int strcmp(const char *lhs, const char *rhs); +int strncmp(const char *lhs, const char *rhs, size_t count); +char *strchr(const char *str, int value); + +size_t rs_strlcpy(char *dst, const char *src, size_t dst_size); +size_t rs_strlcat(char *dst, const char *src, size_t dst_size); +void rs_trim_whitespace(char *str); +void rs_remove_suffix(char *dst, size_t dst_size, const char *src, char separator); + +#endif diff --git a/crt/include/retrosoc/service/bench.h b/crt/include/retrosoc/service/bench.h new file mode 100644 index 00000000..d57d0d50 --- /dev/null +++ b/crt/include/retrosoc/service/bench.h @@ -0,0 +1,9 @@ +#ifndef RETROSOC_BENCH_H +#define RETROSOC_BENCH_H + +#include +#include + +uint32_t rs_bench(bool verbose, uint32_t *instns_p); + +#endif diff --git a/crt/inc/rs_booter.h b/crt/include/retrosoc/service/booter.h similarity index 68% rename from crt/inc/rs_booter.h rename to crt/include/retrosoc/service/booter.h index b04ba73f..09912a05 100644 --- a/crt/inc/rs_booter.h +++ b/crt/include/retrosoc/service/booter.h @@ -1,5 +1,7 @@ -#ifndef TINYBOOTER_H__ -#define TINYBOOTER_H__ +#ifndef RETROSOC_BOOTER_H +#define RETROSOC_BOOTER_H + +#include extern uint32_t _flash_wait_start, _flash_wait_end; extern uint32_t _ram_lma, _ram_vma; @@ -9,7 +11,7 @@ extern uint32_t _psram_lma, _psram_vma, _edata; extern uint32_t _sbss, _ebss; extern uint32_t _heap_start; -void app_info(); -void tinybooter(); +void rs_app_info(void); +void rs_booter(void); -#endif \ No newline at end of file +#endif diff --git a/crt/include/retrosoc/service/shell.h b/crt/include/retrosoc/service/shell.h new file mode 100644 index 00000000..f41ae174 --- /dev/null +++ b/crt/include/retrosoc/service/shell.h @@ -0,0 +1,31 @@ +#ifndef RETROSOC_SERVICE_SHELL_H +#define RETROSOC_SERVICE_SHELL_H + +#include +#include + +#include + +#define RS_SHELL_MAX_ARGC 16U +#define RS_SHELL_MAX_COMMANDS 72U +#define RS_SHELL_MAX_COMMAND_LENGTH 100U +#define RS_SHELL_MAX_HISTORY 100U +#define RS_SHELL_MAX_PATH 128U +#define RS_SHELL_MAX_BUFFER (512U * 1024U) + +typedef void (*rs_shell_handler_t)(int argc, char **argv); + +typedef struct { + const char *name; + const char *info; + bool batch; + rs_shell_handler_t handler; +} rs_shell_command_t; + +rs_status_t rs_shell_register(const char *name, const char *info, bool batch, + rs_shell_handler_t handler); +void rs_shell_init(void); +void rs_shell_batch_run(void); +void rs_shell_launch(void); + +#endif diff --git a/crt/libgcc/clzsi2.c b/crt/libgcc/clzsi2.c deleted file mode 100644 index ea25ab63..00000000 --- a/crt/libgcc/clzsi2.c +++ /dev/null @@ -1,21 +0,0 @@ -int __clzsi2(unsigned int value) { - if (value == 0) return 32; - - // keep MSB - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - value = (value >> 1) + 1; - - // de bruijn sequence - static const int deBruijn[32] = { - 0, 9, 1, 10, 13, 21, 2, 29, - 11, 14, 16, 18, 22, 25, 3, 30, - 8, 12, 20, 28, 15, 17, 24, 7, - 19, 27, 23, 6, 26, 5, 4, 31 - }; - - return 31 - deBruijn[(value * 0x07C4ACDDU) >> 27]; -} \ No newline at end of file diff --git a/crt/libgcc/divdi3.c b/crt/libgcc/divdi3.c deleted file mode 100644 index e4f6428a..00000000 --- a/crt/libgcc/divdi3.c +++ /dev/null @@ -1,34 +0,0 @@ -long long __divdi3(long long dividend, long long divisor) { - if (divisor == 0) return 0; - - // Handle special overflow case - if (dividend == (-9223372036854775807LL - 1) && divisor == -1) { - return dividend; - } - - // Handle signs - int sign = 1; - if (dividend < 0) { - sign = -sign; - dividend = -dividend; - } - if (divisor < 0) { - sign = -sign; - divisor = -divisor; - } - - // Shift and subtract algorithm - long long quotient = 0; - long long remainder = 0; - - for (int i = 63; i >= 0; i--) { - remainder = (remainder << 1) | ((dividend >> i) & 1); - - if (remainder >= divisor) { - remainder -= divisor; - quotient |= (1LL << i); - } - } - - return sign < 0 ? -quotient : quotient; -} \ No newline at end of file diff --git a/crt/libgcc/ffssi2.c b/crt/libgcc/ffssi2.c deleted file mode 100644 index 26e135bd..00000000 --- a/crt/libgcc/ffssi2.c +++ /dev/null @@ -1,12 +0,0 @@ -int __ffssi2(unsigned int value) { - static const char table[32] = { - 0, 1, 2, 24, 3, 19, 6, 25, 22, 4, 20, 10, 16, 7, 12, 26, - 31, 23, 18, 5, 21, 9, 15, 11, 30, 17, 8, 14, 29, 13, 28, 27 - }; - - // calc LSB mask - unsigned int mask = value & -value; - - // de bruijn sequence - return table[(mask * 0x04D7651F) >> 27]; -} \ No newline at end of file diff --git a/crt/libgcc/mulsi3.c b/crt/libgcc/mulsi3.c deleted file mode 100644 index a8ff18ac..00000000 --- a/crt/libgcc/mulsi3.c +++ /dev/null @@ -1,14 +0,0 @@ -unsigned int -__mulsi3 (unsigned int a, unsigned int b) -{ - unsigned int r = 0; - - while (a) - { - if (a & 1) - r += b; - a >>= 1; - b <<= 1; - } - return r; -} \ No newline at end of file diff --git a/crt/libgcc/udivdi3.c b/crt/libgcc/udivdi3.c deleted file mode 100644 index d0338245..00000000 --- a/crt/libgcc/udivdi3.c +++ /dev/null @@ -1,58 +0,0 @@ -#include - -unsigned long long __udivdi3(unsigned long long dividend, unsigned long long divisor) { - // Handle division by zero case - if (divisor == 0) return 0; - - // Fast path: dividend smaller than divisor - if (dividend < divisor) return 0; - - // Fast path: divisor equals 1 - if (divisor == 1) return dividend; - - // Split 64-bit values into 32-bit parts - uint32_t d_hi = (uint32_t)(divisor >> 32); - uint32_t d_lo = (uint32_t)(divisor & 0xFFFFFFFF); - uint32_t n_hi = (uint32_t)(dividend >> 32); - uint32_t n_lo = (uint32_t)(dividend & 0xFFFFFFFF); - - // Case 1: Divisor is 32-bit - if (d_hi == 0) { - // 64-bit dividend divided by 32-bit divisor - uint32_t rem_hi = n_hi % d_lo; - uint64_t rem64 = ((uint64_t)rem_hi << 32) | n_lo; - uint32_t quo_hi = n_hi / d_lo; - uint32_t quo_lo = (uint32_t)(rem64 / divisor); - - return ((uint64_t)quo_hi << 32) | quo_lo; - } - - // Case 2: Dividend's high 32 bits less than divisor's high 32 bits - if (n_hi < d_hi) { - return 0; - } - - // Case 3: General algorithm - // Calculate high quotient estimate - uint32_t q_estimate = n_hi / d_hi; - uint32_t r = n_hi % d_hi; - - // Compute intermediate value - uint64_t u = ((uint64_t)r << 32) | n_lo; - uint64_t product = (uint64_t)q_estimate * divisor; - - // Correct quotient estimate - while (product > u) { - q_estimate--; - product -= divisor; - } - - // Calculate final high quotient - uint32_t q_hi = q_estimate; - - // Calculate low 32-bit quotient - uint64_t remainder = u - product; - uint32_t q_lo = (uint32_t)(remainder / divisor); - - return ((uint64_t)q_hi << 32) | q_lo; -} \ No newline at end of file diff --git a/crt/libgcc/umoddi3.c b/crt/libgcc/umoddi3.c deleted file mode 100644 index 413f5578..00000000 --- a/crt/libgcc/umoddi3.c +++ /dev/null @@ -1,51 +0,0 @@ -#include - -unsigned long long __umoddi3(unsigned long long dividend, unsigned long long divisor) { - // Handle division by zero case - if (divisor == 0) return 0; - - // Fast path: dividend smaller than divisor - if (dividend < divisor) return dividend; - - // Fast path: divisor equals 1 - if (divisor == 1) return 0; - - // Fast path: divisor is power of two - if ((divisor & (divisor - 1)) == 0) { - return dividend & (divisor - 1); - } - - // Split 64-bit values into 32-bit parts - uint32_t d_hi = divisor >> 32; - uint32_t d_lo = divisor & 0xFFFFFFFF; - uint32_t n_hi = dividend >> 32; - uint32_t n_lo = dividend & 0xFFFFFFFF; - - // Handle 32-bit divisor case - if (d_hi == 0) { - // 64-bit dividend divided by 32-bit divisor - uint32_t rem_hi = n_hi % d_lo; - uint64_t rem64 = ((uint64_t)rem_hi << 32) | n_lo; - return rem64 % divisor; - } - - // Handle case where dividend's high bits < divisor's high bits - if (n_hi < d_hi) { - return dividend; - } - - // Calculate quotient and remainder - uint32_t q = n_hi / d_hi; - uint32_t r = n_hi % d_hi; - - // Compute intermediate remainder - uint64_t u = ((uint64_t)r << 32) | n_lo; - uint64_t rem = u - q * divisor; - - // Correction step - while (rem >= divisor) { - rem -= divisor; - } - - return rem; -} \ No newline at end of file diff --git a/crt/lds/ld2_psram.lds b/crt/linker/ld2_psram.lds similarity index 100% rename from crt/lds/ld2_psram.lds rename to crt/linker/ld2_psram.lds diff --git a/crt/lds/ld2_sdram.lds b/crt/linker/ld2_sdram.lds similarity index 100% rename from crt/lds/ld2_sdram.lds rename to crt/linker/ld2_sdram.lds diff --git a/crt/lds/ld2_sram.lds b/crt/linker/ld2_sram.lds similarity index 100% rename from crt/lds/ld2_sram.lds rename to crt/linker/ld2_sram.lds diff --git a/crt/lds/xip.lds b/crt/linker/xip.lds similarity index 100% rename from crt/lds/xip.lds rename to crt/linker/xip.lds diff --git a/crt/src/rs_archinfo.c b/crt/src/core/archinfo.c similarity index 65% rename from crt/src/rs_archinfo.c rename to crt/src/core/archinfo.c index b92055ae..229c7b3c 100644 --- a/crt/src/rs_archinfo.c +++ b/crt/src/core/archinfo.c @@ -1,10 +1,10 @@ -#include -#include -#include +#include +#include +#include void ip_archinfo_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("[APB IP] archinfo test\n"); printf("[ARCHINFO SYS] %x\n", reg_archinfo_sys); printf("[ARCHINFO IDL] %x\n", reg_archinfo_idl); diff --git a/crt/src/core/irq.c b/crt/src/core/irq.c new file mode 100644 index 00000000..c1617db5 --- /dev/null +++ b/crt/src/core/irq.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include + +#define RS_TIMER_DELTA_VALUE 360000UL +#define RS_IRQ_TEST_TIMEOUT_MS 6000U + +static volatile uint32_t timer_irq_count; +static volatile uint32_t software_irq_count; +static volatile uint32_t software_irq_ready = 1U; + +static void rs_timer_irq_handler(uintptr_t mcause, uintptr_t stack_pointer) { + uint64_t now; + + (void)mcause; + (void)stack_pointer; + ++timer_irq_count; + now = SysTimer_GetMtimeValue(); + SysTimer_SetMtimecmpValue(now + RS_TIMER_DELTA_VALUE); +} + +static void rs_software_irq_handler(uintptr_t mcause, uintptr_t stack_pointer) { + (void)mcause; + (void)stack_pointer; + SysTimer_ClearSoftwareIRQ(); + ++software_irq_count; + software_irq_ready = 1U; +} + +static rs_status_t rs_irq_wait_for_count(volatile uint32_t *counter, uint32_t target) { + for (uint32_t elapsed = 0U; elapsed < RS_IRQ_TEST_TIMEOUT_MS; ++elapsed) { + if (*counter >= target) { + return RS_OK; + } + delay_ms(1U); + } + return RS_ETIMEOUT; +} + +void irq_test(int argc, char **argv) { + uint64_t now; + + (void)argc; + (void)argv; + timer_irq_count = 0U; + software_irq_count = 0U; + software_irq_ready = 1U; + + if (rs_irq_enable_core(IRQ_M_TIMER, rs_timer_irq_handler) != RS_OK) { + printf("unable to register timer irq\n"); + return; + } + __enable_irq(); + now = SysTimer_GetMtimeValue(); + SysTimer_SetMtimecmpValue(now + RS_TIMER_DELTA_VALUE); + + if (rs_irq_wait_for_count(&timer_irq_count, 6U) != RS_OK) { + printf("timer irq timed out\n"); + __disable_core_irq(IRQ_M_TIMER); + return; + } + __disable_core_irq(IRQ_M_TIMER); + + if (rs_irq_enable_core(IRQ_M_SOFT, rs_software_irq_handler) != RS_OK) { + printf("unable to register software irq\n"); + return; + } + for (uint32_t attempt = 0U; attempt < 6U; ++attempt) { + if (software_irq_ready == 0U) { + printf("software irq did not clear\n"); + return; + } + software_irq_ready = 0U; + SysTimer_SetSoftwareIRQ(); + if (rs_irq_wait_for_count(&software_irq_count, attempt + 1U) != RS_OK) { + printf("software irq timed out\n"); + return; + } + } + __disable_core_irq(IRQ_M_SOFT); + printf("timer and software irq tests passed\n"); +} diff --git a/crt/src/core/system_irq_handler.c b/crt/src/core/system_irq_handler.c new file mode 100644 index 00000000..33058909 --- /dev/null +++ b/crt/src/core/system_irq_handler.c @@ -0,0 +1,102 @@ +#include + +#include +#include +#include +#include + +#define RS_EXCEPTION_COUNT 16U +#define RS_CORE_IRQ_COUNT 12U +#define RS_EXTERNAL_IRQ_COUNT 30U + +static rs_trap_handler_t exception_handlers[RS_EXCEPTION_COUNT]; +static rs_trap_handler_t core_irq_handlers[RS_CORE_IRQ_COUNT]; + +static void rs_default_exception(uintptr_t mcause, uintptr_t stack_pointer) { + printf("trap exception mcause=0x%lx sp=0x%lx\n", (unsigned long)mcause, + (unsigned long)stack_pointer); + for (;;) { + } +} + +static void rs_default_interrupt(uintptr_t mcause, uintptr_t stack_pointer) { + printf("trap interrupt mcause=0x%lx sp=0x%lx\n", (unsigned long)mcause, + (unsigned long)stack_pointer); +} + +static void rs_irq_init_tables(void) { + for (uint32_t index = 0U; index < RS_EXCEPTION_COUNT; ++index) { + exception_handlers[index] = rs_default_exception; + } + for (uint32_t index = 0U; index < RS_CORE_IRQ_COUNT; ++index) { + core_irq_handlers[index] = rs_default_interrupt; + } +} + +rs_status_t rs_irq_register_exception(uint32_t id, rs_trap_handler_t handler) { + if ((id >= RS_EXCEPTION_COUNT) || (handler == NULL)) { + return RS_EINVAL; + } + exception_handlers[id] = handler; + return RS_OK; +} + +rs_status_t rs_irq_register_core(uint32_t id, rs_trap_handler_t handler) { + if ((id >= RS_CORE_IRQ_COUNT) || (handler == NULL)) { + return RS_EINVAL; + } + core_irq_handlers[id] = handler; + return RS_OK; +} + +rs_status_t rs_irq_register_external(uint32_t id, rs_trap_handler_t handler) { + if ((id >= RS_EXTERNAL_IRQ_COUNT) || (handler == NULL)) { + return RS_EINVAL; + } + + /* No PLIC claim/complete path is present in this SoC configuration. */ + return RS_ENOTSUP; +} + +rs_status_t rs_irq_enable_core(uint32_t id, rs_trap_handler_t handler) { + const rs_status_t status = rs_irq_register_core(id, handler); + + if (status != RS_OK) { + return status; + } + switch (id) { + case IRQ_M_SOFT: + __enable_sw_irq(); + break; + case IRQ_M_TIMER: + __enable_timer_irq(); + break; + default: + return RS_ENOTSUP; + } + return RS_OK; +} + +uint32_t system_trap_handler(uintptr_t mcause, uintptr_t stack_pointer) { + const uint32_t id = (uint32_t)(mcause & 0x00000fffU); + + if ((mcause & (uintptr_t)MCAUSE_INTERRUPT) != 0U) { + if (id == IRQ_M_EXT) { + rs_default_interrupt(mcause, stack_pointer); + } else if (id < RS_CORE_IRQ_COUNT) { + core_irq_handlers[id](mcause, stack_pointer); + } else { + rs_default_interrupt(mcause, stack_pointer); + } + } else if (id < RS_EXCEPTION_COUNT) { + exception_handlers[id](mcause, stack_pointer); + } else { + rs_default_exception(mcause, stack_pointer); + } + return 0U; +} + +void _premain_init(void) { + rs_irq_init_tables(); + __enable_all_counter(); +} diff --git a/crt/src/hal/advanced_timer.c b/crt/src/hal/advanced_timer.c new file mode 100644 index 00000000..c3775353 --- /dev/null +++ b/crt/src/hal/advanced_timer.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#define RS_ADVTIMER_LONG_TIMEOUT (RS_TIMEOUT_DEFAULT * 100U) + +static rs_status_t rs_advtimer_init(uint32_t div, uint32_t cmp) { + if ((div == 0U) || (cmp == 0U)) { + return RS_EINVAL; + } + reg_tim3_ctrl = (uint32_t)0x0; + if (rs_wait_value(®_tim3_stat, 0U, RS_TIMEOUT_DEFAULT) != RS_OK) { + return RS_ETIMEOUT; + } + reg_tim3_pscr = div - 1; + reg_tim3_cmp = cmp - 1; + printf("CTRL: %d PSCR: %d CMP: %d\n", reg_tim3_ctrl, reg_tim3_pscr, reg_tim3_cmp); + return RS_OK; +} + +static rs_status_t rs_advtimer_delay(uint32_t val, rs_timeout_t timeout) { + reg_tim3_ctrl = (uint32_t)0xD; + for (uint32_t i = 0U; i < val; ++i) { + if (rs_wait_value(®_tim3_stat, 1U, timeout) != RS_OK) { + reg_tim3_ctrl = (uint32_t)0x0; + return RS_ETIMEOUT; + } + } + reg_tim3_ctrl = (uint32_t)0x0; + return RS_OK; +} + +void ip_advtim_test(void) { + printf("[APB IP] adv timer test\n"); + // 'CPU_FREQ' MHz for 1ms + printf("no div test start\n"); + if (rs_advtimer_init(1U, CPU_FREQ * 1000U) != RS_OK) { + printf("advanced timer initialization timed out\n"); + return; + } + // advtimer_init(1, 100); // for rtl simu + for (uint32_t i = 1U; i <= 10U; ++i) { + if (rs_advtimer_delay(1000U, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("advanced timer delay timed out\n"); + return; + } + printf("delay 1s\n"); + } + printf("no div test done\n"); + printf("div test start\n"); + // 'CPU_FREQ' MHz for 1s + if (rs_advtimer_init(CPU_FREQ, 1000000U) != RS_OK) { + printf("advanced timer initialization timed out\n"); + return; + } + // advtimer_init(100, 10); // for soc + for (uint32_t i = 1U; i <= 10U; ++i) { + if (rs_advtimer_delay(1U, RS_ADVTIMER_LONG_TIMEOUT) != RS_OK) { + printf("advanced timer delay timed out\n"); + return; + } + printf("delay 1s\n"); + } + printf("CTRL: %d PSCR: %d CMP: %d\n", reg_tim3_ctrl, reg_tim3_pscr, reg_tim3_cmp); +} diff --git a/crt/src/hal/crc.c b/crt/src/hal/crc.c new file mode 100644 index 00000000..a15ce783 --- /dev/null +++ b/crt/src/hal/crc.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +void ip_crc_test(int argc, char **argv) { + (void)argc; + (void)argv; + + printf("[APB IP] crc test\n"); + + reg_crc_ctrl = (uint32_t)0; + reg_crc_init = (uint32_t)0xFFFF; + reg_crc_xorv = (uint32_t)0; + reg_crc_ctrl = (uint32_t)0b1001001; + + uint32_t val = 0x123456; + for (uint32_t i = 0U; i < 16U; ++i) { + reg_crc_data = val + i; + if (rs_wait_not_value(®_crc_stat, 0U, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("crc calculation timed out\n"); + return; + } + printf("cnt: %d crc: %x\n", i, reg_crc_data); + } +} diff --git a/crt/src/hal/dma.c b/crt/src/hal/dma.c new file mode 100644 index 00000000..36684369 --- /dev/null +++ b/crt/src/hal/dma.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +rs_status_t rs_dma_config(uint32_t mode, uintptr_t source, uint32_t source_increment, + uintptr_t destination, uint32_t destination_increment, + uint32_t transfer_words) { + if ((source == 0U) || (destination == 0U) || (transfer_words == 0U)) { + return RS_EINVAL; + } + + reg_dma_mode = mode; + reg_dma_srcaddr = (uint32_t)source; + reg_dma_srcincr = source_increment; + reg_dma_dstaddr = (uint32_t)destination; + reg_dma_dstincr = destination_increment; + reg_dma_xferlen = transfer_words; + return RS_OK; +} + +rs_status_t rs_dma_start(void) { + reg_dma_start = 1U; + return RS_OK; +} + +rs_status_t rs_dma_stop(void) { + reg_dma_stop = 1U; + return RS_OK; +} + +rs_status_t rs_dma_reset(void) { + (void)rs_dma_stop(); + reg_dma_reset = 1U; + (void)rs_dma_stop(); + return RS_OK; +} + +rs_status_t rs_dma_wait(rs_timeout_t timeout) { + return rs_wait_mask(®_dma_status, UINT32_MAX, 1U, timeout); +} + +void ip_dma_test(void) { + printf("dma test\n"); + reg_i2s_mode = 1U; + reg_i2s_upbound = 120U; + reg_i2s_lowbound = 32U; + reg_i2s_recven = 0U; + + if ((rs_dma_config(1U, 0x40000000U, 1U, (uintptr_t)®_i2s_txdata, 0U, 512U) != RS_OK) || + (rs_dma_start() != RS_OK) || (rs_dma_wait(RS_TIMEOUT_DEFAULT) != RS_OK)) { + printf("dma transmit failed\n"); + return; + } + + reg_i2s_recven = 1U; + if ((rs_dma_config(2U, (uintptr_t)®_i2s_rxdata, 0U, 0x41000000U, 1U, 180U) != RS_OK) || + (rs_dma_start() != RS_OK) || (rs_dma_wait(RS_TIMEOUT_DEFAULT) != RS_OK)) { + printf("dma receive failed\n"); + reg_i2s_recven = 0U; + return; + } + reg_i2s_recven = 0U; + printf("dma test passed\n"); +} diff --git a/crt/src/rs_gpio.c b/crt/src/hal/gpio.c similarity index 81% rename from crt/src/rs_gpio.c rename to crt/src/hal/gpio.c index d15a749d..eced0edb 100644 --- a/crt/src/rs_gpio.c +++ b/crt/src/hal/gpio.c @@ -1,11 +1,11 @@ -#include -#include -#include -#include +#include +#include +#include +#include void ip_gpio_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("[NATV IP] gpio test\n"); @@ -23,8 +23,10 @@ void ip_gpio_test(int argc, char **argv) { printf("led output test\n"); for (int i = 0; i < 50; ++i) { delay_ms(300); - if (reg_gpio_do == 0b00) reg_gpio_do = (uint32_t)0b01; - else reg_gpio_do = (uint32_t)0b00; + if (reg_gpio_do == 0b00) + reg_gpio_do = (uint32_t)0b01; + else + reg_gpio_do = (uint32_t)0b00; } reg_gpio_do = (uint32_t)0b00; diff --git a/crt/src/rs_hpuart.c b/crt/src/hal/hpuart.c similarity index 72% rename from crt/src/rs_hpuart.c rename to crt/src/hal/hpuart.c index 948d1b47..ef557055 100644 --- a/crt/src/rs_hpuart.c +++ b/crt/src/hal/hpuart.c @@ -1,10 +1,11 @@ -#include -#include -#include +#include +#include +#include +#include void ip_hpuart_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("[IP] uart test\n"); @@ -21,10 +22,11 @@ void ip_hpuart_test(int argc, char **argv) { printf("uart tx test\n"); uint32_t val = (uint32_t)0x41; - for (int i = 0; i < 30; ++i) - { - while (((reg_uart1_lsr & 0x100) >> 8) == 1) - ; + for (uint32_t i = 0U; i < 30U; ++i) { + if (rs_wait_mask(®_uart1_lsr, 0x100U, 0U, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("uart tx fifo timed out\n"); + return; + } reg_uart1_trx = (uint32_t)(val + i); } diff --git a/crt/src/hal/i2c.c b/crt/src/hal/i2c.c new file mode 100644 index 00000000..94032e65 --- /dev/null +++ b/crt/src/hal/i2c.c @@ -0,0 +1,59 @@ +#include + +#include +#include +#include + +static rs_status_t rs_i2c0_validate(uint8_t address_width, uint8_t count, const void *data) { + if ((address_width > RS_I2C_DEVICE_ADDRESS_16BIT) || ((count != 0U) && (data == NULL))) { + return RS_EINVAL; + } + return RS_OK; +} + +rs_status_t rs_i2c0_init(uint8_t clock_divider) { + reg_i2c0_clkdiv = clock_divider; + return RS_OK; +} + +rs_status_t rs_i2c0_write(uint8_t device_address, uint16_t register_address, uint8_t address_width, + uint8_t count, const uint8_t *data, rs_timeout_t timeout) { + rs_status_t status = rs_i2c0_validate(address_width, count, data); + + if (status != RS_OK) { + return status; + } + reg_i2c0_devaddr = device_address; + reg_i2c0_cfg = address_width; + for (uint8_t index = 0U; index < count; ++index) { + reg_i2c0_regaddr = (uint32_t)register_address + index; + reg_i2c0_txdata = data[index]; + reg_i2c0_xfer = RS_I2C_XFER_WRITE; + status = rs_wait_mask(®_i2c0_status, UINT32_MAX, 1U, timeout); + if (status != RS_OK) { + return status; + } + } + return RS_OK; +} + +rs_status_t rs_i2c0_read(uint8_t device_address, uint16_t register_address, uint8_t address_width, + uint8_t count, uint8_t *data, rs_timeout_t timeout) { + rs_status_t status = rs_i2c0_validate(address_width, count, data); + + if (status != RS_OK) { + return status; + } + reg_i2c0_devaddr = device_address; + reg_i2c0_cfg = address_width; + for (uint8_t index = 0U; index < count; ++index) { + reg_i2c0_regaddr = (uint32_t)register_address + index; + reg_i2c0_xfer = RS_I2C_XFER_READ; + status = rs_wait_mask(®_i2c0_status, UINT32_MAX, 1U, timeout); + if (status != RS_OK) { + return status; + } + data[index] = (uint8_t)reg_i2c0_rxdata; + } + return RS_OK; +} diff --git a/crt/src/hal/i2s.c b/crt/src/hal/i2s.c new file mode 100644 index 00000000..e78735de --- /dev/null +++ b/crt/src/hal/i2s.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include + +static const uint32_t audio_addr[] = {0x61004000U, 0x64737000U}; +static const uint32_t audio_len = 2U; +static uint32_t audio_idx; + +static void i2s_init(uint32_t mode) { + reg_i2s_mode = (uint32_t)mode; + reg_i2s_upbound = (uint32_t)120; + // NOTE: larger than 'clk/clk_aud 'size of i2x tx fifo + reg_i2s_lowbound = (uint32_t)80; +} + +static void i2s_audio_load(void) { + rs_wav_info_t info; + const uint32_t start_address = audio_addr[audio_idx]; + const uint32_t available_size = + (start_address >= TF_CARD_START) && (start_address < (TF_CARD_START + TF_CARD_OFFST)) + ? TF_CARD_OFFST - (start_address - TF_CARD_START) + : 0U; + + if ((available_size == 0U) || + (rs_wav_parse_spisd(start_address, available_size, &info) != RS_OK) || + ((info.data_size % sizeof(uint32_t)) != 0U) || + (rs_dma_config(1U, start_address + info.data_offset, 1U, (uintptr_t)®_i2s_txdata, 0U, + info.data_size / sizeof(uint32_t)) != RS_OK)) { + printf("wav file parse/configuration error\n"); + } +} + +static void i2s_audio_panel(void) { + printf("============================================================\n"); + printf(" retroSoC Audio Player \n"); + printf(" system: help[h] exit[e] mode[m] next-audio[n] \n"); + printf("============================================================\n"); + printf(" player: play[s] pause[t] reset[r] vol-up[u] vol-down[d] \n"); + printf("============================================================\n"); +} + +void ip_i2s_test(int argc, char **argv) { + (void)argc; + (void)argv; + + char type_ch; + uint32_t mode = 0, pause = 0, xfering = 0; + + es8388_init(); + printf("[APB IP] i2s test\n"); + // load first data + // i2s_audio_load(); + i2s_audio_panel(); + while (true) { + type_ch = getchar(); + + if (xfering) { + if (reg_dma_status == (uint32_t)1) { + printf("dma tx done\n"); + xfering = (uint32_t)0; + } + } + + if (type_ch == 'e' && !xfering) + break; + else if (type_ch == 'h' && !xfering) + i2s_audio_panel(); + else if (type_ch == 'n' && !xfering) { + if (audio_idx == audio_len - 1) + audio_idx = 0; + else + ++audio_idx; + + i2s_audio_load(); + } else if (type_ch == 'm' && !xfering) { + if (mode) { + mode = (uint32_t)0; + printf("switch to loopback mode\n"); + } else { + mode = (uint32_t)1; + printf("switch to fifo-xfer mode\n"); + } + i2s_init(mode); + } else if (type_ch == 's' && !xfering) { + // force switching to fifo-xfer mode + i2s_init(1); + xfering = (uint32_t)1; + if (rs_dma_start() == RS_OK) { + printf("start xfer\n"); + } else { + xfering = 0U; + } + } else if (type_ch == 't' && xfering) { + if (pause) { + pause = (uint32_t)0; + (void)rs_dma_stop(); + i2s_init(1); + printf("resume audio play\n"); + } else { + pause = (uint32_t)1; + i2s_init(0); + (void)rs_dma_stop(); + printf("fsm: %d\n", reg_dma_fsm); + printf("pause audio play\n"); + } + } else if (type_ch == 'r' && xfering) { + xfering = (uint32_t)0; + i2s_init(0); + (void)rs_dma_reset(); + printf("reset audio play\n"); + } + } + + i2s_init(0); +} diff --git a/crt/src/rs_lcd.c b/crt/src/hal/lcd.c similarity index 58% rename from crt/src/rs_lcd.c rename to crt/src/hal/lcd.c index 4ea5302d..7eb8bc70 100644 --- a/crt/src/rs_lcd.c +++ b/crt/src/hal/lcd.c @@ -1,13 +1,13 @@ -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #ifdef CSR_ENABLE -#include +#include #endif // #include "image.h" // #include "video.h" @@ -26,48 +26,58 @@ // }; static uint32_t rgb_color[][32] = { - { // red - 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, - 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, - 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, - 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, - }, - { // green - 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, - 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, - 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, - 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, - }, - { // blue - 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, - 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, - 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, - 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, - }, + { + // red + 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, + 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, + 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, + 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, + 0xF800F800, 0xF800F800, 0xF800F800, 0xF800F800, + }, + { + // green + 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, + 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, + 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, + 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, + 0x07E007E0, 0x07E007E0, 0x07E007E0, 0x07E007E0, + }, + { + // blue + 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, + 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, + 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, + 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, + 0x001F001F, 0x001F001F, 0x001F001F, 0x001F001F, + }, }; -void lcd_wr_dc_cmd(uint8_t cmd) { +static bool rs_lcd_region_valid(uint16_t x_start, uint16_t y_start, uint16_t x_end, + uint16_t y_end) { + return (x_end > x_start) && (y_end > y_start) && (x_end <= LCD_W) && (y_end <= LCD_H); +} + +static void lcd_wr_dc_cmd(uint8_t cmd) { lcd_dc_clr; qspi0_wr_dat8(cmd); } -void lcd_wr_dc_data8(uint8_t dat) { +static void lcd_wr_dc_data8(uint8_t dat) { lcd_dc_set; qspi0_wr_dat8(dat); } -void lcd_wr_dc_data16(uint16_t dat) { +static void lcd_wr_dc_data16(uint16_t dat) { lcd_dc_set; qspi0_wr_dat16(dat); } -void lcd_wr_data32(uint32_t* dat, uint32_t len) { +static void lcd_wr_data32(uint32_t *dat, uint32_t len) { lcd_dc_set; qspi0_wr_data32(dat, len); } - -void lcd_init() { +void lcd_init(void) { delay_ms(500); lcd_wr_dc_cmd(0x11); delay_ms(120); @@ -154,6 +164,9 @@ void lcd_init() { } void lcd_addr_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { + if ((x1 > x2) || (y1 > y2) || (x2 >= LCD_W) || (y2 >= LCD_H)) { + return; + } if (USE_HORIZONTAL == 0) { lcd_wr_dc_cmd(0x2A); // set col addr lcd_wr_dc_data16(x1 + 52); @@ -189,95 +202,117 @@ void lcd_addr_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { } } -void lcd_fill_bg(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint32_t idx) { +static void lcd_fill_bg(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint32_t idx) { + if (!rs_lcd_region_valid(xsta, ysta, xend, yend) || + (idx >= (sizeof(rgb_color) / sizeof(rgb_color[0])))) { + return; + } lcd_addr_set(xsta, ysta, xend - 1, yend - 1); - int tot = (xend - xsta) * (yend - ysta); + uint32_t total_pixels = (uint32_t)(xend - xsta) * (uint32_t)(yend - ysta); - for(int i = 0; i < tot; i += 64) { - lcd_wr_data32(rgb_color[idx], 32); + for (uint32_t i = 0U; i < total_pixels; i += 64U) { + const uint32_t pixels = ((total_pixels - i) < 64U) ? (total_pixels - i) : 64U; + lcd_wr_data32(rgb_color[idx], (pixels + 1U) / 2U); } - } void lcd_fill_image(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint32_t *data) { - // printf("xsta: %d ysta: %d xend: %d yend: %d\n", xsta, ysta, xend, yend); + if (!rs_lcd_region_valid(xsta, ysta, xend, yend) || (data == NULL)) { + return; + } lcd_addr_set(xsta, ysta, xend - 1, yend - 1); - int tot = (xend - xsta) * (yend - ysta); - // printf("tot: %d\n", tot); + uint32_t total_pixels = (uint32_t)(xend - xsta) * (uint32_t)(yend - ysta); #ifdef USE_QSPI0_DMA lcd_dc_set; uintptr_t addr = (uintptr_t)data; // printf("addr: %x\n\n", addr); - qspi0_dma_xfer(addr, tot / 2); // perf: every xfer in 32bits(2 pixels for RGB565 format) + qspi0_dma_xfer(addr, total_pixels / 2U); // every xfer contains two RGB565 pixels #else - int i, j; - for (i = 0, j = 0; i + 64 < tot; i += 64, j += 32) { + uint32_t i; + uint32_t j; + for (i = 0U, j = 0U; (i + 64U) < total_pixels; i += 64U, j += 32U) { lcd_wr_data32(data + j, 32); // 32x2 pixels = 64pisel } - if (i < tot) lcd_wr_data32(data + j, (tot - i) / 2); + if (i < total_pixels) + lcd_wr_data32(data + j, (total_pixels - i) / 2U); #endif } void lcd_fill_video(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint32_t *data) { + if (!rs_lcd_region_valid(xsta, ysta, xend, yend) || (data == NULL)) { + return; + } lcd_addr_set(xsta, ysta, xend - 1, yend - 1); - int tot = (xend - xsta) * (yend - ysta); - int i, j; - for (i = 0, j = 0; i + 64 < tot; i += 64, j += 32) { + uint32_t total_pixels = (uint32_t)(xend - xsta) * (uint32_t)(yend - ysta); + uint32_t i; + uint32_t j; + for (i = 0U, j = 0U; (i + 64U) < total_pixels; i += 64U, j += 32U) { lcd_wr_data32(data + j, 32); // 32x2 pixels = 64pisel } - if (i < tot) lcd_wr_data32(data + j, (tot - i) / 2); + if (i < total_pixels) + lcd_wr_data32(data + j, (total_pixels - i) / 2U); } - -void lcd_frame(uint32_t first, uint32_t pref_cnt) { +static void lcd_frame(uint32_t first, uint32_t pref_cnt) { #ifdef CORE_PICORV32 static uint32_t cycle_start, cycle_end; static uint32_t cycleh_start, cycleh_end; static uint32_t inst_start, inst_end; static uint32_t insth_start, insth_end; - if(first) { - __asm__ volatile("rdcycle %0" : "=r"(cycle_start)); - __asm__ volatile("rdcycleh %0" : "=r"(cycleh_start)); - __asm__ volatile("rdinstret %0" : "=r"(inst_start)); + if (first) { + __asm__ volatile("rdcycle %0" : "=r"(cycle_start)); + __asm__ volatile("rdcycleh %0" : "=r"(cycleh_start)); + __asm__ volatile("rdinstret %0" : "=r"(inst_start)); __asm__ volatile("rdinstreth %0" : "=r"(insth_start)); } else { - __asm__ volatile("rdcycle %0" : "=r"(cycle_end)); - __asm__ volatile("rdcycleh %0" : "=r"(cycleh_end)); - __asm__ volatile("rdinstret %0" : "=r"(inst_end)); + __asm__ volatile("rdcycle %0" : "=r"(cycle_end)); + __asm__ volatile("rdcycleh %0" : "=r"(cycleh_end)); + __asm__ volatile("rdinstret %0" : "=r"(inst_end)); __asm__ volatile("rdinstreth %0" : "=r"(insth_end)); printf("cycles num: %d(high: %d)\n", cycle_end - cycle_start, cycleh_end - cycleh_start); printf("insts num: %d(high: %d)\n", inst_end - inst_start, insth_end - insth_start); - printf("flush rate: %dfps\n", pref_cnt / ((cycle_end - cycle_start) / CPU_FREQ / 1000000)); + if (cycle_end > cycle_start) { + const uint32_t elapsed_us = (cycle_end - cycle_start) / CPU_FREQ; + if (elapsed_us != 0U) { + printf("flush rate: %dfps\n", (pref_cnt * 1000000U) / elapsed_us); + } + } } #elif CORE_HAZARD3 static uint64_t cycle_start, cycle_end; static uint64_t inst_start, inst_end; - if(first) { + if (first) { // cycle_start = __get_rv_cycle(); // inst_start = __get_rv_instret(); } else { // cycle_end = __get_rv_cycle(); // inst_end = __get_rv_instret(); - printf("cycles num: %lld\n", cycle_end - cycle_start); - printf("insts num: %lld\n", inst_end - inst_start); - printf("flush rate: %lldfps\n", pref_cnt / ((uint32_t)(cycle_end - cycle_start) / CPU_FREQ / 1000000)); + if (cycle_end > cycle_start) { + const uint64_t elapsed_us = (cycle_end - cycle_start) / CPU_FREQ; + printf("cycles num: %lld\n", cycle_end - cycle_start); + printf("insts num: %lld\n", inst_end - inst_start); + if (elapsed_us != 0U) { + printf("flush rate: %lldfps\n", ((uint64_t)pref_cnt * 1000000U) / elapsed_us); + } + } else { + printf("frame timing is unavailable on this core\n"); + } } #else - (void) first; - (void) pref_cnt; + (void)first; + (void)pref_cnt; #endif } - void ip_lcd_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("lcd test\n"); // // lcd_wr_dc_cmd(0x01); // software reset diff --git a/crt/src/hal/onewire.c b/crt/src/hal/onewire.c new file mode 100644 index 00000000..365543bc --- /dev/null +++ b/crt/src/hal/onewire.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +void ip_1wire_test(int argc, char **argv) { + (void)argc; + (void)argv; + printf("1-wire test\n"); + + reg_onewire_clkdiv = (uint8_t)(CPU_FREQ / 0.8); // 72M 90 + reg_onewire_zerocnt = (uint8_t)(CPU_FREQ / 3); // 72M 24 + reg_onewire_onecnt = (uint8_t)(CPU_FREQ / 1.6); // 72M 45 + reg_onewire_rstcnt = (uint8_t)(CPU_FREQ / 12); // 72M 6 + + for (uint32_t num = 0U; num < 6U; ++num) { + for (uint32_t i = 0U; i < 256U; ++i) { + // clear fifo + reg_onewire_ctrl = (uint8_t)0b01; + // write data(GRB888 format) + reg_onewire_txdata = (uint32_t)i; + reg_onewire_txdata = (uint32_t)(i << 8); + reg_onewire_txdata = (uint32_t)(i << 16); + reg_onewire_txdata = (uint32_t)((i << 8) | (i << 16)); + reg_onewire_ctrl = (uint8_t)0b10; + if (rs_wait_value(®_onewire_status, 5U, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("1-wire transfer timed out\n"); + return; + } + delay_ms(5); + } + } + + reg_onewire_ctrl = (uint8_t)0b01; + reg_onewire_txdata = (uint32_t)0; + reg_onewire_txdata = (uint32_t)0; + reg_onewire_txdata = (uint32_t)0; + reg_onewire_txdata = (uint32_t)0; + reg_onewire_ctrl = (uint8_t)0b10; + printf("1-wire test done\n"); +} diff --git a/crt/src/rs_ps2.c b/crt/src/hal/ps2.c similarity index 61% rename from crt/src/rs_ps2.c rename to crt/src/hal/ps2.c index 38c61d55..caad1ca1 100644 --- a/crt/src/rs_ps2.c +++ b/crt/src/hal/ps2.c @@ -1,22 +1,21 @@ -#include -#include -#include +#include +#include +#include void ip_ps2_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("[APB IP] ps2 test\n"); reg_ps2_ctrl = (uint32_t)0b11; printf("ps2 ctrl: %x\n", reg_ps2_ctrl); uint32_t kdb_code; - while(1) - { + while (1) { kdb_code = reg_ps2_data; - if (kdb_code != 0) - { - if(kdb_code == 0x76) break; + if (kdb_code != 0) { + if (kdb_code == 0x76) + break; printf("[PS2 DAT] %x\n", kdb_code); } } diff --git a/crt/src/rs_psram.c b/crt/src/hal/psram.c similarity index 80% rename from crt/src/rs_psram.c rename to crt/src/hal/psram.c index aed05379..7a6848a2 100644 --- a/crt/src/rs_psram.c +++ b/crt/src/hal/psram.c @@ -1,9 +1,9 @@ -#include -#include -#include +#include +#include +#include -void ip_psram_boot() { +void ip_psram_boot(void) { bool timing_pass = true; printf("[PSRAM] device: ESP-PSRAM64H(max %dMHz)\n", PSRAM_SCLK_MAX_FREQ); @@ -13,7 +13,7 @@ void ip_psram_boot() { printf(" sclk freq: %dMHz\n", PSRAM_SCLK_FREQ); // check uint32_t timing_expt = 0, timing_actual = 0; - char msg_pass[20] = "\e[0;32m[PASS]\e[0m", msg_fail[20] = "\e[0;31m[FAIL]\e[0m"; + char msg_pass[20] = "\e[0;32m[PASS]\e[0m", msg_fail[20] = "\e[0;31m[FAIL]\e[0m"; printf("[PSRAM] wait cycles(default): %d\n", reg_psram_wait); printf("[PSRAM] chd delay cycles(defalut): %d\n", reg_psram_chd); @@ -64,9 +64,9 @@ void ip_psram_boot() { printf(" actul: %dns ", timing_actual); printf("%s\n", (timing_pass &= (timing_actual >= timing_expt)) ? msg_pass : msg_fail); - if(!timing_pass) { + if (!timing_pass) { printf("[PSRAM] timing check fail\n"); - while(1); + return; } uint32_t psram_cfg_val = (uint32_t)8; @@ -82,6 +82,9 @@ void ip_psram_boot() { uint32_t xorshift32(uint32_t *state) { /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */ + if (state == NULL) { + return 0U; + } uint32_t x = *state; x ^= x << 13; x ^= x >> 17; @@ -95,52 +98,59 @@ void ip_psram_selftest(uint32_t addr, uint32_t range) { volatile uint32_t *base_word = (uint32_t *)addr; volatile uint16_t *base_hword = (uint16_t *)addr; volatile uint8_t *base_byte = (uint8_t *)addr; - int test_num = 8192; + uint32_t test_num; + + if ((addr == 0U) || ((addr & (sizeof(uint32_t) - 1U)) != 0U) || (range < sizeof(uint32_t))) { + printf("[PSRAM] self test range is invalid\n"); + return; + } + test_num = range / sizeof(uint32_t); + if (test_num > 8192U) { + test_num = 8192U; + } printf("[range: %dB] 4-bytes wr/rd test\n", 4 * test_num); - for (int i = 0; i < test_num; ++i) { + for (uint32_t i = 0U; i < test_num; ++i) { *(base_word + i) = (uint32_t)(0x12345678 + i); } - for (int i = 0; i < test_num; ++i) { + for (uint32_t i = 0U; i < test_num; ++i) { if (*(base_word + i) != ((uint32_t)(0x12345678 + i))) printf("[error] rd: %x org: %x\n", *(base_word + i), (uint32_t)(0x12345678 + i)); } printf("[range: %dB] 2-bytes wr/rd test\n", 2 * test_num); - for (int i = 0; i < test_num; ++i) { + for (uint32_t i = 0U; i < test_num; ++i) { *(base_hword + i) = (uint16_t)(0x5678 + i); } - for (int i = 0; i < test_num; ++i) { + for (uint32_t i = 0U; i < test_num; ++i) { if (*(base_hword + i) != ((uint16_t)(0x5678 + i))) printf("[error] rd: %x org: %x\n", *(base_hword + i), (uint16_t)(0x5678 + i)); } printf("[range: %dB] 1-bytes wr/rd test\n", test_num); - for (int i = 0; i < test_num; ++i) { + for (uint32_t i = 0U; i < test_num; ++i) { *(base_byte + i) = (uint8_t)(0x78 + i); } - for (int i = 0; i < test_num; ++i) { + for (uint32_t i = 0U; i < test_num; ++i) { if (*(base_byte + i) != ((uint8_t)(0x78 + i))) printf("[error] rd: %x org: %x\n", *(base_byte + i), (uint8_t)(0x78 + i)); } - int cyc_count = 5; - int stride = 256; + const uint32_t cyc_count = 5U; + const uint32_t stride = 256U; uint32_t state; printf("[range: %dMB] stride increments wr/rd test\n", range / 1024 / 1024); - for (int i = 1; i <= cyc_count; i++) { + for (uint32_t i = 1U; i <= cyc_count; ++i) { state = i; - for (uint32_t word = 0; word < range / sizeof(int); word += stride) { + for (uint32_t word = 0U; word < range / sizeof(*base_word); word += stride) { *(base_word + word) = xorshift32(&state); } state = i; - for (uint32_t word = 0; word < range / sizeof(int); word += stride) { + for (uint32_t word = 0U; word < range / sizeof(*base_word); word += stride) { if (*(base_word + word) != xorshift32(&state)) { printf("***FAILED BYTE*** at %x\n", 4 * word); - while (1) - ; return; } } diff --git a/crt/src/rs_pwm.c b/crt/src/hal/pwm.c similarity index 67% rename from crt/src/rs_pwm.c rename to crt/src/hal/pwm.c index fddf792e..b8a32e4d 100644 --- a/crt/src/rs_pwm.c +++ b/crt/src/hal/pwm.c @@ -1,22 +1,21 @@ -#include -#include -#include -#include +#include +#include +#include +#include void ip_pwm_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("[APB IP] pwm test\n"); reg_pwm_ctrl = (uint32_t)0; reg_pwm_pscr = (uint32_t)(CPU_FREQ - 1); // 'CPU_FREQ' MHz for 1MHz reg_pwm_cmp = (uint32_t)(1000 - 1); // 1KHz - printf("reg_pwm_ctrl: %d reg_pwm_pscr: %d reg_pwm_cmp: %d\n", reg_pwm_ctrl, reg_pwm_pscr, reg_pwm_cmp); - for (int i = 0; i < 6; i++) - { - for (int j = 10; j <= 990; ++j) - { + printf("reg_pwm_ctrl: %d reg_pwm_pscr: %d reg_pwm_cmp: %d\n", reg_pwm_ctrl, reg_pwm_pscr, + reg_pwm_cmp); + for (int i = 0; i < 6; i++) { + for (int j = 10; j <= 990; ++j) { reg_pwm_ctrl = (uint32_t)4; reg_pwm_cr0 = j; reg_pwm_ctrl = (uint32_t)3; @@ -24,8 +23,7 @@ void ip_pwm_test(int argc, char **argv) { delay_ms(1); } - for (int j = 990; j >= 10; --j) - { + for (int j = 990; j >= 10; --j) { reg_pwm_ctrl = (uint32_t)4; reg_pwm_cr0 = j; reg_pwm_ctrl = (uint32_t)3; diff --git a/crt/src/rs_qspi.c b/crt/src/hal/qspi.c similarity index 57% rename from crt/src/rs_qspi.c rename to crt/src/hal/qspi.c index 3fda04d5..9c8f170a 100644 --- a/crt/src/rs_qspi.c +++ b/crt/src/hal/qspi.c @@ -1,27 +1,35 @@ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +static bool rs_qspi_wait(uint32_t mask, uint32_t expected) { + const rs_status_t status = rs_wait_mask(®_xpi_status, mask, expected, RS_TIMEOUT_DEFAULT); -void qspi0_init(QSPI0_InitStruct_t val) { - reg_gpio_oe = (uint32_t)0b100; - reg_xpi_mode = val.mode; - reg_xpi_nss = val.nss; - reg_xpi_clkdiv = val.clkdiv; - reg_xpi_txupb = val.txub; - reg_xpi_txlowb = val.txlb; - reg_xpi_rxupb = val.rxub; - reg_xpi_rxlowb = val.rxlb; - reg_xpi_hlvlen = val.hlven; + if (status != RS_OK) { + printf("qspi transfer timed out\n"); + return false; + } + return true; } -void qspi0_wr(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, - uint32_t adrtyp, uint32_t adrlen, uint32_t adrdat, - uint32_t dumlen, - uint32_t dattyp, uint32_t datlen, uint32_t datbit, - uint32_t* dat_list) { +void qspi0_init(QSPI0_InitStruct_t val) { + reg_gpio_oe = (uint32_t)0b100; + reg_xpi_mode = val.mode; + reg_xpi_nss = val.nss; + reg_xpi_clkdiv = val.clkdiv; + reg_xpi_txupb = val.txub; + reg_xpi_txlowb = val.txlb; + reg_xpi_rxupb = val.rxub; + reg_xpi_rxlowb = val.rxlb; + reg_xpi_hlvlen = val.hlven; +} + +void qspi0_wr(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, uint32_t adrtyp, uint32_t adrlen, + uint32_t adrdat, uint32_t dumlen, uint32_t dattyp, uint32_t datlen, uint32_t datbit, + uint32_t *dat_list) { reg_xpi_rdwr = (uint32_t)0; reg_xpi_revdat = (uint32_t)0; @@ -42,22 +50,20 @@ void qspi0_wr(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, reg_xpi_datlen = datlen; reg_xpi_datbit = datbit; - // NOTE: need to guarantee 'len < fifo depth' - for(uint32_t i = 0; i < datlen; ++i) { + if ((datlen != 0U) && (dat_list == NULL)) { + return; + } + for (uint32_t i = 0; i < datlen; ++i) { reg_xpi_txdata = dat_list[i]; } reg_xpi_start = (uint32_t)1; - while((reg_xpi_status & (uint32_t)1) == 0); + (void)rs_qspi_wait(1U, 1U); } -void qspi0_xfer_config( - uint32_t rdwr, uint32_t revdat, uint32_t flush, - uint32_t cmdtyp, uint32_t cmdlen, - uint32_t adrtyp, uint32_t adrlen, - uint32_t dumlen, - uint32_t dattyp, uint32_t datlen, uint32_t datbit -) { +void qspi0_xfer_config(uint32_t rdwr, uint32_t revdat, uint32_t flush, uint32_t cmdtyp, + uint32_t cmdlen, uint32_t adrtyp, uint32_t adrlen, uint32_t dumlen, + uint32_t dattyp, uint32_t datlen, uint32_t datbit) { reg_xpi_rdwr = rdwr; reg_xpi_revdat = revdat; reg_xpi_flush = flush; @@ -76,13 +82,13 @@ void qspi0_xfer_config( reg_xpi_datbit = datbit; } -// NOTE: +// NOTE: void qspi0_wr_cmd8(uint8_t dat) { uint32_t xfer_cmd = dat << 24; reg_xpi_cmdlen = (uint32_t)1; reg_xpi_cmddat = xfer_cmd; reg_xpi_start = (uint32_t)1; - while((reg_xpi_status & (uint32_t)1) == 0); + (void)rs_qspi_wait(1U, 1U); } void qspi0_wr_cmd16(uint16_t dat) { @@ -90,7 +96,7 @@ void qspi0_wr_cmd16(uint16_t dat) { reg_xpi_cmdlen = (uint32_t)2; reg_xpi_cmddat = xfer_cmd; reg_xpi_start = (uint32_t)1; - while((reg_xpi_status & (uint32_t)1) == 0); + (void)rs_qspi_wait(1U, 1U); } void qspi0_wr_dat8(uint8_t dat) { @@ -98,7 +104,7 @@ void qspi0_wr_dat8(uint8_t dat) { reg_xpi_datbit = (uint32_t)1; reg_xpi_txdata = xfer_dat; reg_xpi_start = (uint32_t)1; - while((reg_xpi_status & (uint32_t)1) == 0); + (void)rs_qspi_wait(1U, 1U); } void qspi0_wr_dat16(uint16_t dat) { @@ -106,32 +112,35 @@ void qspi0_wr_dat16(uint16_t dat) { reg_xpi_datbit = (uint32_t)2; reg_xpi_txdata = xfer_dat; reg_xpi_start = (uint32_t)1; - while((reg_xpi_status & (uint32_t)1) == 0); + (void)rs_qspi_wait(1U, 1U); } -void qspi0_wr_data32(uint32_t* dat, uint32_t len) { +void qspi0_wr_data32(uint32_t *dat, uint32_t len) { reg_xpi_flush = (uint32_t)1; reg_xpi_mode = (uint32_t)0; reg_xpi_revdat = (uint32_t)1; reg_xpi_datlen = len; reg_xpi_datbit = (uint32_t)4; - for (uint32_t i = 0; i < len; ++i) { - reg_xpi_txdata = dat[i]; - // printf("data[%d]: %x\n", i, dat[i]); - } + if ((dat == NULL) && (len != 0U)) { + return; + } + for (uint32_t i = 0; i < len; ++i) { + reg_xpi_txdata = dat[i]; + // printf("data[%d]: %x\n", i, dat[i]); + } reg_xpi_start = (uint32_t)1; - while((reg_xpi_status & (uint32_t)1) == 0); + if (!rs_qspi_wait(1U, 1U)) { + return; + } reg_xpi_flush = (uint32_t)1; reg_xpi_revdat = (uint32_t)0; reg_xpi_datlen = (uint32_t)1; } -void qspi0_rd(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, - uint32_t adrtyp, uint32_t adrlen, uint32_t adrdat, - uint32_t dumlen, - uint32_t dattyp, uint32_t datlen, uint32_t datbit, - uint32_t* dat_list) { +void qspi0_rd(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, uint32_t adrtyp, uint32_t adrlen, + uint32_t adrdat, uint32_t dumlen, uint32_t dattyp, uint32_t datlen, uint32_t datbit, + uint32_t *dat_list) { reg_xpi_rdwr = (uint32_t)1; reg_xpi_revdat = (uint32_t)0; @@ -152,15 +161,22 @@ void qspi0_rd(uint32_t cmdtyp, uint32_t cmdlen, uint32_t cmddat, reg_xpi_datlen = datlen; reg_xpi_datbit = datbit; + if ((dat_list == NULL) && (datlen != 0U)) { + return; + } reg_xpi_start = (uint32_t)1; - for(uint32_t i = 0; i < datlen; ++i) { - while((reg_xpi_status & (uint32_t)(1 << 4))); + for (uint32_t i = 0; i < datlen; ++i) { + if (!rs_qspi_wait(1U << 4U, 0U)) { + return; + } dat_list[i] = reg_xpi_rxdata; } } - void qspi0_dma_xfer(uint32_t addr, uint32_t len) { + if ((addr == 0U) || (len == 0U)) { + return; + } reg_xpi_flush = (uint32_t)1; reg_xpi_datlen = (uint32_t)32; reg_xpi_mode = (uint32_t)1; @@ -171,18 +187,22 @@ void qspi0_dma_xfer(uint32_t addr, uint32_t len) { // for(int i = 0; i < 32; ++i) { // printf("data[%d]: %x\n", i, ptr[i]); // } - dma_config((uint32_t)3, addr, (uint32_t)1, (uint32_t)®_xpi_txdata, (uint32_t)0, len); - dma_start_xfer(); - // NOTE: must guarantee dma xfer done flag is clr after tx fifo empty check! - while((reg_xpi_status & (uint32_t)(1 << 2)) == 0); - dma_wait_done(); + if ((rs_dma_config(3U, addr, 1U, (uintptr_t)®_xpi_txdata, 0U, len) != RS_OK) || + (rs_dma_start() != RS_OK) || !rs_qspi_wait(1U << 2U, 1U) || + (rs_dma_wait(RS_TIMEOUT_DEFAULT) != RS_OK)) { + reg_xpi_mode = 0U; + reg_xpi_flush = 1U; + reg_xpi_revdat = 0U; + reg_xpi_datlen = 1U; + return; + } reg_xpi_mode = (uint32_t)0; reg_xpi_flush = (uint32_t)1; reg_xpi_revdat = (uint32_t)0; reg_xpi_datlen = (uint32_t)1; } -void qspi_dev_init() { +void qspi_dev_init(void) { QSPI0_InitStruct_t qspi0 = { (uint32_t)0, (uint32_t)0b0001, // fpga @@ -197,9 +217,6 @@ void qspi_dev_init() { qspi0_init(qspi0); // 1-1-1(tx data only) qspi0_xfer_config((uint32_t)0, (uint32_t)0, (uint32_t)1, // flush bit - (uint32_t)0, (uint32_t)0, - (uint32_t)0, (uint32_t)0, - (uint32_t)0, - (uint32_t)1, (uint32_t)1, (uint32_t)1 - ); + (uint32_t)0, (uint32_t)0, (uint32_t)0, (uint32_t)0, (uint32_t)0, (uint32_t)1, + (uint32_t)1, (uint32_t)1); } diff --git a/crt/src/rs_rng.c b/crt/src/hal/rng.c similarity index 80% rename from crt/src/rs_rng.c rename to crt/src/hal/rng.c index 340c41f0..36371177 100644 --- a/crt/src/rs_rng.c +++ b/crt/src/hal/rng.c @@ -1,10 +1,10 @@ -#include -#include -#include +#include +#include +#include void ip_rng_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("[APB IP] rng test\n"); diff --git a/crt/src/rs_rtc.c b/crt/src/hal/rtc.c similarity index 68% rename from crt/src/rs_rtc.c rename to crt/src/hal/rtc.c index 1bae3806..b403fdba 100644 --- a/crt/src/rs_rtc.c +++ b/crt/src/hal/rtc.c @@ -1,13 +1,16 @@ -#include -#include -#include +#include +#include +#include +#include + +#define RS_RTC_WAIT_TIMEOUT (RS_TIMEOUT_DEFAULT * 16U) // 12.288M/256=48K // apb4 clk: 'CPU_FREQ' MHz // rtc_clk: 12.288 MHz void ip_rtc_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("rtc test\n"); @@ -15,26 +18,30 @@ void ip_rtc_test(int argc, char **argv) { reg_rtc_pscr = (uint32_t)(1000000 - 1); // div1000000 for 'CPU_FREQ' Hz printf("CTRL: %d PSCR: %d\n", reg_rtc_ctrl, reg_rtc_pscr); - for(int i = 0; i < 6; ++i) { + for (uint32_t i = 0U; i < 6U; ++i) { reg_rtc_cnt = (uint32_t)(123 * i); reg_rtc_alrm = reg_rtc_cnt + 10; printf("[static]CNT: %d ALRM: %d\n", reg_rtc_cnt, reg_rtc_alrm); - if(reg_rtc_cnt != (uint32_t)(123 * i)) printf("error\n"); + if (reg_rtc_cnt != (uint32_t)(123 * i)) + printf("error\n"); } - reg_rtc_cnt = (uint32_t)0; - reg_rtc_ctrl = (uint32_t)0b0010010; // core and inc trg en + reg_rtc_cnt = (uint32_t)0; + reg_rtc_ctrl = (uint32_t)0b0010010; // core and inc trg en printf("CTRL: %d PSCR: %d\n", reg_rtc_ctrl, reg_rtc_pscr); printf("cnt inc test\n"); - for(int i = 0; i < 6; ++i) { - while(reg_rtc_ista != (uint32_t)1); // wait inc irq flag + for (uint32_t i = 0U; i < 6U; ++i) { + if (rs_wait_value(®_rtc_ista, 1U, RS_RTC_WAIT_TIMEOUT) != RS_OK) { + printf("rtc increment timed out\n"); + return; + } printf("reg_rtc_cnt: %d\n", reg_rtc_cnt); // inc 1 in 1/'CPU_FREQ' s } printf("cnt inc test done\n"); printf("alrm trigger test\n"); reg_rtc_ctrl = (uint32_t)1; // enter config mode - reg_rtc_cnt = (uint32_t)0; + reg_rtc_cnt = (uint32_t)0; reg_rtc_alrm = reg_rtc_cnt + 6; // for(int i = 0; i < 6; ++i) { // reg_rtc_ctrl = (uint32_t)0b0010100; // core and alrm trg en @@ -47,5 +54,4 @@ void ip_rtc_test(int argc, char **argv) { printf("CTRL: %d PSCR: %d\n", reg_rtc_ctrl, reg_rtc_pscr); printf("alrm trigger test done\n"); printf("rtc test done\n"); - } diff --git a/crt/src/hal/spisd.c b/crt/src/hal/spisd.c new file mode 100644 index 00000000..e1762eeb --- /dev/null +++ b/crt/src/hal/spisd.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + +static rs_status_t rs_spisd_sector_address(uint32_t sector, uintptr_t *address) { + if ((address == NULL) || (sector > ((UINT32_MAX - TF_CARD_START) / RS_SPISD_SECTOR_SIZE))) { + return RS_EINVAL; + } + *address = (uintptr_t)TF_CARD_START + ((uintptr_t)sector * RS_SPISD_SECTOR_SIZE); + return RS_OK; +} + +rs_status_t rs_spisd_read_bytes(void *buffer, size_t byte_count, uintptr_t address) { + volatile const uint8_t *source = (volatile const uint8_t *)address; + uint8_t *destination = (uint8_t *)buffer; + + if ((buffer == NULL) || (address == 0U)) { + return RS_EINVAL; + } + for (size_t index = 0U; index < byte_count; ++index) { + destination[index] = source[index]; + } + return RS_OK; +} + +rs_status_t rs_spisd_sector_read(uint8_t *buffer, uint32_t sector, uint32_t count) { + uintptr_t address; + size_t byte_count; + rs_status_t status; + + if ((buffer == NULL) || (count == 0U) || (count > (SIZE_MAX / RS_SPISD_SECTOR_SIZE))) { + return RS_EINVAL; + } + status = rs_spisd_sector_address(sector, &address); + if (status != RS_OK) { + return status; + } + byte_count = (size_t)count * RS_SPISD_SECTOR_SIZE; + return rs_spisd_read_bytes(buffer, byte_count, address); +} + +rs_status_t rs_spisd_sector_write(const uint8_t *buffer, uint32_t sector, uint32_t count) { + volatile uint8_t *destination; + uintptr_t address; + size_t byte_count; + rs_status_t status; + + if ((buffer == NULL) || (count == 0U) || (count > (SIZE_MAX / RS_SPISD_SECTOR_SIZE))) { + return RS_EINVAL; + } + status = rs_spisd_sector_address(sector, &address); + if (status != RS_OK) { + return status; + } + destination = (volatile uint8_t *)address; + byte_count = (size_t)count * RS_SPISD_SECTOR_SIZE; + for (size_t index = 0U; index < byte_count; ++index) { + destination[index] = buffer[index]; + } + return RS_OK; +} + +rs_status_t rs_spisd_sector_sync(rs_timeout_t timeout) { + reg_spisd_sync = 1U; + return rs_wait_mask(®_spisd_status, UINT32_MAX, 0U, timeout); +} + +void ip_spisd_test(void) { + printf("spisd test\n"); + printf("[SPISD] clock divider: %d\n", reg_spisd_clkdiv); + ip_psram_selftest(0x50000000U, 1U * 1024U * 1024U); +} + +void ip_spisd_read(uint32_t address, uint32_t length) { + volatile const uint32_t *source = (volatile const uint32_t *)(uintptr_t)address; + + printf("spisd read test\n"); + for (uint32_t index = 0U; index < length; ++index) { + printf("addr: %x val: %x\n", (unsigned int)(uintptr_t)&source[index], source[index]); + } +} diff --git a/crt/src/rs_tim.c b/crt/src/hal/timer.c similarity index 85% rename from crt/src/rs_tim.c rename to crt/src/hal/timer.c index aedc89ec..30acb463 100644 --- a/crt/src/rs_tim.c +++ b/crt/src/hal/timer.c @@ -1,15 +1,16 @@ -#include -#include -#include +#include +#include +#include void delay_ms(uint32_t val) { reg_tim0_val = (uint32_t)(CPU_FREQ * val * 1000 - 1); reg_tim0_cfg = (uint32_t)0b0011; // irq disable, count down, oneshot mode, timer enable - while (reg_tim0_val); + while (reg_tim0_val) + ; reg_tim0_cfg = (uint32_t)0b0000; } -void tim1_init() { +void tim1_init(void) { reg_tim1_cfg = (uint32_t)0b0000; reg_tim1_rld = (uint32_t)0xFFFFFFFF; reg_tim1_val = (uint32_t)0; @@ -20,13 +21,13 @@ void tim1_init() { // printf("tim1 cfg: %d\n", reg_tim1_cfg); } -uint32_t tim1_get_value() { +uint32_t tim1_get_value(void) { return reg_tim1_val; } void ip_tim_test(int argc, char **argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; printf("[NATV IP] counter timer test\n"); printf("[tim0 reload] %x\n", reg_tim0_rld); diff --git a/crt/src/hal/uart.c b/crt/src/hal/uart.c new file mode 100644 index 00000000..17a52b64 --- /dev/null +++ b/crt/src/hal/uart.c @@ -0,0 +1,14 @@ +#include +#include + +void uart0_init(uint32_t freq, uint32_t bps) { + reg_uart0_clkdiv = (uint32_t)(freq * 1000000 / bps); +} + +void putch(char ch) { + // while (((reg_uart1_lsr & 0x100) >> 8) == 1) + // ; + // reg_uart1_trx = (uint32_t)ch; + + reg_uart0_data = ch; +} diff --git a/crt/src/hal/watchdog.c b/crt/src/hal/watchdog.c new file mode 100644 index 00000000..77bd5a95 --- /dev/null +++ b/crt/src/hal/watchdog.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +#define RS_WDG_WAIT_TIMEOUT (RS_TIMEOUT_DEFAULT * 16U) + +void ip_wdg_test(int argc, char **argv) { + (void)argc; + (void)argv; + + printf("[APB IP] wdg test\n"); + + reg_wdg_key = WDG_MAGIC_NUM; + reg_wdg_ctrl = (uint32_t)0x0; + + // feed wdg in every 50ms + reg_wdg_key = WDG_MAGIC_NUM; + reg_wdg_pscr = (uint32_t)(CPU_FREQ - 1); // div/'CPU_FREQ' for 1MHz + + reg_wdg_key = WDG_MAGIC_NUM; + + reg_wdg_cmp = (uint32_t)(50000 - 1); // overflow in every 50ms + // reg_wdg_cmp = (uint32_t)(500 - 1); // overflow in every 500ns + + if (rs_wait_not_value(®_wdg_stat, 1U, RS_TIMEOUT_DEFAULT) != RS_OK) { + printf("watchdog status did not clear\n"); + return; + } + + reg_wdg_key = WDG_MAGIC_NUM; + reg_wdg_ctrl = (uint32_t)0b101; // core and ov trg en + + reg_wdg_key = WDG_MAGIC_NUM; + reg_wdg_feed = (uint32_t)0x1; + reg_wdg_key = WDG_MAGIC_NUM; + reg_wdg_feed = (uint32_t)0x0; + + for (uint32_t i = 0U; i < 10U; ++i) { + printf("reg_wdg_pscr: %d\n", reg_wdg_pscr); + if (rs_wait_not_value(®_wdg_stat, 0U, RS_WDG_WAIT_TIMEOUT) != RS_OK) { + printf("watchdog test timed out\n"); + return; + } + printf("%d wdg reset trigger\n", i); + } +} diff --git a/crt/src/lib/console.c b/crt/src/lib/console.c new file mode 100644 index 00000000..318c47d6 --- /dev/null +++ b/crt/src/lib/console.c @@ -0,0 +1,24 @@ +#include + +#include +#include + +void putchar(char c) { + if (c == '\n') { + reg_uart0_data = '\r'; + } + reg_uart0_data = c; +} + +char getchar(void) { + return reg_uart0_data; +} + +void print(const char *p) { + if (p == NULL) { + return; + } + while (*p != '\0') { + putchar(*p++); + } +} diff --git a/crt/src/lib/printf.c b/crt/src/lib/printf.c new file mode 100644 index 00000000..990a3b04 --- /dev/null +++ b/crt/src/lib/printf.c @@ -0,0 +1,383 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +typedef enum { + RS_FMT_NONE, + RS_FMT_HH, + RS_FMT_H, + RS_FMT_L, + RS_FMT_LL, + RS_FMT_Z, +} rs_format_length_t; + +typedef void (*rs_format_sink_t)(void *context, char value); + +typedef struct { + char *dst; + size_t dst_size; + size_t count; + rs_format_sink_t sink; + void *context; +} rs_format_output_t; + +static void rs_format_putc(rs_format_output_t *output, char value) { + if (output->sink != NULL) { + output->sink(output->context, value); + } else if ((output->dst != NULL) && (output->dst_size > 0U) && + (output->count < (output->dst_size - 1U))) { + output->dst[output->count] = value; + } + ++output->count; +} + +static void rs_format_repeat(rs_format_output_t *output, char value, size_t count) { + while (count-- != 0U) { + rs_format_putc(output, value); + } +} + +static size_t rs_format_uint(char *dst, uint64_t value, uint32_t base, bool uppercase) { + static const char lower_digits[] = "0123456789abcdef"; + static const char upper_digits[] = "0123456789ABCDEF"; + const char *digits = uppercase ? upper_digits : lower_digits; + char reversed[32]; + size_t count = 0U; + size_t index; + + do { + reversed[count] = digits[value % base]; + ++count; + value /= base; + } while (value != 0U); + + for (index = 0U; index < count; ++index) { + dst[index] = reversed[count - index - 1U]; + } + return count; +} + +static uint64_t rs_format_unsigned_arg(va_list *args, rs_format_length_t length) { + switch (length) { + case RS_FMT_HH: + return (uint64_t)(unsigned char)va_arg(*args, unsigned int); + case RS_FMT_H: + return (uint64_t)(unsigned short)va_arg(*args, unsigned int); + case RS_FMT_L: + return (uint64_t)va_arg(*args, unsigned long); + case RS_FMT_LL: + return (uint64_t)va_arg(*args, unsigned long long); + case RS_FMT_Z: + return (uint64_t)va_arg(*args, size_t); + case RS_FMT_NONE: + default: + return (uint64_t)va_arg(*args, unsigned int); + } +} + +static int64_t rs_format_signed_arg(va_list *args, rs_format_length_t length) { + switch (length) { + case RS_FMT_HH: + return (int64_t)(signed char)va_arg(*args, int); + case RS_FMT_H: + return (int64_t)(short)va_arg(*args, int); + case RS_FMT_L: + return (int64_t)va_arg(*args, long); + case RS_FMT_LL: + return (int64_t)va_arg(*args, long long); + case RS_FMT_Z: + return (int64_t)va_arg(*args, ptrdiff_t); + case RS_FMT_NONE: + default: + return (int64_t)va_arg(*args, int); + } +} + +static void rs_format_number(rs_format_output_t *output, uint64_t value, bool negative, + uint32_t base, bool uppercase, bool left_align, bool zero_pad, + bool force_sign, bool space_sign, size_t width, size_t precision, + bool has_precision, bool alternate) { + char digits[32]; + char prefix[2] = {'\0', '\0'}; + size_t digit_count = rs_format_uint(digits, value, base, uppercase); + size_t prefix_count = 0U; + size_t sign_count = 0U; + size_t zero_count; + size_t padding; + char sign = '\0'; + + if (has_precision && (precision == 0U) && (value == 0U)) { + digit_count = 0U; + } + if (negative) { + sign = '-'; + sign_count = 1U; + } else if (force_sign) { + sign = '+'; + sign_count = 1U; + } else if (space_sign) { + sign = ' '; + sign_count = 1U; + } + if (alternate && (value != 0U) && (base == 16U)) { + prefix[0] = '0'; + prefix[1] = uppercase ? 'X' : 'x'; + prefix_count = 2U; + } else if (alternate && (value != 0U) && (base == 8U)) { + prefix[0] = '0'; + prefix_count = 1U; + } + + zero_count = (has_precision && (precision > digit_count)) ? precision - digit_count : 0U; + padding = width > (sign_count + prefix_count + zero_count + digit_count) + ? width - sign_count - prefix_count - zero_count - digit_count + : 0U; + + if (!left_align && !(zero_pad && !has_precision)) { + rs_format_repeat(output, ' ', padding); + } + if (sign_count != 0U) { + rs_format_putc(output, sign); + } + if (prefix_count != 0U) { + rs_format_putc(output, prefix[0]); + if (prefix_count == 2U) { + rs_format_putc(output, prefix[1]); + } + } + if (!left_align && zero_pad && !has_precision) { + rs_format_repeat(output, '0', padding); + } + rs_format_repeat(output, '0', zero_count); + for (size_t index = 0U; index < digit_count; ++index) { + rs_format_putc(output, digits[index]); + } + if (left_align) { + rs_format_repeat(output, ' ', padding); + } +} + +static int rs_vformat(rs_format_output_t *output, const char *format, va_list *args) { + if ((output == NULL) || (format == NULL) || (args == NULL)) { + return -1; + } + + while (*format != '\0') { + bool left_align = false; + bool force_sign = false; + bool space_sign = false; + bool zero_pad = false; + bool alternate = false; + bool has_precision = false; + size_t width = 0U; + size_t precision = 0U; + rs_format_length_t length = RS_FMT_NONE; + char conversion; + + if (*format != '%') { + rs_format_putc(output, *format++); + continue; + } + ++format; + + for (;;) { + if (*format == '-') { + left_align = true; + } else if (*format == '+') { + force_sign = true; + } else if (*format == ' ') { + space_sign = true; + } else if (*format == '0') { + zero_pad = true; + } else if (*format == '#') { + alternate = true; + } else { + break; + } + ++format; + } + while ((*format >= '0') && (*format <= '9')) { + width = (width * 10U) + (size_t)(*format - '0'); + ++format; + } + if (*format == '.') { + has_precision = true; + ++format; + while ((*format >= '0') && (*format <= '9')) { + precision = (precision * 10U) + (size_t)(*format - '0'); + ++format; + } + } + if (*format == 'h') { + length = RS_FMT_H; + ++format; + if (*format == 'h') { + length = RS_FMT_HH; + ++format; + } + } else if (*format == 'l') { + length = RS_FMT_L; + ++format; + if (*format == 'l') { + length = RS_FMT_LL; + ++format; + } + } else if (*format == 'z') { + length = RS_FMT_Z; + ++format; + } + + conversion = *format; + if (conversion == '\0') { + break; + } + ++format; + + switch (conversion) { + case 'd': + case 'i': { + const int64_t signed_value = rs_format_signed_arg(args, length); + const bool negative = signed_value < 0; + const uint64_t value = + negative ? (uint64_t)(-(signed_value + 1)) + 1U : (uint64_t)signed_value; + rs_format_number(output, value, negative, 10U, false, left_align, zero_pad, force_sign, + space_sign, width, precision, has_precision, false); + break; + } + case 'u': + rs_format_number(output, rs_format_unsigned_arg(args, length), false, 10U, false, + left_align, zero_pad, false, false, width, precision, has_precision, + false); + break; + case 'x': + case 'X': + rs_format_number(output, rs_format_unsigned_arg(args, length), false, 16U, + conversion == 'X', left_align, zero_pad, false, false, width, + precision, has_precision, alternate); + break; + case 'o': + rs_format_number(output, rs_format_unsigned_arg(args, length), false, 8U, false, + left_align, zero_pad, false, false, width, precision, has_precision, + alternate); + break; + case 'p': + rs_format_number(output, (uintptr_t)va_arg(*args, void *), false, 16U, false, + left_align, true, false, false, width, precision, has_precision, true); + break; + case 'c': { + const char value = (char)va_arg(*args, int); + if (!left_align) { + rs_format_repeat(output, ' ', width > 1U ? width - 1U : 0U); + } + rs_format_putc(output, value); + if (left_align) { + rs_format_repeat(output, ' ', width > 1U ? width - 1U : 0U); + } + break; + } + case 's': { + const char *value = va_arg(*args, const char *); + size_t length_value; + if (value == NULL) { + value = "(null)"; + } + length_value = strlen(value); + if (has_precision && (length_value > precision)) { + length_value = precision; + } + if (!left_align) { + rs_format_repeat(output, ' ', width > length_value ? width - length_value : 0U); + } + for (size_t index = 0U; index < length_value; ++index) { + rs_format_putc(output, value[index]); + } + if (left_align) { + rs_format_repeat(output, ' ', width > length_value ? width - length_value : 0U); + } + break; + } + case '%': + rs_format_putc(output, '%'); + break; + default: + rs_format_putc(output, '%'); + rs_format_putc(output, conversion); + break; + } + } + + return (output->count > (size_t)INT32_MAX) ? -1 : (int)output->count; +} + +static void rs_console_sink(void *context, char value) { + (void)context; + putch(value); +} + +int rs_vsnprintf(char *dst, size_t dst_size, const char *format, va_list args) { + rs_format_output_t output = {dst, dst_size, 0U, NULL, NULL}; + va_list copy; + int result; + + va_copy(copy, args); + result = rs_vformat(&output, format, ©); + va_end(copy); + + if ((dst != NULL) && (dst_size > 0U)) { + const size_t terminator = output.count < (dst_size - 1U) ? output.count : dst_size - 1U; + dst[terminator] = '\0'; + } + return result; +} + +int rs_snprintf(char *dst, size_t dst_size, const char *format, ...) { + int result; + va_list args; + + va_start(args, format); + result = rs_vsnprintf(dst, dst_size, format, args); + va_end(args); + return result; +} + +int rs_printf(const char *format, ...) { + int result; + va_list args; + + rs_format_output_t output = {NULL, 0U, 0U, rs_console_sink, NULL}; + va_start(args, format); + result = rs_vformat(&output, format, &args); + va_end(args); + return result; +} + +int vsnprintf(char *dst, size_t dst_size, const char *format, va_list args) { + return rs_vsnprintf(dst, dst_size, format, args); +} + +int snprintf(char *dst, size_t dst_size, const char *format, ...) { + int result; + va_list args; + + va_start(args, format); + result = rs_vsnprintf(dst, dst_size, format, args); + va_end(args); + return result; +} + +int printf(const char *format, ...) { + int result; + va_list args; + rs_format_output_t output = {NULL, 0U, 0U, rs_console_sink, NULL}; + + va_start(args, format); + result = rs_vformat(&output, format, &args); + va_end(args); + return result; +} diff --git a/crt/src/lib/stdlib.c b/crt/src/lib/stdlib.c new file mode 100644 index 00000000..f0bca77d --- /dev/null +++ b/crt/src/lib/stdlib.c @@ -0,0 +1,96 @@ +#include +#include +#include + +#include + +static uint32_t rs_rand_state = 1U; + +rs_status_t rs_strtoi32(const char *str, int32_t *value) { + uint32_t magnitude = 0U; + bool negative = false; + + if ((str == NULL) || (value == NULL)) { + return RS_EINVAL; + } + + while ((*str == ' ') || (*str == '\t')) { + ++str; + } + if ((*str == '+') || (*str == '-')) { + negative = (*str == '-'); + ++str; + } + if ((*str < '0') || (*str > '9')) { + return RS_EFORMAT; + } + + while ((*str >= '0') && (*str <= '9')) { + const uint32_t digit = (uint32_t)(*str - '0'); + const uint32_t limit = negative ? ((uint32_t)INT32_MAX + 1U) : (uint32_t)INT32_MAX; + if ((magnitude > (limit / 10U)) || + ((magnitude == (limit / 10U)) && (digit > (limit % 10U)))) { + return RS_EFORMAT; + } + magnitude = (magnitude * 10U) + digit; + ++str; + } + + if (*str != '\0') { + return RS_EFORMAT; + } + if (negative) { + *value = (magnitude == ((uint32_t)INT32_MAX + 1U)) ? INT32_MIN : -(int32_t)magnitude; + } else { + *value = (int32_t)magnitude; + } + return RS_OK; +} + +rs_status_t rs_utoa(uint32_t value, char *dst, uint32_t base) { + static const char digits[] = "0123456789ABCDEF"; + char reversed[33]; + uint32_t count = 0U; + uint32_t index; + + if ((dst == NULL) || (base < 2U) || (base > 16U)) { + return RS_EINVAL; + } + + do { + reversed[count] = digits[value % base]; + ++count; + value /= base; + } while (value != 0U); + + for (index = 0U; index < count; ++index) { + dst[index] = reversed[count - index - 1U]; + } + dst[count] = '\0'; + return RS_OK; +} + +int atoi(const char *str) { + int32_t value = 0; + return (rs_strtoi32(str, &value) == RS_OK) ? (int)value : 0; +} + +char *itoa(unsigned int value, char *dst, int base) { + if (rs_utoa((uint32_t)value, dst, (uint32_t)base) != RS_OK) { + return NULL; + } + return dst; +} + +int abs(int value) { + return (value == INT_MIN) ? INT_MAX : ((value < 0) ? -value : value); +} + +int rand(void) { + rs_rand_state = (rs_rand_state * 1103515245U) + 12345U; + return (int)((rs_rand_state >> 16U) & (uint32_t)RAND_MAX); +} + +void srand(unsigned int seed) { + rs_rand_state = seed; +} diff --git a/crt/src/lib/string.c b/crt/src/lib/string.c new file mode 100644 index 00000000..496a2c90 --- /dev/null +++ b/crt/src/lib/string.c @@ -0,0 +1,264 @@ +#include + +size_t strlen(const char *str) { + const char *cursor = str; + + if (str == NULL) { + return 0U; + } + + while (*cursor != '\0') { + ++cursor; + } + return (size_t)(cursor - str); +} + +char *strcpy(char *dst, const char *src) { + char *cursor = dst; + + if ((dst == NULL) || (src == NULL)) { + return dst; + } + + do { + *cursor = *src; + ++cursor; + ++src; + } while (*(cursor - 1) != '\0'); + return dst; +} + +char *strncpy(char *dst, const char *src, size_t count) { + size_t index; + + if ((dst == NULL) || (src == NULL)) { + return dst; + } + + for (index = 0U; index < count; ++index) { + dst[index] = src[index]; + if (src[index] == '\0') { + ++index; + break; + } + } + while (index < count) { + dst[index] = '\0'; + ++index; + } + return dst; +} + +char *strcat(char *dst, const char *src) { + if ((dst == NULL) || (src == NULL)) { + return dst; + } + return strcpy(dst + strlen(dst), src); +} + +int strcmp(const char *lhs, const char *rhs) { + unsigned char left; + unsigned char right; + + if (lhs == rhs) { + return 0; + } + if (lhs == NULL) { + return -1; + } + if (rhs == NULL) { + return 1; + } + + do { + left = (unsigned char)*lhs++; + right = (unsigned char)*rhs++; + } while ((left != '\0') && (left == right)); + return (int)left - (int)right; +} + +int strncmp(const char *lhs, const char *rhs, size_t count) { + size_t index; + + if ((count == 0U) || (lhs == rhs)) { + return 0; + } + if (lhs == NULL) { + return -1; + } + if (rhs == NULL) { + return 1; + } + + for (index = 0U; index < count; ++index) { + const unsigned char left = (unsigned char)lhs[index]; + const unsigned char right = (unsigned char)rhs[index]; + if (left != right) { + return (int)left - (int)right; + } + if (left == '\0') { + return 0; + } + } + return 0; +} + +void *memset(void *dst, int value, size_t count) { + unsigned char *cursor = (unsigned char *)dst; + size_t index; + + if (dst == NULL) { + return NULL; + } + for (index = 0U; index < count; ++index) { + cursor[index] = (unsigned char)value; + } + return dst; +} + +void *memmove(void *dst, const void *src, size_t count) { + unsigned char *output = (unsigned char *)dst; + const unsigned char *input = (const unsigned char *)src; + + if ((dst == NULL) || (src == NULL) || (dst == src) || (count == 0U)) { + return dst; + } + + if ((output > input) && (output < (input + count))) { + while (count-- != 0U) { + output[count] = input[count]; + } + } else { + size_t index; + for (index = 0U; index < count; ++index) { + output[index] = input[index]; + } + } + return dst; +} + +void *memcpy(void *dst, const void *src, size_t count) { + return memmove(dst, src, count); +} + +int memcmp(const void *lhs, const void *rhs, size_t count) { + const unsigned char *left = (const unsigned char *)lhs; + const unsigned char *right = (const unsigned char *)rhs; + size_t index; + + if ((count == 0U) || (lhs == rhs)) { + return 0; + } + if (lhs == NULL) { + return -1; + } + if (rhs == NULL) { + return 1; + } + + for (index = 0U; index < count; ++index) { + if (left[index] != right[index]) { + return (int)left[index] - (int)right[index]; + } + } + return 0; +} + +char *strchr(const char *str, int value) { + const char target = (char)value; + + if (str == NULL) { + return NULL; + } + do { + if (*str == target) { + return (char *)str; + } + } while (*str++ != '\0'); + return NULL; +} + +size_t rs_strlcpy(char *dst, const char *src, size_t dst_size) { + const size_t src_size = strlen(src); + size_t copied = 0U; + + if ((dst == NULL) || (src == NULL) || (dst_size == 0U)) { + return src_size; + } + + while ((copied + 1U < dst_size) && (src[copied] != '\0')) { + dst[copied] = src[copied]; + ++copied; + } + dst[copied] = '\0'; + return src_size; +} + +size_t rs_strlcat(char *dst, const char *src, size_t dst_size) { + const size_t dst_length = strlen(dst); + const size_t src_length = strlen(src); + + if ((dst == NULL) || (src == NULL) || (dst_size == 0U)) { + return dst_length + src_length; + } + if (dst_length >= dst_size) { + return dst_size + src_length; + } + + (void)rs_strlcpy(dst + dst_length, src, dst_size - dst_length); + return dst_length + src_length; +} + +void rs_trim_whitespace(char *str) { + char *start; + char *end; + + if (str == NULL) { + return; + } + + start = str; + while ((*start == ' ') || (*start == '\t')) { + ++start; + } + if (*start == '\0') { + *str = '\0'; + return; + } + + end = start + strlen(start); + while ((end > start) && + ((end[-1] == ' ') || (end[-1] == '\t') || (end[-1] == '\r') || (end[-1] == '\n'))) { + --end; + } + *end = '\0'; + if (start != str) { + (void)memmove(str, start, (size_t)(end - start) + 1U); + } +} + +void rs_remove_suffix(char *dst, size_t dst_size, const char *src, char separator) { + const char *cursor; + size_t length; + + if ((dst == NULL) || (dst_size == 0U) || (src == NULL)) { + return; + } + + length = strlen(src); + cursor = src + length; + while ((cursor > src) && (cursor[-1] != separator)) { + --cursor; + } + if (cursor == src) { + (void)rs_strlcpy(dst, src, dst_size); + return; + } + + length = (size_t)(cursor - src - 1); + if (length >= dst_size) { + length = dst_size - 1U; + } + (void)memcpy(dst, src, length); + dst[length] = '\0'; +} diff --git a/crt/src/main.c b/crt/src/main.c deleted file mode 100644 index 2c14f1ef..00000000 --- a/crt/src/main.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -// #include -// #include - -// val * 1000 / CPU_FREQ / 1000 / 1000 -uint32_t my_get_millis(void) { - return reg_tim1_val / CPU_FREQ / 1000; -} - -void main() { - uart0_init(CPU_FREQ, UART_BPS); -#ifdef SW_BASE - app_info(); - ip_archinfo_test(0, NULL); -#else - tinybooter(); - i2c0_init((uint8_t)(CPU_FREQ / 2 - 1)); - qspi_dev_init(); - lcd_init(); - - // lv_init(); - // tim1_init(); - // lv_tick_set_cb(my_get_millis); - - // lv_port_disp_init(); - - // lv_obj_t *label = lv_label_create(lv_scr_act()); - // lv_label_set_text(label,"Hello maksyuki!!!"); - // lv_obj_center(label); - - // while(1) { - // lv_timer_handler(); - // delay_ms(5); - // printf("hello\n"); - // } - - tinysh_init(); - tinysh_register("app", "app info", (uint8_t)1, app_info); - tinysh_register("arch", "archinfo test", (uint8_t)1, ip_archinfo_test); - tinysh_register("1wire", "1wire test", (uint8_t)1, ip_1wire_test); - tinysh_register("tim", "timer test", (uint8_t)1, ip_tim_test); - tinysh_register("gpio", "gpio test", (uint8_t)1, ip_gpio_test); - tinysh_register("pwm", "pwm test", (uint8_t)1, ip_pwm_test); - tinysh_register("rtc", "rtc test", (uint8_t)1, ip_rtc_test); - tinysh_register("wdg", "wdg test", (uint8_t)1, ip_wdg_test); - tinysh_register("rng", "rng test", (uint8_t)1, ip_rng_test); - tinysh_register("crc", "crc test", (uint8_t)1, ip_crc_test); - tinysh_register("ps2", "ps2 test", (uint8_t)0, ip_ps2_test); - tinysh_register("lcd", "lcd test", (uint8_t)1, ip_lcd_test); - tinysh_register("i2s", "i2s test", (uint8_t)0, ip_i2s_test); - tinysh_register("nor", "nor flash test", (uint8_t)0, ip_norflash_test); - tinysh_register("uart1", "uart1 test", (uint8_t)0, ip_hpuart_test); - tinysh_register("pcf", "pcf8563b test", (uint8_t)1, pcf8563b_test); -#ifdef CSR_ENABLE - tinysh_register("irq", "tmr/sw irq test", (uint8_t)1, irq_test); -#endif - tinysh_register("donut", "dount test", (uint8_t)0, donut_test); - tinysh_batch_run(); - tinysh_launch(); - // video_show(0x60000000); - // ip_norflash_test(); - // ip_lcd_test(0, NULL); - - // ip_spisd_read((uint32_t)0x51004000, (uint32_t)44); - // ip_spisd_test(); - // ip_dma_test(0, NULL); - // tinybench(true, 0); -#endif -} diff --git a/crt/src/rs_1wire.c b/crt/src/rs_1wire.c deleted file mode 100644 index 61fe95b7..00000000 --- a/crt/src/rs_1wire.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include - - -void ip_1wire_test(int argc, char **argv) { - (void) argc; - (void) argv; - printf("1-wire test\n"); - - reg_onewire_clkdiv = (uint8_t)(CPU_FREQ / 0.8); // 72M 90 - reg_onewire_zerocnt = (uint8_t)(CPU_FREQ / 3); // 72M 24 - reg_onewire_onecnt = (uint8_t)(CPU_FREQ / 1.6); // 72M 45 - reg_onewire_rstcnt = (uint8_t)(CPU_FREQ / 12); // 72M 6 - - for(int num = 0; num < 6; ++num) { - for(int i = 0; i < 256; ++i) { - // clear fifo - reg_onewire_ctrl = (uint8_t)0b01; - // write data(GRB888 format) - reg_onewire_txdata = (uint32_t) i; - reg_onewire_txdata = (uint32_t) (i << 8); - reg_onewire_txdata = (uint32_t) (i << 16); - reg_onewire_txdata = (uint32_t) ((i << 8) | (i << 16)); - reg_onewire_ctrl = (uint8_t)0b10; - while(!(reg_onewire_status == (uint32_t)5)); - delay_ms(5); - } - } - - reg_onewire_ctrl = (uint8_t)0b01; - reg_onewire_txdata = (uint32_t) 0; - reg_onewire_txdata = (uint32_t) 0; - reg_onewire_txdata = (uint32_t) 0; - reg_onewire_txdata = (uint32_t) 0; - reg_onewire_ctrl = (uint8_t)0b10; - printf("1-wire test done\n"); -} diff --git a/crt/src/rs_advtim.c b/crt/src/rs_advtim.c deleted file mode 100644 index 07a7636c..00000000 --- a/crt/src/rs_advtim.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include - -void advtimer_init(uint32_t div, uint32_t cmp) { - reg_tim3_ctrl = (uint32_t)0x0; - while(reg_tim3_stat == 1); // clear irq - reg_tim3_pscr = div - 1; - reg_tim3_cmp = cmp - 1; - printf("CTRL: %d PSCR: %d CMP: %d\n", reg_tim3_ctrl, reg_tim3_pscr, reg_tim3_cmp); -} - -void advtimer_delay(uint32_t val) { - reg_tim3_ctrl = (uint32_t)0xD; - for(uint32_t i = 0; i < val; ++i) { - while(reg_tim3_stat == 0); - } - reg_tim3_ctrl = (uint32_t)0x0; -} - -void ip_advtim_test() { - printf("[APB IP] adv timer test\n"); - // 'CPU_FREQ' MHz for 1ms - printf("no div test start\n"); - advtimer_init(1, CPU_FREQ * 1000); - // advtimer_init(1, 100); // for rtl simu - for(int i = 1; i <= 10; ++i) { - advtimer_delay(1000); - printf("delay 1s\n"); - } - printf("no div test done\n"); - printf("div test start\n"); - // 'CPU_FREQ' MHz for 1s - advtimer_init(CPU_FREQ, 1000000); - // advtimer_init(100, 10); // for soc - for(int i = 1; i <= 10; ++i) { - advtimer_delay(1); - printf("delay 1s\n"); - } - printf("CTRL: %d PSCR: %d CMP: %d\n", reg_tim3_ctrl, reg_tim3_pscr, reg_tim3_cmp); -} diff --git a/crt/src/rs_booter.c b/crt/src/rs_booter.c deleted file mode 100644 index 71f6008c..00000000 --- a/crt/src/rs_booter.c +++ /dev/null @@ -1,201 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -// HACK: -#if defined(CORE_MDD) || defined(IP_MDD) -#include <../../rtl/mini/mpw/.build/user_design_info.h> -#endif - - -void app_info() { - printf("#############################################################\n"); - printf("#############################################################\n"); - printf("compile date: %s %s\n", __DATE__, __TIME__); - printf("first bootloader done, app section info:\n"); - printf("_flash_wait_start: 0x%x\n", &_flash_wait_start); - printf("_flash_wait_end: 0x%x\n", &_flash_wait_end); - printf("_ram_lma: 0x%x\n", &_ram_lma); - printf("_ram_vma: 0x%x\n", &_ram_vma); - printf("_ram_start: 0x%x\n", &_ram_start); - printf("stack point: 0x%x\n", &_stack_point); - printf("_stext(entry): 0x%x\n", &_start); - printf("_etext: 0x%x\n", &_etext); - printf("_psram_lma: 0x%x\n", &_psram_lma); - printf("_psram_vma: 0x%x\n", &_psram_vma); - printf("_edata: 0x%x\n", &_edata); - printf("_sbss: 0x%x\n", &_sbss); - printf("_ebss: 0x%x\n", &_ebss); - printf("_heap_start: 0x%x\n\n", &_heap_start); - printf("uart config: 8n1 %dbps\n", UART_BPS); - printf("app booting...\n"); - printf("\n"); - printf(" _ _____ _____ \n"); - printf(" | | / ____| / ____|\n"); - printf(" _ __ ___| |_ _ __ ___| (___ ___ | | \n"); - printf("| '__/ _ \\ __| '__/ _ \\\\___ \\ / _ \\| |\n"); - printf("| | | __/ |_| | | (_) |___) | (_) | |____ \n"); - printf("|_| \\___|\\__|_| \\___/_____/ \\___/ \\_____|\n"); - printf(" retroSoC: A Customized ASIC for Retro Stuff\n"); - printf(" \n"); - printf(" author: Yuchi Miao \n"); - printf(" contributor: MrAMS \n"); - printf(" license: MulanPSL-2.0 license\n\n"); - printf(" series: retroSoC Mini\n"); - printf(" specs: Gen2 Plus\n"); - printf(" version: %s(commit: %s)\n\n", RETROSOC_BRANCH, RETROSOC_COMMIT); - - printf("User Processors:\n"); -#ifndef CORE_MDD - printf(" CORE: %s\n", HW_CORE); -#else - uint32_t core_size = sizeof(user_core_info)/sizeof(user_core_info[0]); - printf(" %-15s %-12s %-12s %s\n", "[name]", "[isa]", "[maintainer]", "[repo]"); - for(uint32_t i = 0; i < core_size; ++i) { - if(reg_sysctrl_coresel == i) printf("=>"); - else printf(" "); - printf("[%d]: %-15s %-12s %-12s %s\n", i, user_core_info[i].name, user_core_info[i].isa, user_core_info[i].maintainer, user_core_info[i].repo); - } -#endif - -#ifdef IP_MDD - printf("\nUser IPs:\n"); - uint32_t ip_size = sizeof(user_ip_info)/sizeof(user_ip_info[0]); - printf(" %-15s %-12s %-12s %s\n", "[name]", "[isa]", "[maintainer]", "[repo]"); - for(uint32_t i = 0; i < ip_size; ++i) { - if(reg_sysctrl_ipsel == i) printf("=>"); - else printf(" "); - printf("[%d]: %-15s %-12s %-12s %s\n", i, user_ip_info[i].name, user_ip_info[i].isa, user_ip_info[i].maintainer, user_ip_info[i].repo); - } -#endif - - - printf("\nSoftware:\n"); - printf(" COMPILER: %s\n", COMPILER_NAME); - printf(" CFLAGS: %s\n", COMPILER_CFLAGS); - printf(" ISA: %s\n", COMPILER_ISA); - printf(" FREQ: %dMHz\n\n", CPU_FREQ); - - printf("Inst/Memory Address Range:\n"); - printf(" QSPI Flash: @[0x%08x-0x%08x] %3d MiB\n", SPFS_MEM_START, SPFS_MEM_START + SPFS_MEM_OFFST - 1, SPFS_MEM_OFFST / 1024 / 1024); - printf(" NMI IP MMIO: @[0x%08x-0x%08x] %3d MiB\n", NMI_MEM_START, NMI_MEM_START + NMI_MEM_OFFST - 1, NMI_MEM_OFFST / 1024 / 1024); - printf(" APB IP MMIO: @[0x%08x-0x%08x] %3d MiB\n", APB_MEM_START, APB_MEM_START + APB_MEM_OFFST - 1, APB_MEM_OFFST / 1024 / 1024); - printf(" On-chip RAM: @[0x%08x-0x%08x] %3d KiB\n", SRAM_MEM_START, SRAM_MEM_START + SRAM_MEM_OFFST - 1, SRAM_MEM_OFFST / 1024); - printf(" Off-chip SDRAM: @[0x%08x-0x%08x] %3d MiB\n", SDRAM_MEM_START, SDRAM_MEM_START + SDRAM_MEM_OFFST - 1, SDRAM_MEM_OFFST / 1024 / 1024); - printf(" Off-chip PSRAM: @[0x%08x-0x%08x] %3d MiB(%dx8MiB)\n", PSRAM_MEM_START, PSRAM_MEM_START + PSRAM_MEM_OFFST - 1, 8 * PSRAM_NUM, PSRAM_NUM); - printf(" Off-chip OPIPSRAM: @[0x%08x-0x%08x] %3d MiB\n", OPIPSRAM_MEM_START, OPIPSRAM_MEM_START + OPIPSRAM_MEM_OFFST - 1, PSRAM_MEM_OFFST / 1024 / 1024); - printf(" XPI MMIO: @[0x%08x-0x%08x] %3d MiB\n", XPI_MEM_START, XPI_MEM_START + XPI_MEM_OFFST - 1, XPI_MEM_OFFST / 1024 / 1024); - printf(" SPISD MMIO: @[0x%08x-0x%08x] %3d GiB\n\n", TF_CARD_START, TF_CARD_START + TF_CARD_OFFST - 1, TF_CARD_OFFST / 1024 / 1024 / 1024); - - printf("Memory Map IO Device:\n"); - printf(" 1 x GPIO(32PIN) @0x%x\n", ®_gpio_oe); - printf(" 1 x UART0 @0x%x\n", ®_uart0_clkdiv); - printf(" 2 x TIMER(0,1) @0x%x,0x%x\n", ®_tim0_cfg, ®_tim1_cfg); - printf(" 1 x PSRAM @0x%x\n", ®_psram_wait); - printf(" 1 x SPISD @0x%x\n", ®_spisd_mode); - printf(" 1 x I2C0 @0x%x\n", ®_i2c0_clkdiv); - printf(" 1 x I2S @0x%x\n", ®_i2s_mode); - printf(" 1 x ONEWIRE @0x%x\n", ®_onewire_clkdiv); - printf(" 1 x XPI @0x%x\n", ®_xpi_cfgidx); - printf(" 1 x DMA @0x%x\n", ®_dma_mode); - printf(" 1 x SYSCTRL @0x%x\n", ®_sysctrl_coresel); - printf(" 1 x CLINT @0x%x\n", ®_clint_mtimel); - printf(" 1 x SDRAM @0x%x\n", ®_sdram_clkdiv); - printf(" 1 x DVP @0x%x\n", ®_dvp_recven); - printf(" 1 x SDIO @0x%x\n", ®_sdio_cfg); - printf(" 1 x OPIPSRAM @0x%x\n", ®_opipsram_cfg); - printf(" 1 x I2C1 @0x%x\n", ®_i2c1_clkdiv); - printf(" 1 x GA* @0x%x\n", ®_ga_cfg); - printf(" 1 x APU* @0x%x\n", ®_apu_cfg); - printf(" 1 x ARCHINFO @0x%x\n", ®_archinfo_sys); - printf(" 1 x RNG @0x%x\n", ®_rng_ctrl); - printf(" 1 x UART1(ADV) @0x%x\n", ®_uart1_lcr); - printf(" 1 x PWM(4CHNL) @0x%x\n", ®_pwm_ctrl); - printf(" 1 x PS2 @0x%x\n", ®_ps2_ctrl); - printf(" 1 x RTC @0x%x\n", ®_rtc_ctrl); - printf(" 1 x WDG @0x%x\n", ®_wdg_ctrl); - printf(" 1 x CRC @0x%x\n", ®_crc_ctrl); - printf(" 1 x TIMER3(ADV) @0x%x\n", ®_tim3_ctrl); - printf(" 1 x USER_IP(4KiB) @0x%x\n\n", ®_user_ip_reg0); - printf("#############################################################\n"); - printf("#############################################################\n"); -} - -uint8_t boot_shell() { - printf("================================\n"); - printf(" Tiny Booter Shell \n"); - printf("================================\n"); - printf("0: flash(defalut) 1: uart 2: tf\n"); - - char type_res[MAX_CMD_LEN], type_ch; - uint8_t type_len; - - while(1) { - printf("tinysh > "); - type_len = 0; - do { - type_ch = getchar(); - if((type_ch >= 'a' && type_ch <= 'z') || (type_ch >= 'A' && type_ch <= 'Z') || - (type_ch >= '0' && type_ch <= '9') || type_ch == ' ' || type_ch == '.' || - type_ch == '/' || type_ch == '_' || type_ch == '"' || type_ch == '/' || - type_ch == '*' || type_ch == '-') { - if(type_len == MAX_CMD_LEN) break; - putchar(type_ch); - type_res[type_len++] = type_ch; - } else if(type_ch == '\b' || type_ch == (char) 127){ - if(type_len == 0) continue; - printf("\b \b"); - type_res[type_len--] = 0; - } else if(type_ch == (char) 9) { // tab - printf("tab\n"); - } - - } while(type_ch != '\n' && type_ch != '\r'); - putchar('\n'); - - type_res[type_len] = 0; - if(strcmp(type_res, "flash") == 0) return 0; - else if(strcmp(type_res, "uart") == 0) return 1; - else if(strcmp(type_res, "tf") == 0) return 2; - else printf("cmd [%s] not found\n", type_res); - } - -} - -uint8_t check_key() { - printf("booter and flash app load done\n"); - printf("whether enter [booter shell] or not...(press key0 to enter)\n\n"); - - uint8_t enter_boot_delay = 6, enter_shell = 0; - for(uint8_t i = 1; i <= enter_boot_delay; ++i) { - printf("delay %ds...[all %ds]\n", i, enter_boot_delay); - delay_ms(1000); - // if(i == 5) enter_shell = 1; // mock the oper - if(enter_shell) { - printf("\n"); - return enter_shell; - } - } - printf("\n"); - return enter_shell; -} - -void tinybooter() { - uint8_t boot_mode = 0; - - if(check_key()) boot_mode = boot_shell(); - else printf("no key0 pressed, default "); - - printf("boot mode is [%s]\n\n", boot_mode == 0 ? "FLASH" : - boot_mode == 1 ? "UART" : - boot_mode == 2 ? "TF" : "NONE"); - - printf("mem self test start...\n"); - ip_psram_boot(); - printf("mem self test done\n"); -} diff --git a/crt/src/rs_crc.c b/crt/src/rs_crc.c deleted file mode 100644 index c060f6aa..00000000 --- a/crt/src/rs_crc.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include - -void ip_crc_test(int argc, char **argv) { - (void) argc; - (void) argv; - - printf("[APB IP] crc test\n"); - - reg_crc_ctrl = (uint32_t)0; - reg_crc_init = (uint32_t)0xFFFF; - reg_crc_xorv = (uint32_t)0; - reg_crc_ctrl = (uint32_t)0b1001001; - - uint32_t val = 0x123456; - for(int i = 0; i < 16; ++i) { - reg_crc_data = val + i; - while(reg_crc_stat == (uint32_t)0); - printf("cnt: %d crc: %x\n", i, reg_crc_data); - } -} diff --git a/crt/src/rs_dma.c b/crt/src/rs_dma.c deleted file mode 100644 index 43a52a7a..00000000 --- a/crt/src/rs_dma.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include - -void dma_config(uint32_t mode, uint32_t src, uint32_t srcincr, uint32_t dst, uint32_t dstincr, uint32_t xferlen) { - // printf("dst: %x\n", dst); - reg_dma_mode = mode; - reg_dma_srcaddr = src; - reg_dma_srcincr = srcincr; - reg_dma_dstaddr = dst; - reg_dma_dstincr = dstincr; - reg_dma_xferlen = xferlen; -} - -void dma_start_xfer() { - reg_dma_start = (uint32_t)1; -} - -void dma_stop_toggle() { - reg_dma_stop = (uint32_t)1; -} - -void dma_reset_xfer() { - dma_stop_toggle(); - reg_dma_reset = (uint32_t)1; - dma_stop_toggle(); - printf("fsm: %d\n", reg_dma_fsm); - printf("dma reset done\n"); - -} - -void dma_wait_done() { - while(reg_dma_status == (uint32_t)0); - // printf("dma tx done\n"); -} - -void ip_dma_test() { - printf("dma test\n"); - // i2s - reg_i2s_mode = (uint32_t)1; - reg_i2s_upbound = (uint32_t)120; - reg_i2s_lowbound = (uint32_t)32; - reg_i2s_recven = (uint32_t)0; - // dma - reg_dma_mode = (uint32_t)1; // i2s tx fifo - // reg_dma_srcaddr = (uint32_t)0x51004000; - reg_dma_srcaddr = (uint32_t)0x40000000; - reg_dma_srcincr = (uint32_t)1; - reg_dma_dstaddr = (uint32_t)(®_i2s_txdata); - reg_dma_dstincr = (uint32_t)0; - reg_dma_xferlen = (uint32_t)512; - reg_dma_start = (uint32_t)1; - while(reg_dma_status == (uint32_t)0); - printf("dma tx done\n"); - - reg_i2s_recven = (uint32_t)1; - reg_dma_mode = (uint32_t)2; // i2s rx fifo - reg_dma_srcaddr = (uint32_t)(®_i2s_rxdata); - reg_dma_srcincr = (uint32_t)0; - reg_dma_dstaddr = (uint32_t)0x41000000; - reg_dma_dstincr = (uint32_t)1; - reg_dma_xferlen = (uint32_t)180; - reg_dma_start = (uint32_t)1; - while(reg_dma_status == (uint32_t)0); - reg_i2s_recven = (uint32_t)0; - printf("dma rx done\n"); - - // volatile uint32_t *test_rd_addr = (uint32_t *)0x41000000; - // for(int i = 0; i < 6; ++i) printf("recv %d: %x\n", i, *(test_rd_addr + i)); -} diff --git a/crt/src/rs_i2c.c b/crt/src/rs_i2c.c deleted file mode 100644 index 614bd046..00000000 --- a/crt/src/rs_i2c.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -void i2c0_init(uint8_t clkdiv) { - // printf("[i2c0] clkdiv: %d\n", reg_i2c0_clkdiv); - reg_i2c0_clkdiv = clkdiv; - // printf("[i2c0] clkdiv: %d\n", reg_i2c0_clkdiv); -} - -void i2c0_wr_nbyte(uint8_t dev_addr, uint16_t reg_addr, uint8_t type, uint8_t num, uint8_t *data) { - reg_i2c0_devaddr = dev_addr; - reg_i2c0_cfg = type; - for(int i = 0; i < num; ++i) { - // HACK: just repeat it by using no-burst xfer - reg_i2c0_regaddr = reg_addr + i; - reg_i2c0_txdata = data[i]; - reg_i2c0_xfer = I2C0_XFER_WR; - while(reg_i2c0_status != (uint32_t)1); - } -} - -void i2c0_rd_nbyte(uint8_t dev_addr, uint16_t reg_addr, uint8_t type, uint8_t num, uint8_t *data) { - reg_i2c0_devaddr = dev_addr; - reg_i2c0_cfg = type; - for(int i = 0; i < num; ++i) { - // HACK: just repeat it by using no-burst xfer - reg_i2c0_regaddr = reg_addr + i; - reg_i2c0_xfer = I2C0_XFER_RD; - while(reg_i2c0_status != (uint32_t)1); - // printf("[i2c0] i: %d, rxdata: %x\n", i, reg_i2c0_rxdata); - data[i] = reg_i2c0_rxdata; - } -} diff --git a/crt/src/rs_i2s.c b/crt/src/rs_i2s.c deleted file mode 100644 index c528f24c..00000000 --- a/crt/src/rs_i2s.c +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -uint32_t test_data[] = {0x12345678, 0x12345679, 0x1234567A, 0x2345EF23, 0x2345EF24, 0x2345EF25}; -uint32_t audio_addr[] = {0x61004000, 0x64737000}; -uint32_t audio_len = 2, audio_idx = 0; - -void i2s_init(uint32_t mode) { - reg_i2s_mode = (uint32_t)mode; - reg_i2s_upbound = (uint32_t)120; - // NOTE: larger than 'clk/clk_aud 'size of i2x tx fifo - reg_i2s_lowbound = (uint32_t)80; -} - -void i2s_simp_test() { - reg_i2s_mode = (uint32_t)1; - reg_i2s_format = (uint32_t)0; - for(uint32_t i = 0; i < 6; ++i) { - // while(reg_i2s_status & (uint32_t)1); // check if fifo is full or not - reg_i2s_txdata = test_data[i]; - } - printf("i2s tx done\n"); - - reg_i2s_recven = (uint32_t)1; - uint32_t tmp = 0; - for(uint32_t i = 0; i < 6; ) { - tmp = reg_i2s_rxdata; - if(tmp != 0) { - printf("rx data: %x\n", tmp); - ++i; - } - } - printf("i2s rx done\n"); -} - -void i2s_audio_load() { - WAVFile_t res = wav_audio_parse(audio_addr[audio_idx]); - if(res.addr == 0 || res.size == 0) printf("wav file pase error\n"); - else dma_config(1, res.addr, (uint32_t)1, (uint32_t)®_i2s_txdata, (uint32_t)0, res.size); -} - -void i2s_audio_panel() { - printf("============================================================\n"); - printf(" Tiny Audio Player \n"); - printf(" system: help[h] exit[e] mode[m] next-audio[n] \n"); - printf("============================================================\n"); - printf(" player: play[s] pause[t] reset[r] vol-up[u] vol-down[d] \n"); - printf("============================================================\n"); -} - -void ip_i2s_test(int argc, char **argv) { - (void) argc; - (void) argv; - - char type_ch; - uint32_t mode = 0, pause = 0, xfering = 0; - - es8388_init(); - printf("[APB IP] i2s test\n"); - // load first data - // i2s_audio_load(); - i2s_audio_panel(); - while(1) { - type_ch = getchar(); - - if(xfering) { - if(reg_dma_status == (uint32_t)1) { - printf("dma tx done\n"); - xfering = (uint32_t)0; - } - } - - if(type_ch == 'e' && !xfering) break; - else if(type_ch == 'h' && !xfering) i2s_audio_panel(); - else if(type_ch == 'n' && !xfering) { - if(audio_idx == audio_len - 1) audio_idx = 0; - else ++audio_idx; - - i2s_audio_load(); - } else if(type_ch == 'm' && !xfering) { - if(mode) { - mode = (uint32_t)0; - printf("switch to loopback mode\n"); - } else { - mode = (uint32_t)1; - printf("switch to fifo-xfer mode\n"); - } - i2s_init(mode); - } else if(type_ch == 's' && !xfering) { - // force switching to fifo-xfer mode - i2s_init(1); - xfering = (uint32_t)1; - dma_start_xfer(); - printf("start xfer\n"); - } else if(type_ch == 't' && xfering) { - if(pause) { - pause = (uint32_t)0; - dma_stop_toggle(); - i2s_init(1); - printf("resume audio play\n"); - } else { - pause = (uint32_t)1; - i2s_init(0); - dma_stop_toggle(); - printf("fsm: %d\n", reg_dma_fsm); - printf("pause audio play\n"); - } - } else if(type_ch == 'r' && xfering) { - xfering = (uint32_t)0; - i2s_init(0); - dma_reset_xfer(); - printf("reset audio play\n"); - } - } - - i2s_init(0); -} diff --git a/crt/src/rs_irq.c b/crt/src/rs_irq.c deleted file mode 100644 index efb3da19..00000000 --- a/crt/src/rs_irq.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include -#include -#include - -#define TIMER_DELTA_VALUE 360000UL -/* Define the interrupt handler name same as vector table in case download mode is flashxip. */ -// #define mtimer_irq_handler core_mtip_handler -// #define mtimer_sw_irq_handler core_msip_handler - -static volatile uint32_t int0_cnt = 0; /* msip timer interrupt test counter */ -static volatile uint32_t int1_cnt = 0; /* mtip timer interrupt test counter */ -volatile unsigned int msip_trig_flag = 1; /* sw trigger mtimer sw interrupt flag */ - -void mtimer_irq_handler(void) { - printf("MTimer IRQ handler %d\n\r", int0_cnt++); - // printf("mtimecmp: %x_%x\n", reg_clint_mtimecmph, reg_clint_mtimecmpl); - // printf("mtime: %x_%x\n", reg_clint_mtimeh, reg_clint_mtimel); - uint64_t now = SysTimer_GetMtimeValue(); - SysTimer_SetMtimecmpValue(now + TIMER_DELTA_VALUE); - delay_ms(1); -} - -void mtimer_sw_irq_handler(void) { - SysTimer_ClearSoftwareIRQ(); - int1_cnt++; - printf("MTimer SW IRQ handler %d\n\r", int1_cnt); - msip_trig_flag = 1; -} - -void setup_timer() { - printf("init timer and start\n\r"); - // for(int i = 0; i < 6; ++i) { - // printf("clkdiv: %x msip: %x mtimecmp: %x_%x\n", reg_clint_clkdiv, reg_clint_msip, reg_clint_mtimecmph, reg_clint_mtimecmpl); - // printf("mtime: %x_%x\n", reg_clint_mtimeh, reg_clint_mtimel); - // printf("clkdiv: %x msip: %x mtimecmp: %lx\n", reg_clint_clkdiv, reg_clint_msip, reg_clint_mtimecmpl); - // printf("mtime: %lx\n", reg_clint_mtimel); - // } - uint64_t now = SysTimer_GetMtimeValue(); - uint64_t then = now + TIMER_DELTA_VALUE; - - SysTimer_SetMtimecmpValue(then); -} - -extern int32_t register_system_core_irq_factory(uint32_t id, void *handler); - -void irq_test(int argc, char **argv) { - (void) argc; - (void) argv; - - register_system_core_irq_factory(IRQ_M_TIMER, mtimer_irq_handler); - __enable_irq(); - setup_timer(); - - while (int0_cnt < 6); - __disable_core_irq(IRQ_M_TIMER); - register_system_core_irq_factory(IRQ_M_SOFT, mtimer_sw_irq_handler); - - do { - if (msip_trig_flag == 1) { - msip_trig_flag = 0; - SysTimer_SetSoftwareIRQ(); - delay_ms(1); - } - } while (int1_cnt < 6); - - printf("MTimer msip and mtip interrupt test finish and pass\r\n"); -} diff --git a/crt/src/rs_lib.c b/crt/src/rs_lib.c deleted file mode 100644 index 4602cf48..00000000 --- a/crt/src/rs_lib.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -static unsigned long int rand_nxt = 1; - -int atoi(const char *str) { - int x = 0; - while (*str == ' ') { str++; } - while (*str >= '0' && *str <= '9') { - x = x * 10 + *str - '0'; - str++; - } - return x; -} - -char *itoa(unsigned int val, char *str, int base) { - char *p = str; - while(val) { - int tmp = val % base; - if(tmp <= 9) - *p++ = '0' + tmp; - else - *p++ = 'A' + tmp - 10; - val /= base; - } - for(char *i = str, *j = p - 1; i < p; ++i, --j) { - if(i >= j) break; - char tmp = *i; - *i = *j; - *j = tmp; - } - *p = 0; - return str; -} - -void *malloc(size_t size) { - // static void *program_break = 0; - // if (program_break == 0) { - // if (heap.start == 0) return 0; - // program_break = heap.start; - // } - // size = (size + 15) & ~15; - // void *mem = program_break; - // program_break += size; - // //assert(program_break <= heap.end, "Run out of memory"); - // return mem; - (void) size; - return NULL; -} - -void free(void *ptr) { - (void) ptr; -} - -int abs(int x) { - return (x < 0 ? -x : x); -} - -int rand(void) { - rand_nxt = rand_nxt * 1103515245 + 12345; - return (unsigned int)(rand_nxt/65536) % RAND_MAX; -} - -void srand(unsigned int seed) { - rand_nxt = seed; -} diff --git a/crt/src/rs_print.c b/crt/src/rs_print.c deleted file mode 100644 index 93afcc8d..00000000 --- a/crt/src/rs_print.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -void putchar(char c) { - if (c == '\n') putchar('\r'); - reg_uart0_data = c; -} - -char getchar() { - return reg_uart0_data; -} - -void print(const char *p) { - while (*p) putchar(*(p++)); -} diff --git a/crt/src/rs_printf.c b/crt/src/rs_printf.c deleted file mode 100644 index 041c2351..00000000 --- a/crt/src/rs_printf.c +++ /dev/null @@ -1,381 +0,0 @@ -#include -#include - -#include -#include - -typedef struct -{ - struct - { - union - { - int enable; - int is_right; - }; - char ch; - } pad, sign; - - char *out; - const char *end; - size_t nbyte; -} format_t; - -static void __putch(char c, int n, format_t *f) -{ - while (n--) - { - if (f->out == NULL) - putch(c); - // do not output if we reach the given size of the buffer - else if (f->out != f->end) - { - *((f->out)++) = c; - } - f->nbyte++; - } -} - -static void __putstr(const char *s, int len, format_t *f) -{ - while (len--) - __putch(*s++, 1, f); -} - -#define FORMAT_FUN_DEF(name, type, base) \ - static int name(char *revbuf, type n) \ - { \ - char *p = revbuf; \ - *(--p) = '\0'; \ - do \ - { \ - *(--p) = "0123456789abcdef"[n % base]; \ - n /= base; \ - } while (n); \ - return revbuf - p - 1; /* exclude the null byte */ \ - } - -FORMAT_FUN_DEF(format_oct32, uint32_t, 8) -FORMAT_FUN_DEF(format_dec32, uint32_t, 10) -FORMAT_FUN_DEF(format_hex32, uint32_t, 16) -// FORMAT_FUN_DEF(format_oct64, uint64_t, 8) -// FORMAT_FUN_DEF(format_dec64, uint64_t, 10) -// FORMAT_FUN_DEF(format_hex64, uint64_t, 16) - -static int format_int32(char *rev_buf, unsigned long long n, int base) -{ - switch (base) - { - case 8: - return format_oct32(rev_buf, n); - case 10: - return format_dec32(rev_buf, n); - case 16: - return format_hex32(rev_buf, n); - } - return 0; -} - -// static int format_int64(char *rev_buf, unsigned long long n, int base) -// { -// switch (base) -// { -// case 8: -// return format_oct64(rev_buf, n); -// case 10: -// return format_dec64(rev_buf, n); -// case 16: -// return format_hex64(rev_buf, n); -// } -// return 0; -// } - -enum -{ - LEN_NONE, - LEN_hh, - LEN_h, - LEN_l, - LEN_ll -}; - -static int vsnprintf_internal(char *out, size_t size, const char *fmt, va_list ap) -{ - format_t f = {}; - f.out = out; - f.end = (out && (size != 0) ? out + size : NULL); - f.nbyte = 0; - - const char *pfmt = fmt; - while (*pfmt) - { - char ch = *pfmt++; - if (ch != '%') - { - __putch(ch, 1, &f); - continue; - } - - char temp_buf[64]; - char *temp_buf_end = temp_buf + sizeof(temp_buf); - uint32_t varguint32 = 0; - uint64_t varguint64 = 0; - int is_64bit = false; -#ifdef __LP64__ -#define vargulong varguint64 -#else -#define vargulong varguint32 -#endif - - f.pad.is_right = false; - f.pad.ch = ' '; - f.sign.enable = false; - int width = 0; - int prec = 0; - int len_mod = LEN_NONE; - int is_signed = false; - int base = 0; - int conv_len = 0; - int width_pad_len = 0; - char *p_str; - - next_ch: - ch = *pfmt++; - reswitch: - switch (ch) - { - // flag character - case '#': - goto next_ch; // not implement - case '-': - f.pad.is_right = true; - f.pad.ch = ' '; - goto next_ch; - case '0': - if (!f.pad.is_right) - f.pad.ch = '0'; - goto next_ch; - case ' ': - if (!(f.sign.enable && f.sign.ch == '+')) - { - f.sign.enable = true; - f.sign.ch = ' '; - } - goto next_ch; - case '+': - f.sign.enable = true; - f.sign.ch = '+'; - goto next_ch; - - // field width - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - width = ch - '0'; - while ((ch = *pfmt++) >= '0' && ch <= '9') - { - width = width * 10 + ch - '0'; - } - if (ch == '-') - { - width = -width; - goto next_ch; - } - else - goto reswitch; - - // presicion; - case '.': - while ((ch = *pfmt++) >= '0' && ch <= '9') - { - prec = prec * 10 + ch - '0'; - } - f.pad.ch = ' '; // ignore '0' flag - goto reswitch; - - // length modifier - case 'h': - if ((ch = *pfmt++) == 'h') - { - len_mod = LEN_hh; - goto next_ch; - } - else - { - len_mod = LEN_h; - goto reswitch; - } - case 'l': - if ((ch = *pfmt++) == 'l') - { - len_mod = LEN_ll; - goto next_ch; - } - else - { - len_mod = LEN_l; - goto reswitch; - } - - // conversion specifier - case 'd': - case 'i': - is_signed = true; // fall through - case 'u': - base = 10; - goto read_arg; - case 'x': - case 'X': - base = 16; - goto read_arg; - case 'o': - base = 8; - goto read_arg; - - read_arg: -#define CASE(len_mod, actual_type, fetch_type, varguint) \ - case len_mod: \ - { \ - signed actual_type s = (signed actual_type)va_arg(ap, signed fetch_type); \ - is_64bit = (sizeof(varguint) == 8); \ - if (is_signed && s < 0) \ - { \ - f.sign.ch = '-'; \ - f.sign.enable = true; \ - /* avoid overflow when performing negation with INT_MIN */ \ - varguint = (unsigned actual_type)(-(s + 1)) + 1; \ - } \ - else \ - varguint = (unsigned actual_type)s; \ - break; \ - } - switch (len_mod) - { - CASE(LEN_hh, char, int, varguint32) - CASE(LEN_h, short, int, varguint32) - CASE(LEN_NONE, int, int, varguint32) - CASE(LEN_l, long, long, vargulong) - CASE(LEN_ll, long long, long long, varguint64) - } - print_num:; - int digit_len = (is_64bit ? format_int32(temp_buf_end, varguint64, base) : format_int32(temp_buf_end, varguint32, base)); - char *p_digit = temp_buf_end - digit_len - 1; - int sign_len = (is_signed && f.sign.enable ? 1 : 0); - int prec_pad0_len = (prec > digit_len ? prec - digit_len : 0); - conv_len = sign_len + prec_pad0_len + digit_len; - width_pad_len = (width > conv_len ? width - conv_len : 0); - - if (!f.pad.is_right && f.pad.ch == ' ') - { - __putch(f.pad.ch, width_pad_len, &f); - } - if (sign_len) - __putch(f.sign.ch, 1, &f); - if (!f.pad.is_right && f.pad.ch == '0') - { - __putch(f.pad.ch, width_pad_len, &f); - } - __putch('0', prec_pad0_len, &f); - __putstr(p_digit, digit_len, &f); - if (f.pad.is_right) - { - __putch(f.pad.ch, width_pad_len, &f); - } - break; - - case 'p': - vargulong = va_arg(ap, uintptr_t); - if (vargulong == 0) - { - __putstr("(nil)", 5, &f); - break; - } - __putstr("0x", 2, &f); - base = 16; - is_64bit = (sizeof(vargulong) == 8); - goto print_num; - - case 'c': - conv_len = 1; - char c = (char)va_arg(ap, int); - p_str = &c; - goto print_str; - - case 's': - p_str = va_arg(ap, char *); - conv_len = (prec == 0 ? (int)(strlen(p_str)) : prec); - print_str: - width_pad_len = (width > conv_len ? width - conv_len : 0); - if (!f.pad.is_right) - { - __putch(f.pad.ch, width_pad_len, &f); - } - __putstr(p_str, conv_len, &f); - if (f.pad.is_right) - { - __putch(f.pad.ch, width_pad_len, &f); - } - break; - - case '%': - __putch('%', 1, &f); - break; - - default:; - } - } - - if (f.out != NULL) - { - *f.out = '\0'; - } - return f.nbyte; -} - -int printf(const char *fmt, ...) -{ - // panic("Not implemented"); - va_list ap; - va_start(ap, fmt); - int r = vsnprintf_internal(NULL, 0, fmt, ap); - va_end(ap); - return r; -} - -int vsprintf(char *out, const char *fmt, va_list ap) -{ - // panic("Not implemented"); - return vsnprintf_internal(out, 0, fmt, ap); -} - -int sprintf(char *out, const char *fmt, ...) -{ - // panic("Not implemented"); - va_list ap; - va_start(ap, fmt); - int r = vsnprintf_internal(out, 0, fmt, ap); - va_end(ap); - return r; -} - -int snprintf(char *out, size_t n, const char *fmt, ...) -{ - // panic("Not implemented"); - va_list ap; - va_start(ap, fmt); - int r = vsnprintf_internal(out, n, fmt, ap); - va_end(ap); - return r; -} - -int vsnprintf(char *out, size_t n, const char *fmt, va_list ap) -{ - // panic("Not implemented"); - return vsnprintf_internal(out, n, fmt, ap); -} diff --git a/crt/src/rs_sh.c b/crt/src/rs_sh.c deleted file mode 100644 index 35f143fd..00000000 --- a/crt/src/rs_sh.c +++ /dev/null @@ -1,723 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include -// #include -#ifdef IP_MDD -#include -#endif - - -static char sh_argv_buf[MAX_CMD_ARGC][MAX_CMD_LEN]; // NOTE: clear -static char *sh_argv[MAX_CMD_ARGC]; -static uint8_t sh_argc; -static tinysh_cmd_t sh_cmd_list[MAX_CMD_NUM]; -static uint8_t sh_cmd_len; -static char sh_history_table[MAX_CMD_HIST][MAX_CMD_LEN]; -static uint8_t sh_history_idx; -// app -static char fat32_pwd[MAX_PATH_LEN]; -static char lsr_pwd[MAX_PATH_LEN]; -static uint8_t lsr_first; -static uint8_t file_buffer[MAX_BUFFER_LEN]; - - -uint8_t tinysh_register(char *name, char *info, uint8_t batch, void *handler) { - if(!name || !handler || !strlen(name)) return 1; - if(sh_cmd_len == MAX_CMD_NUM) return 1; - - for(uint8_t i = 0; i < sh_cmd_len; ++i) { - if(strcmp(name, sh_cmd_list[i].name) == 0) return 1; - } - - tinysh_cmd_t tmp = {name, info, batch, handler}; - sh_cmd_list[sh_cmd_len++] = tmp; - return 0; -} - -// static void tinysh_search_cmd(char *cmd, uint8_t len) { - -// } - -static uint8_t tinysh_split_cmd(char *cmd) { - trim_whitespace(cmd); - // printf("split original cmd: ==%s==\n", cmd); - if (strlen(cmd) == 0) return 1; - - sh_argc = 0; - char sub_cmd[MAX_CMD_LEN]; - uint8_t tmp_len = 0, escape_char = 0, cmd_len = strlen(cmd); - for(uint8_t i = 0; i < cmd_len; ++i) { - if(cmd[i] == '"') { - if(escape_char == 0) escape_char = 1; - else escape_char = 0; - } else if(cmd[i] == ' ' && escape_char == 0) { - sub_cmd[tmp_len] = 0; - // printf("sub cmd: %s\n", sub_cmd); - strcpy(sh_argv[sh_argc], sub_cmd); - ++sh_argc; - tmp_len = 0; - } else { - sub_cmd[tmp_len++] = cmd[i]; - } - } - sub_cmd[tmp_len] = 0; - // printf("sub cmd: %s\n", sub_cmd); - strcpy(sh_argv[sh_argc], sub_cmd); - ++sh_argc; - strcpy(sh_argv[sh_argc], NULL); - - // printf("argc: %d\nargv:", sh_argc); - // for(uint8_t i = 0; i <= sh_argc; ++i) { - // printf(" %s", sh_argv[i] == NULL ? "NULL" : sh_argv[i]); - // } - // printf("\n"); - - return 0; -} - -static void tinysh_parse_and_exec(char *cmd) { - uint8_t split_res = tinysh_split_cmd(cmd); - if(split_res == (uint8_t)1) { - printf("error input\n"); - return; - } - - bool is_find = false; - for(uint8_t i = 0; i < sh_cmd_len; ++i) { - if(strcmp(sh_argv[0], sh_cmd_list[i].name) == 0) { - is_find = true; - sh_cmd_list[i].handler(sh_argc, sh_argv); - lsr_first = 1; - break; - } - } - - if(!is_find) printf("cmd: [%s] not found\n", sh_argv[0]); -} - -void tinysh_load_file(char *path, uint8_t head) { - FIL ff_obj; - FRESULT ff_res; - UINT br; - FSIZE_t rd_len = 0; - - // printf("path: %s\n", path); - ff_res = f_open(&ff_obj, path, FA_READ); - if (ff_res != FR_OK) { - f_close(&ff_obj); - return; - } - - // printf("open file is right!\n"); - printf("stat: %d\n", ff_obj.obj.stat); - printf("size: %d bytes\n", ff_obj.obj.objsize); - - if(head) rd_len = 64; - else { - if(ff_obj.obj.objsize > MAX_BUFFER_LEN) { - printf("file size is larger than the buffer size\n"); - f_close(&ff_obj); - return; - } - rd_len = ff_obj.obj.objsize; - } - - ff_res = f_read(&ff_obj, file_buffer, rd_len, &br); - if(ff_res != FR_OK) printf("br: %d\n", br); - f_close(&ff_obj); -} - -static void tinysh_help() { - for(uint8_t i = 0; i < sh_cmd_len; ++i) { - printf("cmd: %-10s --- %s\n", sh_cmd_list[i].name, sh_cmd_list[i].info); - } -} - -static void tinysh_history_list() { - for(uint8_t i = 0; i < sh_history_idx; ++i) { - printf("%3d %s\n", i, sh_history_table[i]); - } -} - -static void tinysh_welcome() { - printf("================================\n"); - printf(" Tiny Shell \n"); - printf("================================\n"); -} - -void tinysh_init() { - sh_cmd_len = 0; - sh_history_idx = 0; - for(uint8_t i = 0; i < MAX_CMD_ARGC; ++i) { - sh_argv[i] = sh_argv_buf[i]; - } - strcpy(fat32_pwd, "/"); - lsr_first = 1; -} - -uint8_t tinysh_mount_fs(FATFS *fs) { - FRESULT ff_res; - ff_res = f_mount(fs, "0:", 1); - switch(ff_res) { - case FR_NO_FILESYSTEM: - printf("[fatfs] no filesystem\n"); - return 1; - break; - case FR_OK: - printf("[fatfs] mount done\n"); - return 0; - break; - default: - printf("[fatfs] filesystem mount fail\n"); - return 1; - } -} - -void tinysh_unmount_fs() { - f_mount(NULL, "0:", 1); -} - - -void tinysh_fat32_ls_cmd(int argc, char **argv) { - char dir_path[MAX_PATH_LEN]; - - printf("argc: %d ff_pwd: %s\n", argc, fat32_pwd); - if(argc == 1) strcpy(dir_path, fat32_pwd); - else if(argc == 2) { - strcpy(dir_path, argv[1]); - strcpy(fat32_pwd, argv[1]); - } else { - printf("[error] argv:"); - for(uint8_t i = 0; i < argc; ++i) { - printf(" %s", argv[i]); - } - printf("\n"); - return; - } - - FRESULT ff_res; - DIR ff_dir; - FILINFO ff_info; - int file_num, dir_num; - - ff_res = f_opendir(&ff_dir, dir_path); - if (ff_res == FR_OK) { - file_num = dir_num = 0; - while(1) { - ff_res = f_readdir(&ff_dir, &ff_info); /* Read a directory item */ - if (ff_info.fname[0] == 0) break; /* Error or end of ff_dir */ - if (ff_info.fattrib & AM_DIR) { /* It is a directory */ - printf(" %s/\n", ff_info.fname); - ++dir_num; - } else { /* It is a file */ - printf("%10u %s\n", ff_info.fsize, ff_info.fname); - ++file_num; - } - } - f_closedir(&ff_dir); - printf("%d dirs, %d files.\n", dir_num, file_num); - } else { - printf("Failed to open \"%s\". (%u)\n", dir_path, ff_res); - } -} - - -FRESULT tinysh_fat32_lsr_cmd(int argc, char **argv) { - (void) argv; - - if(argc != 1) { - printf("lsr cmd param error\n"); - return FR_OK; - } - - FRESULT ff_res; - DIR ff_dir; - UINT i; - FILINFO ff_info; - - if(lsr_first) { - strcpy(lsr_pwd, fat32_pwd); - lsr_first = 0; - } - - ff_res = f_opendir(&ff_dir, lsr_pwd); /* Open the directory */ - if (ff_res == FR_OK) { - while(1) { - ff_res = f_readdir(&ff_dir, &ff_info); /* Read a directory item */ - if (ff_info.fname[0] == 0) break; /* Break on error or end of ff_dir */ - if (ff_info.fattrib & AM_DIR) { /* The item is a directory */ - i = strlen(lsr_pwd); - sprintf(&lsr_pwd[i], "/%s", ff_info.fname); - ff_res = tinysh_fat32_lsr_cmd(argc, argv); /* Enter the directory */ - if (ff_res != FR_OK) break; - lsr_pwd[i] = 0; - } else { /* The item is a file. */ - printf("%s/%s\n", lsr_pwd, ff_info.fname); - } - } - f_closedir(&ff_dir); - } - return ff_res; -} - -void tinysh_fat32_cd_cmd(int argc, char **argv) { - if(argc != 2) { - printf("[cd] cmd param error\n"); - return; - } - - FRESULT ff_res; - TCHAR dir_path[MAX_PATH_LEN]; - if(strcmp(argv[1], "..") == 0) { - if(strcmp(fat32_pwd, "/") == 0) return; - - remove_suffix(dir_path, fat32_pwd, '/'); - } else if(argv[1][0] == '/') strcpy(dir_path, argv[1]); // abs path - else { - // rel path - strcpy(dir_path, fat32_pwd); - strcat(dir_path, "/"); - strcat(dir_path, argv[1]); - } - - ff_res = f_chdir(dir_path); - if(ff_res != FR_OK) { - printf("ch cmd exec error\n"); - } else strcpy(fat32_pwd, dir_path); - -} - -void tinysh_fat32_mv_cmd(int argc, char **argv) { - if(argc != 3) { - printf("[mv] cmd param error\n"); - return; - } - - FRESULT ff_res; - ff_res = f_rename(argv[1], argv[2]); - if(ff_res != FR_OK) printf("error: %d\n", ff_res); -} - - -void tinysh_fat32_pwd_cmd(int argc, char **argv) { - (void) argc; - (void) argv; - - FRESULT ff_res; - TCHAR dir_path[MAX_PATH_LEN]; - - ff_res = f_getcwd(dir_path, MAX_PATH_LEN); - if(ff_res == FR_OK) { - printf("%s\n", dir_path); - strcpy(fat32_pwd, dir_path); - } -} - -void tinysh_fat32_mkdir_cmd(int argc, char **argv) { - if(argc != 2) { - printf("[mkdir] cmd param error\n"); - return; - } - - FRESULT ff_res; - ff_res = f_mkdir(argv[1]); - if(ff_res != FR_OK) printf("error: %d\n", ff_res); -} - -void tinysh_fat32_rm_cmd(int argc, char **argv) { - if(argc != 2) { - printf("[rm] cmd param error\n"); - return; - } - - FRESULT ff_res; - ff_res = f_unlink(argv[1]); - if(ff_res != FR_OK) printf("error: %d\n", ff_res); -} - -void tinysh_fat32_chmod_cmd(int argc, char **argv) { - if(argc != 2) { - printf("[chmod] cmd param error\n"); - return; - } - - FRESULT ff_res; - ff_res = f_chmod(argv[1], AM_RDO, AM_RDO); - if(ff_res != FR_OK) printf("error: %d\n", ff_res); -} - -void tinysh_fat32_touch_cmd(int argc, char **argv) { - if(argc != 8) { - printf("[touch] cmd param error\n"); - return; - } - - FRESULT ff_res; - FILINFO ff_info; - // touch file year month day hour min sec - ff_info.fdate = (WORD)(((atoi(argv[2]) - 1980) * 512U) | atoi(argv[3]) * 32U | atoi(argv[4])); - ff_info.ftime = (WORD)(atoi(argv[5]) * 2048U | atoi(argv[6]) * 32U | atoi(argv[7]) / 2U); -#if FF_FS_CRTIME - ff_info.crdate = 0; /* Do not change created time in this code */ -#endif - - ff_res = f_utime(argv[1], &ff_info); - if(ff_res != FR_OK) printf("error: %d\n", ff_res); -} - -void tinysh_fat32_find_cmd(int argc, char **argv) { - if(argc != 2 && argc != 3) { - printf("find cmd param error\n"); - return; - } - - FRESULT ff_res; /* Return value */ - DIR ff_dir; /* Directory object */ - FILINFO ff_info; /* File information */ - - // support blob oper - if(argc == 2) { - ff_res = f_findfirst(&ff_dir, &ff_info, fat32_pwd, argv[1]); - } else if(argc == 3) { - ff_res = f_findfirst(&ff_dir, &ff_info, argv[1], argv[2]); - } - - while (ff_res == FR_OK && ff_info.fname[0]) { /* Repeat while an item is found */ - printf("%s\n", ff_info.fname); /* Print the object name */ - ff_res = f_findnext(&ff_dir, &ff_info); /* Search for next item */ - } - - f_closedir(&ff_dir); -} - -void tinysh_fat32_file_cmd(int argc, char **argv) { - if(argc != 2) { - printf("file cmd param error\n"); - return; - } - - // printf("file name: %s\n", argv[1]); - - FILINFO ff_info; - FRESULT ff_res; - ff_res = f_stat(argv[1], &ff_info); - - switch(ff_res) { - case FR_OK: - printf("[attr]: %c%c%c%c%c ", - (ff_info.fattrib & AM_DIR) ? 'D' : '-', - (ff_info.fattrib & AM_RDO) ? 'R' : '-', - (ff_info.fattrib & AM_HID) ? 'H' : '-', - (ff_info.fattrib & AM_SYS) ? 'S' : '-', - (ff_info.fattrib & AM_ARC) ? 'A' : '-'); - printf("[size]: %lu bytes ", ff_info.fsize); - printf("[date]: %u-%02u-%02u %02u:%02u%02u\n", - (ff_info.fdate >> 9) + 1980, ff_info.fdate >> 5 & 15, ff_info.fdate & 31, - ff_info.ftime >> 11, ff_info.ftime >> 5 & 63, ff_info.ftime * 2); - break; - case FR_NO_FILE: - case FR_NO_PATH: - printf("\"%s\" is not exist.\n", argv[1]); - break; - default: - printf("An error occured. (%d)\n", ff_res); - } -} - -void tinysh_fat32_write_cmd(int argc, char **argv) { - // write test.txt asdf.txtxt - if(argc != 3) { - printf("[write] cmd param error\n"); - return; - } - - FIL ff_obj; - FRESULT ff_res; - UINT ff_num; - ff_res = f_open(&ff_obj, argv[1], FA_WRITE | FA_CREATE_ALWAYS); - if(ff_res == FR_OK) { - ff_res = f_write(&ff_obj, argv[2], strlen(argv[2]), &ff_num); - if(ff_res != FR_OK) printf("error: %d\n", ff_res); - } else { - printf("error: %d\n", ff_res); - } - f_close(&ff_obj); -} - -void tinysh_fat32_cat_cmd(int argc, char **argv) { - if(argc != 2) { - printf("[cat] cmd param error\n"); - return; - } - - tinysh_load_file(argv[1], (uint8_t)1); - printf("file header:\n"); - for(uint8_t i = 0; i < 4; ++i) { - for(uint8_t j = 0; j < 16; ++j) { - printf("%02x", file_buffer[16*i+j]); - if(j <= 14) printf(" "); - } - printf("\n"); - } -} - -void tinysh_fat32_df_cmd(int argc, char **argv) { - (void) argv; - if(argc != 1) { - printf("[df] cmd param error\n"); - return; - } - - FATFS *fs; - FRESULT ff_res; - DWORD free_clust, free_sect, total_sect; - /* Get volume information and free clusters of drive 1 */ - ff_res = f_getfree("0:", &free_clust, &fs); - if (ff_res != FR_OK) { - printf("error: %d\n", ff_res); - return; - } - - /* Get total sectors and free sectors */ - total_sect = (fs->n_fatent - 2) * fs->csize; - free_sect = free_clust * fs->csize; - - /* Print the free space (assuming 512 bytes/sector) */ - printf("%10lu MiB total drive space.\n%10lu MiB available.\n", total_sect / 2 / 1024, free_sect / 2 / 1024); -} - -void tinysh_fat32_fatlabel_cmd(int argc, char **argv) { - if(argc != 1 && argc != 2) { - printf("[fatlabel] cmd param error\n"); - return; - } - - TCHAR label[24]; - DWORD vsn; - FRESULT ff_res; - if(argc == 1) { - ff_res = f_getlabel("", label, &vsn); - if (ff_res != FR_OK) printf("error: %d\n", ff_res); - printf("Volume Label: %s\n", label); - printf("Volume Serial Number: %lu\n", (unsigned long)vsn); - } else if(argc == 2) { - ff_res = f_setlabel(argv[1]); - if(ff_res != FR_OK) printf("error: %d\n", ff_res); - } -} - -void tinysh_app_image_cmd(int argc, char **argv) { - // image: -i -m[0] file.bin - // uint8_t is_info = 1, frame = 0; - if(argc != 2) { - printf("[image] cmd param error\n"); - return; - } - - // for(uint8_t i = 0; i < 64; ++i) printf("file_buffer: %x\n", file_buffer[i]); - - static uint8_t image_is_init = 0; - if(image_is_init == 0) { - tinysh_load_file(argv[1], (uint8_t)0); - image_is_init = 1; - } - - VideoHeader_t* videoHeader = (VideoHeader_t *)file_buffer; - printf("================================\n"); - printf(" image bin file info \n"); - printf("width: %d\n", videoHeader->width); - printf("height: %d\n", videoHeader->height); - printf("frame count: %d\n", videoHeader->frame_count); - printf("================================\n"); - - uint32_t* ptr = (uint32_t*)(file_buffer + 16); - uint32_t delta = videoHeader->width * videoHeader->height / 2; - uint8_t idx = 0; - while(1) { - lcd_fill_image(0, 0, videoHeader->width, videoHeader->height, ptr); - delay_ms(3000); - - if(idx == 3) { - idx = 0; - ptr = (uint32_t*)(file_buffer + 16); - } else { - ++idx; - ptr += delta; - } - } - -} - -// video -i info -void tinysh_app_video_cmd(int argc, char **argv) { - (void)argc; - (void)argv; -} - -// audio -i info -void tinysh_app_audio_cmd(int argc, char **argv) { - (void)argc; - (void)argv; -} - - -// val * 1000 / CPU_FREQ / 1000 / 1000 -// uint32_t my_get_millis(void) { -// return reg_tim1_val / CPU_FREQ / 1000; -// } - -void tinysh_app_lvgl_cmd(int argc, char **argv) { - (void)argc; - (void)argv; - - // lv_init(); - // tim1_init(); - // lv_tick_set_cb(my_get_millis); - - // lv_port_disp_init(); - - // lv_obj_t *label = lv_label_create(lv_scr_act()); - // lv_label_set_text(label,"Hello maksyuki!!!"); - // lv_obj_center(label); - - // while(1) { - // lv_timer_handler(); - // delay_ms(5); - // printf("hello\n"); - // } -} - -void tinysh_app_arduboy_cmd(int argc, char **argv) { - (void)argc; - (void)argv; -} - -void tinysh_app_nes_cmd(int argc, char **argv) { - (void)argc; - (void)argv; -} - -void tinysh_app_coremark_cmd(int argc, char **argv) { - (void)argc; - (void)argv; - core_main(); -} - -#ifdef IP_MDD -void tinysh_app_userip_cmd(int argc, char **argv) { - if(argc != 1 && argc != 2) { - printf("[userip] cmd param error\n"); - return; - } - - if(argc == 1) { - printf("current user ip id: %03d\n", reg_sysctrl_ipsel); - userip_main(0, NULL); - } else if(argc == 2) { - int16_t user_id = atoi(argv[1]); - if(user_id >= 0 && user_id <= 255) { - printf("switch to user ip id to [%03d...]\n", user_id); - reg_sysctrl_ipsel = (uint8_t)user_id; - userip_main(user_id, NULL); // HACK: - } else { - printf("error use id: %d\n", user_id); - return; - } - } - // userip: list all info/current id -} -#endif - -void tinysh_launch() { - char type_res[MAX_CMD_LEN], type_ch; - uint8_t type_len; - - tinysh_welcome(); - uint8_t fs_init_state = 0; - FATFS fs; - fs_init_state = tinysh_mount_fs(&fs); - // register internal cmd - tinysh_register("help", "help info", (uint8_t)0, tinysh_help); - tinysh_register("history", "print history list", (uint8_t)0, tinysh_history_list); - tinysh_register("coremark", "coremark test", (uint8_t)0, tinysh_app_coremark_cmd); -#ifdef IP_MDD - tinysh_register("userip", "run user ip program", (uint8_t)0, tinysh_app_userip_cmd); -#endif - if(fs_init_state == (uint8_t)0) { - tinysh_register("ls", "list directory contents", (uint8_t)0, tinysh_fat32_ls_cmd); - tinysh_register("lsr", "list directory contents recursively", (uint8_t)0, tinysh_fat32_lsr_cmd); - tinysh_register("cd", "change directory", (uint8_t)0, tinysh_fat32_cd_cmd); - tinysh_register("mv", "move/remove files", (uint8_t)0, tinysh_fat32_mv_cmd); - tinysh_register("pwd", "print current directory", (uint8_t)0, tinysh_fat32_pwd_cmd); - tinysh_register("mkdir", "make directories", (uint8_t)0, tinysh_fat32_mkdir_cmd); - tinysh_register("rm", "remove files or directories", (uint8_t)0, tinysh_fat32_rm_cmd); - tinysh_register("chmod", "change file mode bits", (uint8_t)0, tinysh_fat32_chmod_cmd); - tinysh_register("touch", "change file timestamps", (uint8_t)0, tinysh_fat32_touch_cmd); - tinysh_register("find", "search files in directory", (uint8_t)0, tinysh_fat32_find_cmd); - tinysh_register("file", "print file info", (uint8_t)0, tinysh_fat32_file_cmd); - tinysh_register("write", "write stirng to file", (uint8_t)0, tinysh_fat32_write_cmd); - tinysh_register("cat", "concatenate file(s) to standard output", (uint8_t)0, tinysh_fat32_cat_cmd); - tinysh_register("df", "report file system disk space usage", (uint8_t)0, tinysh_fat32_df_cmd); - tinysh_register("fatlabel", "set/get filesystem label or volume ID", (uint8_t)0, tinysh_fat32_fatlabel_cmd); - tinysh_register("image", "image viewer", (uint8_t)0, tinysh_app_image_cmd); - tinysh_register("video", "video player", (uint8_t)0, tinysh_app_video_cmd); - tinysh_register("audio", "audio player", (uint8_t)0, tinysh_app_audio_cmd); - tinysh_register("lvgl", "show lvgl components", (uint8_t)0, tinysh_app_lvgl_cmd); - tinysh_register("arduboy", "run arduboy", (uint8_t)0, tinysh_app_arduboy_cmd); - tinysh_register("nes", "run nes simulator", (uint8_t)0, tinysh_app_nes_cmd); - printf("register cmd num: %d\n", sh_cmd_len); - } - - while(1) { - printf("tinysh > "); - type_len = 0; - - do { - type_ch = getchar(); - if((type_ch >= 'a' && type_ch <= 'z') || (type_ch >= 'A' && type_ch <= 'Z') || - (type_ch >= '0' && type_ch <= '9') || type_ch == ' ' || type_ch == '.' || - type_ch == '/' || type_ch == '_' || type_ch == '"' || type_ch == '/' || - type_ch == '*' || type_ch == '-') { - if(type_len == MAX_CMD_LEN) break; - putchar(type_ch); - type_res[type_len++] = type_ch; - } else if(type_ch == '\b' || type_ch == (char) 127){ - if(type_len == 0) continue; - printf("\b \b"); - type_res[type_len--] = 0; - } else if(type_ch == (char) 9) { // tab - printf("tab\n"); - // tinysh_search_cmd(type_res, type_len); - } - - } while(type_ch != '\n' && type_ch != '\r'); - putchar('\n'); - - type_res[type_len] = 0; - if(sh_history_idx < MAX_CMD_HIST) strcpy(sh_history_table[sh_history_idx++], type_res); - else { - for(uint8_t i = 1; i < MAX_CMD_HIST; ++i) { - strcpy(sh_history_table[i-1], sh_history_table[i]); - } - strcpy(sh_history_table[sh_history_idx-1], type_res); - } - - tinysh_parse_and_exec(type_res); - // printf("ff_pwd: %s\n", fat32_pwd); - } -} - -void tinysh_batch_run() { - for(uint8_t i = 0; i < sh_cmd_len; ++i) { - if(sh_cmd_list[i].batch == (uint8_t)1) sh_cmd_list[i].handler(0, NULL); - } -} diff --git a/crt/src/rs_spisd.c b/crt/src/rs_spisd.c deleted file mode 100644 index 83d2d05d..00000000 --- a/crt/src/rs_spisd.c +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include - - -void spisd_mem_read(uint8_t *buff, uint32_t size, uint32_t count, uint32_t addr) { - switch(size) { - case 1: { - volatile uint8_t *wr_ptr = (volatile uint8_t*)addr; - volatile uint8_t *buff_ptr = (volatile uint8_t*)buff; - for (uint32_t i = 0; i < count; ++i) buff_ptr[i] = wr_ptr[i]; - break; - } - case 2: { - volatile uint16_t *wr_ptr = (volatile uint16_t*)addr; - volatile uint16_t *buff_ptr = (volatile uint16_t*)buff; - for (uint32_t i = 0; i < count; ++i) buff_ptr[i] = wr_ptr[i]; - break; - } - case 4: { - volatile uint32_t *wr_ptr = (volatile uint32_t*)addr; - volatile uint32_t *buff_ptr = (volatile uint32_t*)buff; - for (uint32_t i = 0; i < count; ++i) buff_ptr[i] = wr_ptr[i]; - break; - } - default: - printf("error\n"); - break; - } -} - -void spisd_sector_read(uint8_t *buff, uint32_t sector, uint32_t count) { - uint32_t start_addr = sector * 512; - start_addr += TF_CARD_START; - // printf("start: %x len: %x buff: %p\n\n", start_addr, 128 * count, buff); - -#ifdef USE_SPISD_DMA - dma_config((uint32_t)0, start_addr, (uint32_t)1, (uint32_t)buff, (uint32_t)1, 128 * count); - dma_start_xfer(); - dma_wait_done(); -#else - volatile uint32_t *vis_addr = (uint32_t *)start_addr; - for(uint32_t i = 0; i < count; ++i) { - for(uint32_t j = 0; j < 128; ++j, ++vis_addr, buff += 4) { - // printf("addr: %x val: %x\n", vis_addr, *vis_addr); - *((uint32_t*)buff) = *vis_addr; - } - } -#endif -} - -void spisd_sector_write(const uint8_t *buff, uint32_t sector, uint32_t count) { - uint32_t start_addr = sector * 512; - start_addr += TF_CARD_START; - // printf("start: %x len: %x buff: %p\n\n", start_addr, 128 * count, buff); - -#ifdef USE_SPISD_DMA - dma_config((uint32_t)0, (uint32_t)buff, (uint32_t)1, start_addr, (uint32_t)1, 128 * count); - dma_start_xfer(); - dma_wait_done(); -#else - volatile uint32_t *vis_addr = (uint32_t *)start_addr; - for(uint32_t i = 0; i < count; ++i) { - for(uint32_t j = 0; j < 128; ++j, ++vis_addr, buff += 4) { - *vis_addr = *((uint32_t*)buff); - } - } -#endif -} - -void spisd_sector_sync() { - reg_spisd_sync = (uint32_t)1; - while(reg_spisd_status == (uint32_t)0b11); - printf("spisd wr sync\n"); -} - -void ip_spisd_test() { - printf("spisd test\n"); - printf("[SPISD] clk div(default): %d\n", reg_spisd_clkdiv); - ip_psram_selftest(0x50000000, 1 * 1024 * 1024); -} - -void ip_spisd_read(uint32_t addr, uint32_t len) { - printf("spisd read test\n"); - printf("[SPISD] mode(default): %d\n", reg_spisd_mode); - printf("[SPISD] clk div(default): %d\n", reg_spisd_clkdiv); - printf("[SPISD] status: %d\n", reg_spisd_status); - - printf("START: %x LEN: %x\n\n", addr, len); - volatile uint32_t *vis_addr = (uint32_t *)addr; - for(uint32_t i = 0; i < len; ++i, ++vis_addr) { - printf("addr: %x val: %x\n", vis_addr, *vis_addr); - } - - // uint8_t res[512] = {0}; - // printf("\nsector read test\n"); - // spisd_sector_read(res, 32800, 1); - // for(int i = 0; i < 512; ++i) { - // printf("res[%d]: %x\n", i, res[i]); - // } -} diff --git a/crt/src/rs_string.c b/crt/src/rs_string.c deleted file mode 100644 index 29ef0830..00000000 --- a/crt/src/rs_string.c +++ /dev/null @@ -1,183 +0,0 @@ -#include - -size_t strlen(const char *s) -{ - const char *p = s; - while (*p) - { - p++; - } - - return p - s; -} - -char *strcpy(char *dst, const char *src) -{ - char *d = dst; - while ((*d++ = *src++)) - { - } - - return dst; -} - -char *strncpy(char *dst, const char *src, size_t n) -{ - char *d = dst; - while ((n--) > 0 && (*d++ = *src++)) - { - } - while ((n--) > 0) - { - *d++ = 0; - } - - return dst; -} - -char *strcat(char *dst, const char *src) -{ - char *d = dst; - - while (*d++) - { - } - d--; - while ((*d++ = *src++)) - { - } - - return dst; -} - -int strcmp(const char *s1, const char *s2) -{ - // unsigned char type is very important - unsigned char c1, c2; - - do - { - c1 = *s1++; - c2 = *s2++; - } while (c1 != 0 && c1 == c2); - - return c1 - c2; -} - -int strncmp(const char *s1, const char *s2, size_t n) -{ - unsigned char c1, c2; - - do - { - c1 = *s1++; - c2 = *s2++; - } while ((n--) > 0 && c1 != 0 && c1 == c2); - - if (!n) - return 0; - return c1 - c2; -} - -void *memset(void *dst, int c, size_t n) -{ - char *cdst = (char *)dst; - - for (uint32_t i = 0; i < n; i++) - { - cdst[i] = c; - } - - return dst; -} - -void *memmove(void *dst, const void *src, size_t n) -{ - const char *s = src; - char *d = dst; - - if (s < d && s + n > d) - { - s += n; - d += n; - while (n-- > 0) - { - *--d = *--s; - } - } - else - { - while (n-- > 0) - { - *d++ = *s++; - } - } - - return dst; -} - -void *memcpy(void *out, const void *in, size_t n) -{ - return memmove(out, in, n); -} - -int memcmp(const void *s1, const void *s2, size_t n) -{ - const unsigned char *v1 = s1; - const unsigned char *v2 = s2; - - while ((n--) > 0) - { - if (*v1 != *v2) - { - return *v1 - *v2; - } - v1++, v2++; - } - - return 0; -} - -char *strchr(const char *s, int c) { - const char ch = (char)c; - - do { - if (*s == ch) return (char *)s; - } while (*s++ != '\0'); - - return 0; -} - - -void trim_whitespace(char *str) { - char *start = str; - while (*start && *start == ' ') start++; - - if (*start == '\0') { - *str = '\0'; - return; - } - - char *end = start + strlen(start) - 1; - while (end > start && (*end == ' ' || *end == '\n' || *end == '\r')) { - *end = '\0'; - end--; - } - - if (start != str) { - memmove(str, start, (end - start) + 2); - } -} - -void remove_suffix(char *dst, char *src, char sign) { - uint8_t idx = 0; - for(uint8_t i = strlen(src) - 1; i >= 1; --i) { - if(src[i] == sign) { - idx = i; break; - } - } - - for(uint8_t i = 0; i < idx; ++i) dst[i] = src[i]; - - dst[idx] = 0; -} diff --git a/crt/src/rs_uart.c b/crt/src/rs_uart.c deleted file mode 100644 index 89959131..00000000 --- a/crt/src/rs_uart.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -void uart0_init(uint32_t freq, uint32_t bps) { - reg_uart0_clkdiv = (uint32_t)(freq * 1000000 / bps); -} - -void putch(char ch) -{ - // while (((reg_uart1_lsr & 0x100) >> 8) == 1) - // ; - // reg_uart1_trx = (uint32_t)ch; - - reg_uart0_data = ch; -} diff --git a/crt/src/rs_wdg.c b/crt/src/rs_wdg.c deleted file mode 100644 index 4070a804..00000000 --- a/crt/src/rs_wdg.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -void ip_wdg_test(int argc, char **argv) { - (void) argc; - (void) argv; - - printf("[APB IP] wdg test\n"); - - reg_wdg_key = WDG_MAGIC_NUM; - reg_wdg_ctrl = (uint32_t)0x0; - - // feed wdg in every 50ms - reg_wdg_key = WDG_MAGIC_NUM; - reg_wdg_pscr = (uint32_t)(CPU_FREQ - 1); // div/'CPU_FREQ' for 1MHz - - reg_wdg_key = WDG_MAGIC_NUM; - - reg_wdg_cmp = (uint32_t)(50000 - 1); // overflow in every 50ms - // reg_wdg_cmp = (uint32_t)(500 - 1); // overflow in every 500ns - - while(reg_wdg_stat == (uint32_t)0x1); // clear irq flag - - reg_wdg_key = WDG_MAGIC_NUM; - reg_wdg_ctrl = (uint32_t) 0b101; // core and ov trg en - - reg_wdg_key = WDG_MAGIC_NUM; - reg_wdg_feed = (uint32_t) 0x1; - reg_wdg_key = WDG_MAGIC_NUM; - reg_wdg_feed = (uint32_t) 0x0; - - for(int i = 0; i < 10; ++i) { - printf("reg_wdg_pscr: %d\n", reg_wdg_pscr); - while(reg_wdg_stat == (uint32_t)0); - printf("%d wdg reset trigger\n", i); - } -} diff --git a/crt/src/rs_bench.c b/crt/src/service/bench.c similarity index 50% rename from crt/src/rs_bench.c rename to crt/src/service/bench.c index 50987a88..4b01aa5c 100644 --- a/crt/src/rs_bench.c +++ b/crt/src/service/bench.c @@ -1,58 +1,49 @@ -#include -#include +#include +#include +#include -uint32_t tinybench(bool verbose, uint32_t *instns_p) -{ +uint32_t rs_bench(bool verbose, uint32_t *instns_p) { printf("benckmark test\n"); - uint8_t data[256]; - uint32_t *words = (void *)data; + uint32_t words[64] = {0U}; + uint8_t *data = (uint8_t *)words; uint32_t x32 = 314159265; uint32_t cycles_begin, cycles_end; uint32_t instns_begin, instns_end; - __asm__ volatile("rdcycle %0" - : "=r"(cycles_begin)); - __asm__ volatile("rdinstret %0" - : "=r"(instns_begin)); + __asm__ volatile("rdcycle %0" : "=r"(cycles_begin)); + __asm__ volatile("rdinstret %0" : "=r"(instns_begin)); printf("cycle and instns read done!\n"); - for (int i = 0; i < 20; i++) - { - for (int k = 0; k < 256; k++) - { + for (int i = 0; i < 20; i++) { + for (int k = 0; k < 256; k++) { x32 ^= x32 << 13; x32 ^= x32 >> 17; x32 ^= x32 << 5; data[k] = x32; } - for (int k = 0, p = 0; k < 256; k++) - { + for (int k = 0, p = 0; k < 256; k++) { if (data[k]) data[p++] = k; } - for (int k = 0; k < 64; k++) - { + for (int k = 0; k < 64; k++) { x32 = x32 ^ words[k]; } } - __asm__ volatile("rdcycle %0" - : "=r"(cycles_end)); - __asm__ volatile("rdinstret %0" - : "=r"(instns_end)); + __asm__ volatile("rdcycle %0" : "=r"(cycles_end)); + __asm__ volatile("rdinstret %0" : "=r"(instns_end)); - if (verbose) - { + if (verbose) { printf("Cycles: 0x%x\n", cycles_end - cycles_begin); printf("Instns: 0x%x\n", instns_end - instns_begin); printf("Chksum: 0x%x\n", x32); } - if (instns_p) + if (instns_p != NULL) *instns_p = instns_end - instns_begin; printf("benckmark done\n"); diff --git a/crt/src/service/booter.c b/crt/src/service/booter.c new file mode 100644 index 00000000..74dfedcc --- /dev/null +++ b/crt/src/service/booter.c @@ -0,0 +1,227 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +// HACK: +#if defined(CORE_MDD) || defined(IP_MDD) +#include <../../rtl/mini/mpw/.build/user_design_info.h> +#endif + +void rs_app_info(void) { + printf("#############################################################\n"); + printf("#############################################################\n"); + printf("compile date: %s %s\n", __DATE__, __TIME__); + printf("first bootloader done, app section info:\n"); + printf("_flash_wait_start: %p\n", (void *)&_flash_wait_start); + printf("_flash_wait_end: %p\n", (void *)&_flash_wait_end); + printf("_ram_lma: %p\n", (void *)&_ram_lma); + printf("_ram_vma: %p\n", (void *)&_ram_vma); + printf("_ram_start: %p\n", (void *)&_ram_start); + printf("stack point: %p\n", (void *)&_stack_point); + printf("_stext(entry): %p\n", (void *)&_start); + printf("_etext: %p\n", (void *)&_etext); + printf("_psram_lma: %p\n", (void *)&_psram_lma); + printf("_psram_vma: %p\n", (void *)&_psram_vma); + printf("_edata: %p\n", (void *)&_edata); + printf("_sbss: %p\n", (void *)&_sbss); + printf("_ebss: %p\n", (void *)&_ebss); + printf("_heap_start: %p\n\n", (void *)&_heap_start); + printf("uart config: 8n1 %dbps\n", UART_BPS); + printf("app booting...\n"); + printf("\n"); + printf(" _ _____ _____ \n"); + printf(" | | / ____| / ____|\n"); + printf(" _ __ ___| |_ _ __ ___| (___ ___ | | \n"); + printf("| '__/ _ \\ __| '__/ _ \\\\___ \\ / _ \\| |\n"); + printf("| | | __/ |_| | | (_) |___) | (_) | |____ \n"); + printf("|_| \\___|\\__|_| \\___/_____/ \\___/ \\_____|\n"); + printf(" retroSoC: A Customized ASIC for Retro Stuff\n"); + printf(" \n"); + printf(" author: Yuchi Miao \n"); + printf(" contributor: MrAMS \n"); + printf(" license: MulanPSL-2.0 license\n\n"); + printf(" series: retroSoC Mini\n"); + printf(" specs: Gen2 Plus\n"); + printf(" version: %s(commit: %s)\n\n", RETROSOC_BRANCH, RETROSOC_COMMIT); + + printf("User Processors:\n"); +#ifndef CORE_MDD + printf(" CORE: %s\n", HW_CORE); +#else + uint32_t core_size = sizeof(user_core_info) / sizeof(user_core_info[0]); + printf(" %-15s %-12s %-12s %s\n", "[name]", "[isa]", "[maintainer]", "[repo]"); + for (uint32_t i = 0; i < core_size; ++i) { + if (reg_sysctrl_coresel == i) + printf("=>"); + else + printf(" "); + printf("[%d]: %-15s %-12s %-12s %s\n", i, user_core_info[i].name, user_core_info[i].isa, + user_core_info[i].maintainer, user_core_info[i].repo); + } +#endif + +#ifdef IP_MDD + printf("\nUser IPs:\n"); + uint32_t ip_size = sizeof(user_ip_info) / sizeof(user_ip_info[0]); + printf(" %-15s %-12s %-12s %s\n", "[name]", "[isa]", "[maintainer]", "[repo]"); + for (uint32_t i = 0; i < ip_size; ++i) { + if (reg_sysctrl_ipsel == i) + printf("=>"); + else + printf(" "); + printf("[%d]: %-15s %-12s %-12s %s\n", i, user_ip_info[i].name, user_ip_info[i].isa, + user_ip_info[i].maintainer, user_ip_info[i].repo); + } +#endif + + printf("\nSoftware:\n"); + printf(" COMPILER: %s\n", COMPILER_NAME); + printf(" CFLAGS: %s\n", COMPILER_CFLAGS); + printf(" ISA: %s\n", COMPILER_ISA); + printf(" FREQ: %dMHz\n\n", CPU_FREQ); + + printf("Inst/Memory Address Range:\n"); + printf(" QSPI Flash: @[0x%08x-0x%08x] %3d MiB\n", SPFS_MEM_START, + SPFS_MEM_START + SPFS_MEM_OFFST - 1, SPFS_MEM_OFFST / 1024 / 1024); + printf(" NMI IP MMIO: @[0x%08x-0x%08x] %3d MiB\n", NMI_MEM_START, + NMI_MEM_START + NMI_MEM_OFFST - 1, NMI_MEM_OFFST / 1024 / 1024); + printf(" APB IP MMIO: @[0x%08x-0x%08x] %3d MiB\n", APB_MEM_START, + APB_MEM_START + APB_MEM_OFFST - 1, APB_MEM_OFFST / 1024 / 1024); + printf(" On-chip RAM: @[0x%08x-0x%08x] %3d KiB\n", SRAM_MEM_START, + SRAM_MEM_START + SRAM_MEM_OFFST - 1, SRAM_MEM_OFFST / 1024); + printf(" Off-chip SDRAM: @[0x%08x-0x%08x] %3d MiB\n", SDRAM_MEM_START, + SDRAM_MEM_START + SDRAM_MEM_OFFST - 1, SDRAM_MEM_OFFST / 1024 / 1024); + printf(" Off-chip PSRAM: @[0x%08x-0x%08x] %3d MiB(%dx8MiB)\n", PSRAM_MEM_START, + PSRAM_MEM_START + PSRAM_MEM_OFFST - 1, 8 * PSRAM_NUM, PSRAM_NUM); + printf(" Off-chip OPIPSRAM: @[0x%08x-0x%08x] %3d MiB\n", OPIPSRAM_MEM_START, + OPIPSRAM_MEM_START + OPIPSRAM_MEM_OFFST - 1, OPIPSRAM_MEM_OFFST / 1024 / 1024); + printf(" XPI MMIO: @[0x%08x-0x%08x] %3d MiB\n", XPI_MEM_START, + XPI_MEM_START + XPI_MEM_OFFST - 1, XPI_MEM_OFFST / 1024 / 1024); + printf(" SPISD MMIO: @[0x%08x-0x%08x] %3d GiB\n\n", TF_CARD_START, + TF_CARD_START + TF_CARD_OFFST - 1, TF_CARD_OFFST / 1024 / 1024 / 1024); + + printf("Memory Map IO Device:\n"); + printf(" 1 x GPIO(32PIN) @%p\n", (void *)®_gpio_oe); + printf(" 1 x UART0 @%p\n", (void *)®_uart0_clkdiv); + printf(" 2 x TIMER(0,1) @%p,%p\n", (void *)®_tim0_cfg, + (void *)®_tim1_cfg); + printf(" 1 x PSRAM @%p\n", (void *)®_psram_wait); + printf(" 1 x SPISD @%p\n", (void *)®_spisd_mode); + printf(" 1 x I2C0 @%p\n", (void *)®_i2c0_clkdiv); + printf(" 1 x I2S @%p\n", (void *)®_i2s_mode); + printf(" 1 x ONEWIRE @%p\n", (void *)®_onewire_clkdiv); + printf(" 1 x XPI @%p\n", (void *)®_xpi_cfgidx); + printf(" 1 x DMA @%p\n", (void *)®_dma_mode); + printf(" 1 x SYSCTRL @%p\n", (void *)®_sysctrl_coresel); + printf(" 1 x CLINT @%p\n", (void *)®_clint_mtimel); + printf(" 1 x SDRAM @%p\n", (void *)®_sdram_clkdiv); + printf(" 1 x DVP @%p\n", (void *)®_dvp_recven); + printf(" 1 x SDIO @%p\n", (void *)®_sdio_cfg); + printf(" 1 x OPIPSRAM @%p\n", (void *)®_opipsram_cfg); + printf(" 1 x I2C1 @%p\n", (void *)®_i2c1_clkdiv); + printf(" 1 x GA* @%p\n", (void *)®_ga_cfg); + printf(" 1 x APU* @%p\n", (void *)®_apu_cfg); + printf(" 1 x ARCHINFO @%p\n", (void *)®_archinfo_sys); + printf(" 1 x RNG @%p\n", (void *)®_rng_ctrl); + printf(" 1 x UART1(ADV) @%p\n", (void *)®_uart1_lcr); + printf(" 1 x PWM(4CHNL) @%p\n", (void *)®_pwm_ctrl); + printf(" 1 x PS2 @%p\n", (void *)®_ps2_ctrl); + printf(" 1 x RTC @%p\n", (void *)®_rtc_ctrl); + printf(" 1 x WDG @%p\n", (void *)®_wdg_ctrl); + printf(" 1 x CRC @%p\n", (void *)®_crc_ctrl); + printf(" 1 x TIMER3(ADV) @%p\n", (void *)®_tim3_ctrl); + printf(" 1 x USER_IP(4KiB) @%p\n\n", (void *)®_user_ip_reg0); + printf("#############################################################\n"); + printf("#############################################################\n"); +} + +static uint8_t rs_booter_shell(void) { + printf("================================\n"); + printf(" retroSoC Booter Shell \n"); + printf("================================\n"); + printf("0: flash(defalut) 1: uart 2: tf\n"); + + char type_res[RS_SHELL_MAX_COMMAND_LENGTH + 1U]; + char type_ch; + size_t type_len; + + for (;;) { + printf("rs_shell > "); + type_len = 0U; + do { + type_ch = getchar(); + if ((type_ch >= 'a' && type_ch <= 'z') || (type_ch >= 'A' && type_ch <= 'Z') || + (type_ch >= '0' && type_ch <= '9') || type_ch == ' ' || type_ch == '.' || + type_ch == '/' || type_ch == '_' || type_ch == '"' || type_ch == '/' || + type_ch == '*' || type_ch == '-') { + if ((type_len + 1U) >= sizeof(type_res)) { + continue; + } + putchar(type_ch); + type_res[type_len++] = type_ch; + } else if (type_ch == '\b' || type_ch == (char)127) { + if (type_len == 0) + continue; + printf("\b \b"); + type_res[type_len--] = 0; + } else if (type_ch == (char)9) { // tab + printf("tab\n"); + } + + } while (type_ch != '\n' && type_ch != '\r'); + putchar('\n'); + + type_res[type_len] = 0; + if (strcmp(type_res, "flash") == 0) + return 0; + else if (strcmp(type_res, "uart") == 0) + return 1; + else if (strcmp(type_res, "tf") == 0) + return 2; + else + printf("cmd [%s] not found\n", type_res); + } +} + +static uint8_t rs_booter_check_key(void) { + printf("booter and flash app load done\n"); + printf("whether enter [booter shell] or not...(press key0 to enter)\n\n"); + + uint8_t enter_boot_delay = 6, enter_shell = 0; + for (uint8_t i = 1; i <= enter_boot_delay; ++i) { + printf("delay %ds...[all %ds]\n", i, enter_boot_delay); + delay_ms(1000); + // if(i == 5) enter_shell = 1; // mock the oper + if (enter_shell) { + printf("\n"); + return enter_shell; + } + } + printf("\n"); + return enter_shell; +} + +void rs_booter(void) { + uint8_t boot_mode = 0; + + if (rs_booter_check_key() != 0U) { + boot_mode = rs_booter_shell(); + } else + printf("no key0 pressed, default "); + + printf("boot mode is [%s]\n\n", boot_mode == 0 ? "FLASH" + : boot_mode == 1 ? "UART" + : boot_mode == 2 ? "TF" + : "NONE"); + + printf("mem self test start...\n"); + ip_psram_boot(); + printf("mem self test done\n"); +} diff --git a/crt/src/service/shell.c b/crt/src/service/shell.c new file mode 100644 index 00000000..be3c1a4d --- /dev/null +++ b/crt/src/service/shell.c @@ -0,0 +1,815 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +// #include +#ifdef IP_MDD +#include +#endif + +static char sh_argv_buf[RS_SHELL_MAX_ARGC][RS_SHELL_MAX_COMMAND_LENGTH + 1U]; +static char *sh_argv[RS_SHELL_MAX_ARGC + 1U]; +static uint8_t sh_argc; +static rs_shell_command_t sh_cmd_list[RS_SHELL_MAX_COMMANDS]; +static uint8_t sh_cmd_len; +static char sh_history_table[RS_SHELL_MAX_HISTORY][RS_SHELL_MAX_COMMAND_LENGTH + 1U]; +static uint8_t sh_history_idx; +static char fat32_pwd[RS_SHELL_MAX_PATH]; +static char lsr_pwd[RS_SHELL_MAX_PATH]; +static uint32_t file_buffer_words[RS_SHELL_MAX_BUFFER / sizeof(uint32_t)]; +static uint8_t *const file_buffer = (uint8_t *)file_buffer_words; + +rs_status_t rs_shell_register(const char *name, const char *info, bool batch, + rs_shell_handler_t handler) { + if ((name == NULL) || (handler == NULL) || (name[0] == '\0')) { + return RS_EINVAL; + } + if (sh_cmd_len >= RS_SHELL_MAX_COMMANDS) { + return RS_ENOSPC; + } + for (uint8_t index = 0U; index < sh_cmd_len; ++index) { + if (strcmp(name, sh_cmd_list[index].name) == 0) { + return RS_EINVAL; + } + } + + sh_cmd_list[sh_cmd_len] = (rs_shell_command_t){name, info, batch, handler}; + ++sh_cmd_len; + return RS_OK; +} + +static rs_status_t rs_shell_split_command(char *command) { + char *cursor; + + if (command == NULL) { + return RS_EINVAL; + } + rs_trim_whitespace(command); + if (command[0] == '\0') { + return RS_EINVAL; + } + + sh_argc = 0U; + cursor = command; + while (*cursor != '\0') { + char *dst; + size_t length = 0U; + bool quoted = false; + + while ((*cursor == ' ') || (*cursor == '\t')) { + ++cursor; + } + if (*cursor == '\0') { + break; + } + if (sh_argc >= RS_SHELL_MAX_ARGC) { + return RS_ENOSPC; + } + + dst = sh_argv_buf[sh_argc]; + while (*cursor != '\0') { + if (*cursor == '"') { + quoted = !quoted; + ++cursor; + continue; + } + if (!quoted && ((*cursor == ' ') || (*cursor == '\t'))) { + break; + } + if (length >= RS_SHELL_MAX_COMMAND_LENGTH) { + return RS_ENOSPC; + } + dst[length++] = *cursor++; + } + if (quoted) { + return RS_EFORMAT; + } + dst[length] = '\0'; + sh_argv[sh_argc] = dst; + ++sh_argc; + } + + sh_argv[sh_argc] = NULL; + return (sh_argc == 0U) ? RS_EINVAL : RS_OK; +} + +static void rs_shell_parse_and_exec(char *command) { + const rs_status_t split_status = rs_shell_split_command(command); + + if (split_status != RS_OK) { + printf("shell input error: %d\n", split_status); + return; + } + + for (uint8_t index = 0U; index < sh_cmd_len; ++index) { + if (strcmp(sh_argv[0], sh_cmd_list[index].name) == 0) { + sh_cmd_list[index].handler((int)sh_argc, sh_argv); + return; + } + } + printf("cmd: [%s] not found\n", sh_argv[0]); +} + +static rs_status_t rs_shell_load_file(const char *path, bool header_only, uint32_t *bytes_read) { + FIL ff_obj; + FRESULT ff_res; + UINT read_count = 0U; + FSIZE_t rd_len = 0; + + if ((path == NULL) || (bytes_read == NULL)) { + return RS_EINVAL; + } + *bytes_read = 0U; + ff_res = f_open(&ff_obj, path, FA_READ); + if (ff_res != FR_OK) { + return RS_EIO; + } + + // printf("open file is right!\n"); + printf("stat: %d\n", ff_obj.obj.stat); + printf("size: %d bytes\n", ff_obj.obj.objsize); + + if (header_only) { + rd_len = (ff_obj.obj.objsize < 64U) ? ff_obj.obj.objsize : 64U; + } else { + if (ff_obj.obj.objsize > RS_SHELL_MAX_BUFFER) { + printf("file size is larger than the buffer size\n"); + f_close(&ff_obj); + return RS_ENOSPC; + } + rd_len = ff_obj.obj.objsize; + } + + ff_res = f_read(&ff_obj, file_buffer, rd_len, &read_count); + f_close(&ff_obj); + if ((ff_res != FR_OK) || (read_count != rd_len)) { + return RS_EIO; + } + *bytes_read = read_count; + return RS_OK; +} + +static void rs_shell_help(int argc, char **argv) { + (void)argc; + (void)argv; + for (uint8_t i = 0U; i < sh_cmd_len; ++i) { + printf("cmd: %-10s --- %s\n", sh_cmd_list[i].name, sh_cmd_list[i].info); + } +} + +static void rs_shell_history_list(int argc, char **argv) { + (void)argc; + (void)argv; + for (uint8_t i = 0U; i < sh_history_idx; ++i) { + printf("%3d %s\n", i, sh_history_table[i]); + } +} + +static void rs_shell_welcome(void) { + printf("================================\n"); + printf(" retroSoC Shell \n"); + printf("================================\n"); +} + +void rs_shell_init(void) { + sh_cmd_len = 0; + sh_history_idx = 0; + for (uint8_t i = 0U; i < RS_SHELL_MAX_ARGC; ++i) { + sh_argv[i] = sh_argv_buf[i]; + } + sh_argv[RS_SHELL_MAX_ARGC] = NULL; + (void)rs_strlcpy(fat32_pwd, "/", sizeof(fat32_pwd)); +} + +static rs_status_t rs_shell_mount_fs(FATFS *fs) { + FRESULT ff_res; + ff_res = f_mount(fs, "0:", 1); + switch (ff_res) { + case FR_NO_FILESYSTEM: + printf("[fatfs] no filesystem\n"); + return RS_EIO; + case FR_OK: + printf("[fatfs] mount done\n"); + return RS_OK; + default: + printf("[fatfs] filesystem mount fail\n"); + return RS_EIO; + } +} + +static void rs_shell_fat32_ls_cmd(int argc, char **argv) { + char dir_path[RS_SHELL_MAX_PATH]; + + printf("argc: %d ff_pwd: %s\n", argc, fat32_pwd); + if (argc == 1) { + (void)rs_strlcpy(dir_path, fat32_pwd, sizeof(dir_path)); + } else if (argc == 2) { + if (rs_strlcpy(dir_path, argv[1], sizeof(dir_path)) >= sizeof(dir_path)) { + printf("path is too long\n"); + return; + } + (void)rs_strlcpy(fat32_pwd, dir_path, sizeof(fat32_pwd)); + } else { + printf("[error] argv:"); + for (uint8_t i = 0; i < argc; ++i) { + printf(" %s", argv[i]); + } + printf("\n"); + return; + } + + FRESULT ff_res; + DIR ff_dir; + FILINFO ff_info; + int file_num, dir_num; + + ff_res = f_opendir(&ff_dir, dir_path); + if (ff_res == FR_OK) { + file_num = dir_num = 0; + for (;;) { + ff_res = f_readdir(&ff_dir, &ff_info); /* Read a directory item */ + if (ff_res != FR_OK) { + printf("directory read failed: %d\n", ff_res); + break; + } + if (ff_info.fname[0] == 0) { + break; + } + if (ff_info.fattrib & AM_DIR) { /* It is a directory */ + printf(" %s/\n", ff_info.fname); + ++dir_num; + } else { /* It is a file */ + printf("%10u %s\n", ff_info.fsize, ff_info.fname); + ++file_num; + } + } + f_closedir(&ff_dir); + printf("%d dirs, %d files.\n", dir_num, file_num); + } else { + printf("Failed to open \"%s\". (%u)\n", dir_path, ff_res); + } +} + +static FRESULT rs_shell_fat32_lsr_walk(void) { + FRESULT ff_res; + DIR ff_dir; + UINT i; + FILINFO ff_info; + + ff_res = f_opendir(&ff_dir, lsr_pwd); /* Open the directory */ + if (ff_res == FR_OK) { + for (;;) { + ff_res = f_readdir(&ff_dir, &ff_info); /* Read a directory item */ + if ((ff_res != FR_OK) || (ff_info.fname[0] == 0)) { + break; + } + if (ff_info.fattrib & AM_DIR) { /* The item is a directory */ + i = strlen(lsr_pwd); + if ((i + 1U + strlen(ff_info.fname)) >= sizeof(lsr_pwd)) { + ff_res = FR_INVALID_NAME; + break; + } + (void)rs_strlcat(lsr_pwd, "/", sizeof(lsr_pwd)); + (void)rs_strlcat(lsr_pwd, ff_info.fname, sizeof(lsr_pwd)); + ff_res = rs_shell_fat32_lsr_walk(); /* Enter the directory */ + if (ff_res != FR_OK) + break; + lsr_pwd[i] = 0; + } else { /* The item is a file. */ + printf("%s/%s\n", lsr_pwd, ff_info.fname); + } + } + f_closedir(&ff_dir); + } + return ff_res; +} + +static void rs_shell_fat32_lsr_cmd(int argc, char **argv) { + FRESULT ff_res; + + (void)argv; + if (argc != 1) { + printf("lsr cmd param error\n"); + return; + } + (void)rs_strlcpy(lsr_pwd, fat32_pwd, sizeof(lsr_pwd)); + ff_res = rs_shell_fat32_lsr_walk(); + if (ff_res != FR_OK) { + printf("lsr failed: %d\n", ff_res); + } +} + +static void rs_shell_fat32_cd_cmd(int argc, char **argv) { + if (argc != 2) { + printf("[cd] cmd param error\n"); + return; + } + + FRESULT ff_res; + TCHAR dir_path[RS_SHELL_MAX_PATH]; + if (strcmp(argv[1], "..") == 0) { + if (strcmp(fat32_pwd, "/") == 0) + return; + + rs_remove_suffix(dir_path, sizeof(dir_path), fat32_pwd, '/'); + } else if (argv[1][0] == '/') { + if (rs_strlcpy(dir_path, argv[1], sizeof(dir_path)) >= sizeof(dir_path)) { + printf("path is too long\n"); + return; + } + } else { + if ((rs_strlcpy(dir_path, fat32_pwd, sizeof(dir_path)) >= sizeof(dir_path)) || + (rs_strlcat(dir_path, "/", sizeof(dir_path)) >= sizeof(dir_path)) || + (rs_strlcat(dir_path, argv[1], sizeof(dir_path)) >= sizeof(dir_path))) { + printf("path is too long\n"); + return; + } + } + + ff_res = f_chdir(dir_path); + if (ff_res != FR_OK) { + printf("ch cmd exec error\n"); + } else { + (void)rs_strlcpy(fat32_pwd, dir_path, sizeof(fat32_pwd)); + } +} + +static void rs_shell_fat32_mv_cmd(int argc, char **argv) { + if (argc != 3) { + printf("[mv] cmd param error\n"); + return; + } + + FRESULT ff_res; + ff_res = f_rename(argv[1], argv[2]); + if (ff_res != FR_OK) + printf("error: %d\n", ff_res); +} + +static void rs_shell_fat32_pwd_cmd(int argc, char **argv) { + (void)argc; + (void)argv; + + FRESULT ff_res; + TCHAR dir_path[RS_SHELL_MAX_PATH]; + + ff_res = f_getcwd(dir_path, RS_SHELL_MAX_PATH); + if (ff_res == FR_OK) { + printf("%s\n", dir_path); + (void)rs_strlcpy(fat32_pwd, dir_path, sizeof(fat32_pwd)); + } +} + +static void rs_shell_fat32_mkdir_cmd(int argc, char **argv) { + if (argc != 2) { + printf("[mkdir] cmd param error\n"); + return; + } + + FRESULT ff_res; + ff_res = f_mkdir(argv[1]); + if (ff_res != FR_OK) + printf("error: %d\n", ff_res); +} + +static void rs_shell_fat32_rm_cmd(int argc, char **argv) { + if (argc != 2) { + printf("[rm] cmd param error\n"); + return; + } + + FRESULT ff_res; + ff_res = f_unlink(argv[1]); + if (ff_res != FR_OK) + printf("error: %d\n", ff_res); +} + +static void rs_shell_fat32_chmod_cmd(int argc, char **argv) { + if (argc != 2) { + printf("[chmod] cmd param error\n"); + return; + } + + FRESULT ff_res; + ff_res = f_chmod(argv[1], AM_RDO, AM_RDO); + if (ff_res != FR_OK) + printf("error: %d\n", ff_res); +} + +static void rs_shell_fat32_touch_cmd(int argc, char **argv) { + int32_t year; + int32_t month; + int32_t day; + int32_t hour; + int32_t minute; + int32_t second; + + if (argc != 8) { + printf("[touch] cmd param error\n"); + return; + } + if ((rs_strtoi32(argv[2], &year) != RS_OK) || (rs_strtoi32(argv[3], &month) != RS_OK) || + (rs_strtoi32(argv[4], &day) != RS_OK) || (rs_strtoi32(argv[5], &hour) != RS_OK) || + (rs_strtoi32(argv[6], &minute) != RS_OK) || (rs_strtoi32(argv[7], &second) != RS_OK) || + (year < 1980) || (year > 2107) || (month < 1) || (month > 12) || (day < 1) || (day > 31) || + (hour < 0) || (hour > 23) || (minute < 0) || (minute > 59) || (second < 0) || + (second > 59)) { + printf("[touch] invalid timestamp\n"); + return; + } + + FRESULT ff_res; + FILINFO ff_info = {0}; + // touch file year month day hour min sec + ff_info.fdate = + (WORD)(((uint32_t)(year - 1980) << 9U) | ((uint32_t)month << 5U) | (uint32_t)day); + ff_info.ftime = + (WORD)(((uint32_t)hour << 11U) | ((uint32_t)minute << 5U) | ((uint32_t)second / 2U)); +#if FF_FS_CRTIME + ff_info.crdate = 0; /* Do not change created time in this code */ +#endif + + ff_res = f_utime(argv[1], &ff_info); + if (ff_res != FR_OK) + printf("error: %d\n", ff_res); +} + +static void rs_shell_fat32_find_cmd(int argc, char **argv) { + if (argc != 2 && argc != 3) { + printf("find cmd param error\n"); + return; + } + + FRESULT ff_res; /* Return value */ + DIR ff_dir; /* Directory object */ + FILINFO ff_info; /* File information */ + + // support blob oper + if (argc == 2) { + ff_res = f_findfirst(&ff_dir, &ff_info, fat32_pwd, argv[1]); + } else if (argc == 3) { + ff_res = f_findfirst(&ff_dir, &ff_info, argv[1], argv[2]); + } + + while (ff_res == FR_OK && ff_info.fname[0]) { /* Repeat while an item is found */ + printf("%s\n", ff_info.fname); /* Print the object name */ + ff_res = f_findnext(&ff_dir, &ff_info); /* Search for next item */ + } + if (ff_res == FR_OK) { + (void)f_closedir(&ff_dir); + } +} + +static void rs_shell_fat32_file_cmd(int argc, char **argv) { + if (argc != 2) { + printf("file cmd param error\n"); + return; + } + + // printf("file name: %s\n", argv[1]); + + FILINFO ff_info; + FRESULT ff_res; + ff_res = f_stat(argv[1], &ff_info); + + switch (ff_res) { + case FR_OK: + printf("[attr]: %c%c%c%c%c ", (ff_info.fattrib & AM_DIR) ? 'D' : '-', + (ff_info.fattrib & AM_RDO) ? 'R' : '-', (ff_info.fattrib & AM_HID) ? 'H' : '-', + (ff_info.fattrib & AM_SYS) ? 'S' : '-', (ff_info.fattrib & AM_ARC) ? 'A' : '-'); + printf("[size]: %lu bytes ", ff_info.fsize); + printf("[date]: %u-%02u-%02u %02u:%02u%02u\n", (ff_info.fdate >> 9) + 1980, + ff_info.fdate >> 5 & 15, ff_info.fdate & 31, ff_info.ftime >> 11, + ff_info.ftime >> 5 & 63, ff_info.ftime * 2); + break; + case FR_NO_FILE: + case FR_NO_PATH: + printf("\"%s\" is not exist.\n", argv[1]); + break; + default: + printf("An error occured. (%d)\n", ff_res); + } +} + +static void rs_shell_fat32_write_cmd(int argc, char **argv) { + // write test.txt asdf.txtxt + if (argc != 3) { + printf("[write] cmd param error\n"); + return; + } + + FIL ff_obj; + FRESULT ff_res; + UINT ff_num; + ff_res = f_open(&ff_obj, argv[1], FA_WRITE | FA_CREATE_ALWAYS); + if (ff_res == FR_OK) { + ff_res = f_write(&ff_obj, argv[2], strlen(argv[2]), &ff_num); + if (ff_res != FR_OK) + printf("error: %d\n", ff_res); + (void)f_close(&ff_obj); + } else { + printf("error: %d\n", ff_res); + } +} + +static void rs_shell_fat32_cat_cmd(int argc, char **argv) { + uint32_t bytes_read; + + if (argc != 2) { + printf("[cat] cmd param error\n"); + return; + } + + if (rs_shell_load_file(argv[1], true, &bytes_read) != RS_OK) { + printf("[cat] unable to read %s\n", argv[1]); + return; + } + printf("file header:\n"); + for (uint32_t offset = 0U; offset < bytes_read; offset += 16U) { + const uint32_t line_length = ((bytes_read - offset) < 16U) ? (bytes_read - offset) : 16U; + for (uint32_t index = 0U; index < line_length; ++index) { + printf("%02x", file_buffer[offset + index]); + if (index + 1U < line_length) { + printf(" "); + } + } + printf("\n"); + } +} + +static void rs_shell_fat32_df_cmd(int argc, char **argv) { + (void)argv; + if (argc != 1) { + printf("[df] cmd param error\n"); + return; + } + + FATFS *fs; + FRESULT ff_res; + DWORD free_clust, free_sect, total_sect; + /* Get volume information and free clusters of drive 1 */ + ff_res = f_getfree("0:", &free_clust, &fs); + if (ff_res != FR_OK) { + printf("error: %d\n", ff_res); + return; + } + + /* Get total sectors and free sectors */ + total_sect = (fs->n_fatent - 2) * fs->csize; + free_sect = free_clust * fs->csize; + + /* Print the free space (assuming 512 bytes/sector) */ + printf("%10lu MiB total drive space.\n%10lu MiB available.\n", total_sect / 2 / 1024, + free_sect / 2 / 1024); +} + +static void rs_shell_fat32_fatlabel_cmd(int argc, char **argv) { + if (argc != 1 && argc != 2) { + printf("[fatlabel] cmd param error\n"); + return; + } + + TCHAR label[24]; + DWORD vsn; + FRESULT ff_res; + if (argc == 1) { + ff_res = f_getlabel("", label, &vsn); + if (ff_res != FR_OK) { + printf("error: %d\n", ff_res); + } else { + printf("Volume Label: %s\n", label); + printf("Volume Serial Number: %lu\n", (unsigned long)vsn); + } + } else if (argc == 2) { + ff_res = f_setlabel(argv[1]); + if (ff_res != FR_OK) + printf("error: %d\n", ff_res); + } +} + +static void rs_shell_app_image_cmd(int argc, char **argv) { + // image: -i -m[0] file.bin + // uint8_t is_info = 1, frame = 0; + if (argc != 2) { + printf("[image] cmd param error\n"); + return; + } + + // for(uint8_t i = 0; i < 64; ++i) printf("file_buffer: %x\n", file_buffer[i]); + + rs_video_info_t video_info; + uint32_t file_size; + uint32_t frame_words; + + if (rs_shell_load_file(argv[1], false, &file_size) != RS_OK) { + printf("[image] unable to read %s\n", argv[1]); + return; + } + if ((rs_video_parse(file_buffer, file_size, &video_info) != RS_OK) || + (video_info.width > LCD_W) || (video_info.height > LCD_H)) { + printf("[image] invalid dimensions\n"); + return; + } + frame_words = video_info.frame_size / sizeof(uint32_t); + + printf("================================\n"); + printf(" image bin file info \n"); + printf("width: %d\n", video_info.width); + printf("height: %d\n", video_info.height); + printf("frame count: %d\n", video_info.frame_count); + printf("================================\n"); + + for (uint32_t frame = 0U; frame < video_info.frame_count; ++frame) { + uint32_t *frame_data = file_buffer_words + (video_info.payload_offset / sizeof(uint32_t)) + + (frame * frame_words); + lcd_fill_image(0U, 0U, (uint16_t)video_info.width, (uint16_t)video_info.height, frame_data); + delay_ms(3000U); + } +} + +// video -i info +static void rs_shell_app_video_cmd(int argc, char **argv) { + (void)argc; + (void)argv; +} + +// audio -i info +static void rs_shell_app_audio_cmd(int argc, char **argv) { + (void)argc; + (void)argv; +} + +// val * 1000 / CPU_FREQ / 1000 / 1000 +// uint32_t my_get_millis(void) { +// return reg_tim1_val / CPU_FREQ / 1000; +// } + +static void rs_shell_app_lvgl_cmd(int argc, char **argv) { + (void)argc; + (void)argv; + + // lv_init(); + // tim1_init(); + // lv_tick_set_cb(my_get_millis); + + // lv_port_disp_init(); + + // lv_obj_t *label = lv_label_create(lv_scr_act()); + // lv_label_set_text(label,"Hello maksyuki!!!"); + // lv_obj_center(label); + + // while(1) { + // lv_timer_handler(); + // delay_ms(5); + // printf("hello\n"); + // } +} + +static void rs_shell_app_arduboy_cmd(int argc, char **argv) { + (void)argc; + (void)argv; +} + +static void rs_shell_app_nes_cmd(int argc, char **argv) { + (void)argc; + (void)argv; +} + +static void rs_shell_app_coremark_cmd(int argc, char **argv) { + (void)argc; + (void)argv; + core_main(); +} + +#ifdef IP_MDD +static void rs_shell_app_userip_cmd(int argc, char **argv) { + if (argc != 1 && argc != 2) { + printf("[userip] cmd param error\n"); + return; + } + + if (argc == 1) { + printf("current user ip id: %03d\n", reg_sysctrl_ipsel); + userip_main(0, NULL); + } else if (argc == 2) { + int32_t user_id; + + if ((rs_strtoi32(argv[1], &user_id) == RS_OK) && (user_id >= 0) && (user_id <= 255)) { + printf("switch to user ip id to [%03d...]\n", user_id); + reg_sysctrl_ipsel = (uint8_t)user_id; + userip_main((int)user_id, NULL); // HACK: + } else { + printf("error use id: %d\n", user_id); + return; + } + } + // userip: list all info/current id +} +#endif + +void rs_shell_launch(void) { + char type_res[RS_SHELL_MAX_COMMAND_LENGTH + 1U]; + char type_ch; + size_t type_len; + + rs_shell_welcome(); + rs_status_t fs_init_state; + FATFS fs; + fs_init_state = rs_shell_mount_fs(&fs); + // register internal cmd + (void)rs_shell_register("help", "help info", false, rs_shell_help); + (void)rs_shell_register("history", "print history list", false, rs_shell_history_list); + (void)rs_shell_register("coremark", "coremark test", false, rs_shell_app_coremark_cmd); +#ifdef IP_MDD + (void)rs_shell_register("userip", "run user ip program", false, rs_shell_app_userip_cmd); +#endif + if (fs_init_state == RS_OK) { + (void)rs_shell_register("ls", "list directory contents", false, rs_shell_fat32_ls_cmd); + (void)rs_shell_register("lsr", "list directory contents recursively", false, + rs_shell_fat32_lsr_cmd); + (void)rs_shell_register("cd", "change directory", false, rs_shell_fat32_cd_cmd); + (void)rs_shell_register("mv", "move/remove files", false, rs_shell_fat32_mv_cmd); + (void)rs_shell_register("pwd", "print current directory", false, rs_shell_fat32_pwd_cmd); + (void)rs_shell_register("mkdir", "make directories", false, rs_shell_fat32_mkdir_cmd); + (void)rs_shell_register("rm", "remove files or directories", false, rs_shell_fat32_rm_cmd); + (void)rs_shell_register("chmod", "change file mode bits", false, rs_shell_fat32_chmod_cmd); + (void)rs_shell_register("touch", "change file timestamps", false, rs_shell_fat32_touch_cmd); + (void)rs_shell_register("find", "search files in directory", false, + rs_shell_fat32_find_cmd); + (void)rs_shell_register("file", "print file info", false, rs_shell_fat32_file_cmd); + (void)rs_shell_register("write", "write string to file", false, rs_shell_fat32_write_cmd); + (void)rs_shell_register("cat", "print file header", false, rs_shell_fat32_cat_cmd); + (void)rs_shell_register("df", "report file system disk space usage", false, + rs_shell_fat32_df_cmd); + (void)rs_shell_register("fatlabel", "set/get filesystem label or volume ID", false, + rs_shell_fat32_fatlabel_cmd); + (void)rs_shell_register("image", "show image frames", false, rs_shell_app_image_cmd); + (void)rs_shell_register("video", "video player", false, rs_shell_app_video_cmd); + (void)rs_shell_register("audio", "audio player", false, rs_shell_app_audio_cmd); + (void)rs_shell_register("lvgl", "show lvgl components", false, rs_shell_app_lvgl_cmd); + (void)rs_shell_register("arduboy", "run arduboy", false, rs_shell_app_arduboy_cmd); + (void)rs_shell_register("nes", "run nes simulator", false, rs_shell_app_nes_cmd); + printf("register cmd num: %d\n", sh_cmd_len); + } + + while (true) { + printf("rs_shell > "); + type_len = 0; + + do { + type_ch = getchar(); + if ((type_ch >= 'a' && type_ch <= 'z') || (type_ch >= 'A' && type_ch <= 'Z') || + (type_ch >= '0' && type_ch <= '9') || type_ch == ' ' || type_ch == '.' || + type_ch == '/' || type_ch == '_' || type_ch == '"' || type_ch == '/' || + type_ch == '*' || type_ch == '-') { + if ((type_len + 1U) >= sizeof(type_res)) { + continue; + } + putchar(type_ch); + type_res[type_len++] = type_ch; + } else if (type_ch == '\b' || type_ch == (char)127) { + if (type_len == 0) + continue; + printf("\b \b"); + type_res[type_len--] = 0; + } else if (type_ch == (char)9) { // tab + printf("tab\n"); + // rs_shell_search_cmd(type_res, type_len); + } + + } while (type_ch != '\n' && type_ch != '\r'); + putchar('\n'); + + type_res[type_len] = 0; + if (sh_history_idx < RS_SHELL_MAX_HISTORY) { + (void)rs_strlcpy(sh_history_table[sh_history_idx++], type_res, + sizeof(sh_history_table[0])); + } else { + for (uint8_t i = 1U; i < RS_SHELL_MAX_HISTORY; ++i) { + (void)rs_strlcpy(sh_history_table[i - 1U], sh_history_table[i], + sizeof(sh_history_table[0])); + } + (void)rs_strlcpy(sh_history_table[sh_history_idx - 1U], type_res, + sizeof(sh_history_table[0])); + } + + rs_shell_parse_and_exec(type_res); + // printf("ff_pwd: %s\n", fat32_pwd); + } +} + +void rs_shell_batch_run(void) { + for (uint8_t i = 0U; i < sh_cmd_len; ++i) { + if (sh_cmd_list[i].batch) { + sh_cmd_list[i].handler(0, NULL); + } + } +} diff --git a/crt/src/system_irq_handler.c b/crt/src/system_irq_handler.c deleted file mode 100644 index 8964f2df..00000000 --- a/crt/src/system_irq_handler.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2019 Nuclei Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// -- Adaptable modifications are redistributed under compatible License -- -// -// Copyright (c) 2023-2026 Yuchi Miao -// retroSoC is licensed under Mulan PSL v2. -// You can use this software according to the terms and conditions of the Mulan PSL v2. -// You may obtain a copy of Mulan PSL v2 at: -// http://license.coscl.org.cn/MulanPSL2 -// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. -// See the Mulan PSL v2 for more details. - -#include -#include -#include -#include - -#define SYSTEM_EXC_MAX_NUM 16 -#define SYSTEM_IRQ_CORE_MAX_NUM 12 -#define SYSTEM_IRQ_EXTN_MAX_NUM 30 - -static unsigned long SystemEXCHandlers[SYSTEM_EXC_MAX_NUM]; -static unsigned long SystemIRQCoreHandlers[SYSTEM_IRQ_CORE_MAX_NUM]; -static unsigned long SystemIRQExtnHandlers[SYSTEM_IRQ_EXTN_MAX_NUM]; - - -typedef void (*EXC_HANDLER) (unsigned long mcause, unsigned long sp); -typedef void (*IRQ_HANDLER) (unsigned long mcause, unsigned long sp); - -/** - * \brief System Default Exception Handler - * \details - * This function provided a default exception handling code for all exception ids. - * By default, It will just print some information for debug, Vendor can customize it according to its requirements. - */ -static void system_default_exc_handler(unsigned long mcause, unsigned long sp) { - printf("Trap in Exception\r\n"); - printf("sp: 0x%x\r\n", sp); - printf("mcause: 0x%x\r\n", mcause); - // printf("mepc : 0x%x\r\n", _READ_CSR(CSR_MEPC)); - // printf("mtval : 0x%x\r\n", _READ_CSR(CSR_MBADADDR)); - while(1); -} - -/** - * \brief System Default Interrupt Handler - * \details - * This function provided a default interrupt handling code for all interrupt ids. - */ -static void system_default_irq_handler(unsigned long mcause, unsigned long sp) { - printf("Trap in Interrupt\r\n"); - printf("sp: 0x%x\r\n", sp); - printf("mcause: 0x%x\r\n", mcause); - // printf("mepc : 0x%x\r\n", _READ_CSR(CSR_MEPC)); - // printf("mtval : 0x%x\r\n", _READ_CSR(CSR_MBADADDR)); -} - -/** - * \brief Initialize all the default core exception handlers - * \details - * The core exception handler for each exception id will be initialized to \ref system_default_exception_handler. - * \note - * Called in \ref _init function, used to initialize default exception handlers for all exception IDs - */ -static void init_system_exception(void) { - for (int i = 0; i < SYSTEM_EXC_MAX_NUM; i++) { - SystemEXCHandlers[i] = (unsigned long)system_default_exc_handler; - } -} - -/** - * \brief Initialize all the default interrupt handlers - * \details - * The interrupt handler for each exception id will be initialized to \ref system_default_interrupt_handler. - * \note - * Called in \ref _init function, used to initialize default interrupt handlers for all interrupt IDs - */ -static void init_system_irq(void) { - for (int i = 0; i < SYSTEM_IRQ_CORE_MAX_NUM; i++) { - SystemIRQCoreHandlers[i] = (unsigned long)system_default_irq_handler; - } - - for (int i = 0; i < SYSTEM_IRQ_EXTN_MAX_NUM; i++) { - SystemIRQExtnHandlers[i] = (unsigned long)system_default_irq_handler; - } -} - -/** - * \brief Register an exception handler for exception code EXCn - * \details - * * For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will be registered into SystemExceptionHandlers[EXCn-1]. - * \param EXCn See \ref EXCn_Type - * \param exc_handler The exception handler for this exception code EXCn - */ -void register_system_exception(uint32_t id, unsigned long exc_handler) { - if (id < SYSTEM_EXC_MAX_NUM) { - SystemEXCHandlers[id] = exc_handler; - } -} - -/** - * \brief Register an core interrupt handler for core interrupt number - * \details - * * For irqn <= 10, it will be registered into SystemCoreInterruptHandlers[irqn-1]. - * \param irqn See \ref IRQn - * \param int_handler The core interrupt handler for this interrupt code irqn - */ -void register_system_core_irq(uint32_t id, unsigned long irq_handler) { - if (id <= SYSTEM_IRQ_CORE_MAX_NUM) { - SystemIRQCoreHandlers[id] = irq_handler; - } -} - -/** - * \brief Register an external interrupt handler for plic external interrupt number - * \details - * * For irqn <= \ref __PLIC_INTNUM, it will be registered into SystemExtInterruptHandlers[irqn-1]. - * \param irqn See \ref IRQn - * \param int_handler The external interrupt handler for this interrupt code irqn - */ -void register_system_extn_irq(uint32_t id, unsigned long irq_handler) { - if (id <= SYSTEM_IRQ_EXTN_MAX_NUM) { - SystemIRQExtnHandlers[id] = irq_handler; - } -} - -/** - * \brief Get an core interrupt handler for core interrupt number - * \param irqn See \ref IRQn - * \return - * The core interrupt handler for this interrupt code irqn - */ -unsigned long get_system_exception(uint32_t id) { - if (id < SYSTEM_EXC_MAX_NUM) { - return SystemEXCHandlers[id]; - } - return 0; -} - -/** - * \brief Get an external interrupt handler for external interrupt number - * \param irqn See \ref IRQn - * \return - * The external interrupt handler for this interrupt code irqn - */ -unsigned long get_system_core_irq(uint32_t id) { - if (id <= SYSTEM_IRQ_CORE_MAX_NUM) { - return SystemIRQCoreHandlers[id]; - } - return 0; -} - -/** - * \brief Get current exception handler for exception code EXCn - * \details - * * For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will return SystemExceptionHandlers[EXCn-1]. - * \param EXCn See \ref EXCn_Type - * \return Current exception handler for exception code EXCn, if not found, return 0. - */ -unsigned long get_system_extn_irq(uint32_t id) { - if (id <= SYSTEM_IRQ_EXTN_MAX_NUM) { - return SystemIRQExtnHandlers[id]; - } - return 0; -} - -/** - * \brief Common trap entry - * \details - * This function provided a command entry for trap. Silicon Vendor could modify - * this template implementation according to requirement. - * \remarks - * - RISCV provided common entry for all types of exception including exception and interrupt. - * This is proposed code template for exception entry function, Silicon Vendor could modify the implementation. - * - If you want to register core exception handler, please use \ref Exception_Register_EXC - * - If you want to register core interrupt handler, please use \ref Interrupt_Register_CoreIRQ - * - If you want to register external interrupt handler, please use \ref Interrupt_Register_ExtIRQ - */ -uint32_t system_trap_handler(unsigned long mcause, unsigned long sp) { - if (mcause & MCAUSE_INTERRUPT) { - IRQ_HANDLER irq_handler = NULL; - uint32_t id = (uint32_t)(mcause & 0X00000fff); - if (id == IRQ_M_EXT) { - printf("extn irq trigger!\n"); - } else { - irq_handler = (IRQ_HANDLER)get_system_core_irq(id); - if (irq_handler != NULL) irq_handler(mcause, sp); - } - return 0; - } else { - EXC_HANDLER exc_handler; - uint32_t id = (uint32_t)(mcause & 0X00000fff); - exc_handler = (EXC_HANDLER)get_system_exception(id); - if (exc_handler != NULL) exc_handler(mcause, sp); - return 0; - } -} - -int32_t register_system_core_irq_factory(uint32_t id, void *handler) -{ - if (id > SYSTEM_IRQ_CORE_MAX_NUM) return -1; - - if (handler != NULL) { - /* register interrupt handler entry to core handlers */ - register_system_core_irq(id, (unsigned long)handler); - } - switch (id) { - case IRQ_M_SOFT: - __enable_sw_irq(); - break; - case IRQ_M_TIMER: - __enable_timer_irq(); - break; - default: - break; - } - - return 0; -} - - -void _premain_init(void) { - // gpio_iof_config(GPIOA, IOF_UART_MASK); - // uart_init(SOC_DEBUG_UART, 115200); - /* Initialize exception default handlers */ - init_system_exception(); - /* Initialize Interrupt default handlers */ - init_system_irq(); - /* Enable MCYCLE & MINSTRET counter */ - __enable_all_counter(); -} diff --git a/crt/ver.py b/crt/ver.py index 6619fa17..24364638 100644 --- a/crt/ver.py +++ b/crt/ver.py @@ -28,7 +28,7 @@ def main() -> int: parser.add_argument("--output", type=Path) args = parser.parse_args() root = args.root.resolve() - output = args.output or root / "crt/inc/socver.h" + output = args.output or root / "crt/include/socver.h" branch = git_value(root, "rev-parse", "--abbrev-ref", "HEAD") commit = git_value(root, "rev-parse", "--short=6", "HEAD") diff --git a/quality/embedded_c_policy.json b/quality/embedded_c_policy.json new file mode 100644 index 00000000..bba9feeb --- /dev/null +++ b/quality/embedded_c_policy.json @@ -0,0 +1,27 @@ +{ + "excluded_prefixes": [ + "app/coremark/coremark-main/", + "app/fatfs/ff16/", + "app/lvgl/lvgl-main/", + "app/middleware/fatfs/ffconf.h", + "app/ports/lvgl/", + "crt/inc/", + "crt/arch/riscv/pico_irq/" + ], + "compatibility_files": [ + "crt/include/retrosoc/lib/string.h", + "crt/src/lib/string.c", + "crt/include/retrosoc/lib/stdlib.h", + "crt/src/lib/stdlib.c" + ], + "forbidden_calls": [ + "strcpy", + "strcat", + "strncpy", + "sprintf", + "vsprintf", + "malloc", + "free", + "atoi" + ] +} diff --git a/rtl/mini/mk/software.mk b/rtl/mini/mk/software.mk index d3b67107..a12e7aec 100644 --- a/rtl/mini/mk/software.mk +++ b/rtl/mini/mk/software.mk @@ -1,145 +1,128 @@ -# software +# Software SDK and application build CROSS ?= riscv32-unknown-elf- -CP = $(CROSS)cpp -CC = $(CROSS)gcc +CP = $(CROSS)cpp +CC = $(CROSS)gcc OBJC = $(CROSS)objcopy DUMP = $(CROSS)objdump -GCC_FLAGS := -Wall -Wextra \ +GCC_FLAGS := -std=gnu11 -Wall -Wextra \ -Wl,-Bstatic,-T,$(LINK_TYPE).lds,--strip-debug -O3 \ - -ffreestanding \ - -nostdlib + -ffreestanding -nostdlib +SW_WARN_FLAGS := -Wformat=2 -Wshadow -Wstrict-prototypes -Wmissing-prototypes \ + -Wcast-align -Werror=implicit-function-declaration \ + -Werror=return-type -Werror=incompatible-pointer-types \ + -Werror=int-conversion -Werror=format -ifeq ($(ISA), RV32E) - ISA_FLAGS := -mabi=ilp32e +ifeq ($(ISA),RV32E) +ISA_FLAGS := -mabi=ilp32e else - ISA_FLAGS := -mabi=ilp32 +ISA_FLAGS := -mabi=ilp32 endif -ifeq ($(ISA), RV32E) - ifeq ($(HAVE_CSR), YES) - ISA_FLAGS += -march=rv32e_zicsr - else - ISA_FLAGS += -march=rv32e - endif -else ifeq ($(ISA), RV32I) - ifeq ($(HAVE_CSR), YES) - ISA_FLAGS += -march=rv32i_zicsr - else - ISA_FLAGS += -march=rv32i - endif -else ifeq ($(ISA), RV32IM) - ifeq ($(HAVE_CSR), YES) - ISA_FLAGS += -march=rv32im_zicsr - else - ISA_FLAGS += -march=rv32im - endif +ifeq ($(ISA),RV32E) +ifeq ($(HAVE_CSR),YES) +ISA_FLAGS += -march=rv32e_zicsr +else +ISA_FLAGS += -march=rv32e +endif +else ifeq ($(ISA),RV32I) +ifeq ($(HAVE_CSR),YES) +ISA_FLAGS += -march=rv32i_zicsr +else +ISA_FLAGS += -march=rv32i +endif +else ifeq ($(ISA),RV32IM) +ifeq ($(HAVE_CSR),YES) +ISA_FLAGS += -march=rv32im_zicsr +else +ISA_FLAGS += -march=rv32im +endif endif DEF_VAL += -DCORE_$(CORE) DEF_VAL += -DIP_$(IP) +DEF_VAL += -DAPP_$(APP) DEF_VAL += -DCOMPILER_NAME='"$(CC)"' -DEF_VAL += -DCOMPILER_CFLAGS='"$(GCC_FLAGS)"' +DEF_VAL += -DCOMPILER_CFLAGS='"$(GCC_FLAGS) $(SW_WARN_FLAGS)"' DEF_VAL += -DCOMPILER_ISA='"$(ISA_FLAGS)"' -DEF_VAL += -DSW_$(PROG_TYPE) -ifeq ($(HAVE_CSR), YES) - DEF_VAL += -DCSR_ENABLE +ifeq ($(HAVE_CSR),YES) +DEF_VAL += -DCSR_ENABLE endif -CFLAGS := $(GCC_FLAGS) -CFLAGS += $(ISA_FLAGS) -CFLAGS += $(DEF_VAL) +CFLAGS := $(GCC_FLAGS) $(SW_WARN_FLAGS) $(ISA_FLAGS) $(DEF_VAL) +CRT_SRCS := $(ROOT_PATH)/crt/arch/riscv/startup.S \ + $(ROOT_PATH)/crt/arch/riscv/libgcc/clzsi2.c \ + $(ROOT_PATH)/crt/arch/riscv/libgcc/divdi3.c \ + $(ROOT_PATH)/crt/arch/riscv/libgcc/ffssi2.c \ + $(ROOT_PATH)/crt/arch/riscv/libgcc/udivdi3.c \ + $(ROOT_PATH)/crt/arch/riscv/libgcc/umoddi3.c \ + $(ROOT_PATH)/crt/src/lib/stdlib.c \ + $(ROOT_PATH)/crt/src/lib/string.c \ + $(ROOT_PATH)/crt/src/lib/console.c \ + $(ROOT_PATH)/crt/src/lib/printf.c \ + $(ROOT_PATH)/crt/src/core/archinfo.c \ + $(ROOT_PATH)/crt/src/service/bench.c \ + $(ROOT_PATH)/crt/src/service/booter.c \ + $(ROOT_PATH)/crt/src/hal/uart.c \ + $(ROOT_PATH)/crt/src/hal/gpio.c \ + $(ROOT_PATH)/crt/src/hal/timer.c \ + $(ROOT_PATH)/crt/src/hal/pwm.c \ + $(ROOT_PATH)/crt/src/hal/rtc.c \ + $(ROOT_PATH)/crt/src/hal/watchdog.c \ + $(ROOT_PATH)/crt/src/hal/crc.c \ + $(ROOT_PATH)/crt/src/hal/rng.c \ + $(ROOT_PATH)/crt/src/hal/advanced_timer.c \ + $(ROOT_PATH)/crt/src/hal/hpuart.c \ + $(ROOT_PATH)/crt/src/hal/ps2.c \ + $(ROOT_PATH)/crt/src/hal/i2c.c \ + $(ROOT_PATH)/crt/src/hal/onewire.c \ + $(ROOT_PATH)/crt/src/hal/dma.c \ + $(ROOT_PATH)/crt/src/hal/lcd.c \ + $(ROOT_PATH)/crt/src/hal/psram.c \ + $(ROOT_PATH)/crt/src/hal/spisd.c \ + $(ROOT_PATH)/crt/src/hal/qspi.c - -TINYLIB_PATH := $(ROOT_PATH)/crt/startup.S \ - $(ROOT_PATH)/crt/src/rs_lib.c \ - $(ROOT_PATH)/crt/src/rs_uart.c \ - $(ROOT_PATH)/crt/src/rs_string.c \ - $(ROOT_PATH)/crt/src/rs_print.c \ - $(ROOT_PATH)/crt/src/rs_printf.c \ - $(ROOT_PATH)/crt/src/rs_gpio.c \ - $(ROOT_PATH)/crt/src/rs_archinfo.c \ - $(ROOT_PATH)/crt/src/rs_rng.c \ - $(ROOT_PATH)/crt/src/rs_tim.c \ - $(ROOT_PATH)/crt/src/rs_pwm.c \ - $(ROOT_PATH)/crt/src/rs_rtc.c \ - $(ROOT_PATH)/crt/src/rs_wdg.c \ - $(ROOT_PATH)/crt/src/rs_crc.c \ - $(ROOT_PATH)/crt/src/rs_advtim.c \ - $(ROOT_PATH)/crt/src/rs_hpuart.c \ - $(ROOT_PATH)/crt/src/rs_ps2.c \ - $(ROOT_PATH)/crt/src/rs_i2c.c \ - $(ROOT_PATH)/crt/src/rs_1wire.c \ - $(ROOT_PATH)/crt/src/rs_dma.c \ - $(ROOT_PATH)/crt/src/rs_lcd.c \ - $(ROOT_PATH)/crt/src/rs_psram.c \ - $(ROOT_PATH)/crt/src/rs_spisd.c \ - $(ROOT_PATH)/crt/src/rs_qspi.c \ - $(ROOT_PATH)/crt/src/rs_bench.c \ - $(ROOT_PATH)/crt/src/rs_booter.c \ - $(ROOT_PATH)/crt/src/main.c - -ifeq ($(HAVE_CSR), YES) -TINYLIB_PATH += $(ROOT_PATH)/crt/system_irq.S -TINYLIB_PATH += $(ROOT_PATH)/crt/src/system_irq_handler.c -TINYLIB_PATH += $(ROOT_PATH)/crt/src/rs_irq.c +ifeq ($(HAVE_CSR),YES) +CRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/system_irq.S +CRT_SRCS += $(ROOT_PATH)/crt/src/core/system_irq_handler.c +CRT_SRCS += $(ROOT_PATH)/crt/src/core/irq.c endif -ifeq ($(PROG_TYPE), FULL) -TINYLIB_PATH += $(ROOT_PATH)/crt/src/rs_sh.c -TINYLIB_PATH += $(ROOT_PATH)/crt/src/rs_i2s.c +APP_SRCS := +APP_INC_DIRS := +APP_MK := $(ROOT_PATH)/app/apps/$(APP)/app.mk + +ifeq ($(wildcard $(APP_MK)),) +$(error Application profile not found: $(APP_MK)) +endif +include $(APP_MK) + +ifneq ($(findstring MDD,$(CORE) $(IP)),) +APP_INC_DIRS += $(MPW_OUTPUT_DIR) endif - -ifeq ($(PROG_TYPE), FULL) -APP_PATH := $(ROOT_PATH)/app/base/src/at24cxx.c \ - $(ROOT_PATH)/app/base/src/pcf8563b.c \ - $(ROOT_PATH)/app/base/src/es8388.c \ - $(ROOT_PATH)/app/base/src/w25q128jvxim.c \ - $(ROOT_PATH)/app/base/src/wav_audio.c \ - $(ROOT_PATH)/app/base/src/video_player.c \ - $(ROOT_PATH)/app/base/src/donut.c +ifneq ($(filter RV32E RV32I,$(ISA)),) +CRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/libgcc/div.S +CRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/libgcc/muldi3.S +CRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/libgcc/mulsi3.c endif INC_PATH := -I$(SW_BUILD_DIR)/include \ - -I$(ROOT_PATH)/crt/inc \ - -I$(ROOT_PATH)/app/base/inc - - -ifneq ($(findstring MDD,$(CORE) $(IP)),) -INC_PATH += -I$(MPW_OUTPUT_DIR) -endif - - -ifeq ($(PROG_TYPE), FULL) -# extern app -include $(ROOT_PATH)/app/userip/userip.mk -include $(ROOT_PATH)/app/fatfs/fatfs.mk -include $(ROOT_PATH)/app/coremark/coremark.mk -# include $(ROOT_PATH)/app/lvgl/lvgl.mk -endif - -SRC_PATH := $(TINYLIB_PATH) -SRC_PATH += $(APP_PATH) - -ifneq ($(filter RV32E RV32I,$(ISA)),) - SRC_PATH += $(ROOT_PATH)/crt/libgcc/div.S - SRC_PATH += $(ROOT_PATH)/crt/libgcc/muldi3.S - SRC_PATH += $(ROOT_PATH)/crt/libgcc/mulsi3.c -endif - -LDS_PATH := $(ROOT_PATH)/crt/lds/$(LINK_TYPE).lds + -I$(ROOT_PATH)/crt/include \ + $(addprefix -I,$(APP_INC_DIRS)) +SRC_PATH := $(CRT_SRCS) $(APP_SRCS) +LDS_PATH := $(ROOT_PATH)/crt/linker/$(LINK_TYPE).lds VERSION_HEADER := $(SW_BUILD_DIR)/include/socver.h FIRMWARE_ELF := $(SW_BUILD_DIR)/firmware ASM_FIRMWARE_NAME ?= retrosoc_asm -SW_HEADERS := $(shell find $(ROOT_PATH)/crt/inc $(ROOT_PATH)/app -type f \ +SW_HEADERS := $(shell find $(ROOT_PATH)/crt/include $(ROOT_PATH)/app -type f \ \( -name '*.h' -o -name '*.hpp' \) 2>/dev/null) $(VERSION_HEADER): FORCE_VERSION $(ROOT_PATH)/crt/ver.py $(ROOT_PATH)/crt/ver.tmpl - python3 $(ROOT_PATH)/crt/ver.py --root $(ROOT_PATH) \ - --output $@ + @mkdir -p $(dir $@) + python3 $(ROOT_PATH)/crt/ver.py --root $(ROOT_PATH) --output $@ FORCE_VERSION: diff --git a/scripts/check_c_warnings.py b/scripts/check_c_warnings.py new file mode 100644 index 00000000..34d8fec7 --- /dev/null +++ b/scripts/check_c_warnings.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +"""Reject compiler warnings emitted from self-owned embedded C sources.""" + +from __future__ import annotations + +import argparse +import json +import re +from pathlib import Path + + +ANSI_RE = re.compile(r"\x1b\[[0-9;]*m") +WARNING_RE = re.compile( + r"^(?P.+?\.(?:c|h)):(?P\d+)(?::\d+)?: warning: (?P.+)$" +) + + +def excluded_prefixes(root: Path) -> list[str]: + policy_path = root / "quality" / "embedded_c_policy.json" + policy = json.loads(policy_path.read_text(encoding="utf-8")) + return [str(prefix) for prefix in policy["excluded_prefixes"]] + + +def self_owned_warnings(root: Path, output: str) -> list[str]: + prefixes = excluded_prefixes(root) + warnings: list[str] = [] + + for raw_line in output.splitlines(): + line = ANSI_RE.sub("", raw_line) + match = WARNING_RE.match(line) + if match is None: + continue + path = Path(match.group("path")) + absolute_path = path if path.is_absolute() else root / path + try: + relative_path = absolute_path.resolve().relative_to(root.resolve()).as_posix() + except ValueError: + continue + if any(relative_path.startswith(prefix) for prefix in prefixes): + continue + warnings.append( + f"{relative_path}:{match.group('line')}: warning: {match.group('message')}" + ) + return warnings + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--root", type=Path, required=True) + parser.add_argument("--log", type=Path, required=True) + args = parser.parse_args() + + root = args.root.resolve() + warnings = self_owned_warnings(root, args.log.read_text(encoding="utf-8", errors="replace")) + for warning in warnings: + print(warning) + return int(bool(warnings)) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/check_embedded_c.py b/scripts/check_embedded_c.py new file mode 100644 index 00000000..ab37fb25 --- /dev/null +++ b/scripts/check_embedded_c.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +"""Check the self-owned embedded C surface without scanning vendored code.""" + +from __future__ import annotations + +import argparse +import json +import re +import shutil +import subprocess +import sys +from pathlib import Path + + +SOURCE_SUFFIXES = {".c", ".h"} +TINY_TOKEN = re.compile(r"\btiny[a-zA-Z0-9_]*\b", re.IGNORECASE) +LEGACY_INCLUDE = re.compile(r"#\s*include\s*[<\"](?:rs_|tiny)", re.IGNORECASE) + + +def load_policy(root: Path) -> dict[str, object]: + path = root / "quality" / "embedded_c_policy.json" + with path.open(encoding="utf-8") as policy_file: + return json.load(policy_file) + + +def is_excluded(relative_path: str, prefixes: list[str]) -> bool: + return any(relative_path.startswith(prefix) for prefix in prefixes) + + +def embedded_c_files(root: Path, policy: dict[str, object]) -> list[Path]: + prefixes = [str(prefix) for prefix in policy["excluded_prefixes"]] + files: list[Path] = [] + for source_root in (root / "crt", root / "app"): + if not source_root.exists(): + continue + for path in source_root.rglob("*"): + if not path.is_file() or path.suffix not in SOURCE_SUFFIXES: + continue + relative_path = path.relative_to(root).as_posix() + if not is_excluded(relative_path, prefixes): + files.append(path) + return sorted(files) + + +def format_issues(path: Path) -> list[str]: + data = path.read_bytes() + issues: list[str] = [] + if b"\r" in data: + issues.append("contains CR line endings") + if data and not data.endswith(b"\n"): + issues.append("does not end with a newline") + + for line_number, raw_line in enumerate(data.splitlines(), start=1): + if raw_line.rstrip(b" \t") != raw_line: + issues.append(f"line {line_number}: trailing whitespace") + if b"\t" in raw_line: + issues.append(f"line {line_number}: tab indentation is not allowed") + return issues + + +def policy_issues(root: Path, path: Path, policy: dict[str, object]) -> list[str]: + relative_path = path.relative_to(root).as_posix() + compatibility_files = {str(item) for item in policy["compatibility_files"]} + forbidden_calls = "|".join(str(item) for item in policy["forbidden_calls"]) + forbidden_call = re.compile(rf"\b(?:{forbidden_calls})\s*\(") + text = path.read_text(encoding="utf-8") + issues: list[str] = [] + + if TINY_TOKEN.search(text): + issues.append("contains a retired tiny-prefixed identifier or label") + if LEGACY_INCLUDE.search(text): + issues.append("contains a retired legacy include path") + if relative_path not in compatibility_files and forbidden_call.search(text): + issues.append("uses a banned unsafe C library call") + return issues + + +def print_issues(root: Path, files: list[Path], callback: object) -> int: + count = 0 + for path in files: + for issue in callback(path): + print(f"{path.relative_to(root)}: {issue}") + count += 1 + return count + + +def run_clang_format(files: list[Path], formatter: str) -> int: + executable = shutil.which(formatter) + if executable is None: + print(f"clang-format executable not found: {formatter}", file=sys.stderr) + return 1 + subprocess.run([executable, "-i", *(str(path) for path in files)], check=True) + return 0 + + +def check_clang_format(files: list[Path], formatter: str) -> int: + executable = shutil.which(formatter) + if executable is None: + print(f"clang-format executable not found: {formatter}", file=sys.stderr) + return 1 + result = subprocess.run( + [executable, "--dry-run", "--Werror", *(str(path) for path in files)], + check=False, + ) + return result.returncode + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--root", type=Path, required=True) + parser.add_argument("--format-check", action="store_true") + parser.add_argument("--clang-format-check", action="store_true") + parser.add_argument("--policy-check", action="store_true") + parser.add_argument("--apply-format", action="store_true") + parser.add_argument("--clang-format", default="clang-format") + args = parser.parse_args() + + if not (args.format_check or args.clang_format_check or args.policy_check or args.apply_format): + parser.error("select a format, policy, or apply action") + + root = args.root.resolve() + policy = load_policy(root) + files = embedded_c_files(root, policy) + failures = 0 + if args.format_check: + failures += print_issues(root, files, format_issues) + if args.policy_check: + failures += print_issues( + root, + files, + lambda path: policy_issues(root, path, policy), + ) + if args.clang_format_check: + failures += check_clang_format(files, args.clang_format) + if args.apply_format: + return run_clang_format(files, args.clang_format) + return 1 if failures else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/regress.py b/scripts/regress.py index bc06b3be..2278c3e4 100644 --- a/scripts/regress.py +++ b/scripts/regress.py @@ -4,11 +4,18 @@ from __future__ import annotations import argparse import subprocess +import sys from pathlib import Path +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT)) + +from scripts.check_c_warnings import self_owned_warnings # noqa: E402 + PR_COMMANDS = ( ("configs/ci/hazard3-rv32im-ihp130.mk", ("firmware",)), + ("configs/ci/hazard3-rv32im-ihp130-shell.mk", ("firmware",)), ("configs/ci/mdd-rv32im-ihp130.mk", ("SIMU=VERILATOR", "firmware", "sim")), ("configs/ci/hazard3-rv32im-ihp130.mk", ("SIMU=VERILATOR", "sim")), ("configs/ci/hazard3-rv32im-ihp130.mk", ("SIMU=IVERILOG", "RTL_SIM_TIMEOUT=5200000", "sim-asm")), @@ -27,6 +34,24 @@ PR_PROFILES = ( NIGHTLY_PROFILES = PR_PROFILES + ("configs/nightly/picorv32-rv32im-ihp130.mk",) +def run_command(command: list[str], root: Path, capture_output: bool) -> str: + if not capture_output: + subprocess.run(command, cwd=root, check=True) + return "" + + result = subprocess.run( + command, + cwd=root, + check=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + sys.stdout.write(result.stdout) + result.check_returncode() + return result.stdout + + def main() -> int: parser = argparse.ArgumentParser(description="Run a supported retroSoC regression suite") parser.add_argument("--root", type=Path, required=True) @@ -39,7 +64,12 @@ def main() -> int: command = ["make", f"CONFIG={profile}", *values] print("+ " + " ".join(command), flush=True) if not args.dry_run: - subprocess.run(command, cwd=args.root, check=True) + output = run_command(command, args.root, "firmware" in values) + warnings = self_owned_warnings(args.root, output) + if warnings: + print("self-owned C compiler warnings:", flush=True) + print("\n".join(warnings), flush=True) + return 1 for profile in profiles: command = [ "make", diff --git a/scripts/run_c_tests.py b/scripts/run_c_tests.py new file mode 100644 index 00000000..b6256aa6 --- /dev/null +++ b/scripts/run_c_tests.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""Build and run host tests for deterministic SDK utilities.""" + +from __future__ import annotations + +import argparse +import shutil +import subprocess +import tempfile +from pathlib import Path + + +TEST_SOURCES = ( + "crt/arch/riscv/libgcc/clzsi2.c", + "crt/arch/riscv/libgcc/divdi3.c", + "crt/arch/riscv/libgcc/ffssi2.c", + "crt/arch/riscv/libgcc/udivdi3.c", + "crt/arch/riscv/libgcc/umoddi3.c", + "crt/src/lib/printf.c", + "crt/src/lib/stdlib.c", + "crt/src/lib/string.c", + "app/media/src/video_player.c", + "app/media/src/wav_audio.c", + "tests/c/test_runtime.c", +) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--root", type=Path, required=True) + parser.add_argument("--cc", default="clang") + args = parser.parse_args() + + compiler = shutil.which(args.cc) + if compiler is None: + raise SystemExit(f"host C compiler not found: {args.cc}") + + root = args.root.resolve() + with tempfile.TemporaryDirectory(prefix="retrosoc-c-tests-") as temporary_directory: + executable = Path(temporary_directory) / "runtime_tests" + command = [ + compiler, + "-std=c11", + "-Wall", + "-Wextra", + "-Werror", + "-fno-builtin", + "-I", + str(root / "crt/include"), + "-I", + str(root / "app/media/include"), + "-o", + str(executable), + *(str(root / source) for source in TEST_SOURCES), + ] + subprocess.run(command, check=True) + subprocess.run([str(executable)], check=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/c/test_runtime.c b/tests/c/test_runtime.c new file mode 100644 index 00000000..6313a833 --- /dev/null +++ b/tests/c/test_runtime.c @@ -0,0 +1,213 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEST_STORAGE_ADDRESS ((uintptr_t)0x1000U) + +int __clzsi2(unsigned int value); +long long __divdi3(long long dividend, long long divisor); +int __ffssi2(unsigned int value); +unsigned long long __udivdi3(unsigned long long dividend, unsigned long long divisor); +unsigned long long __umoddi3(unsigned long long dividend, unsigned long long divisor); + +static uint8_t storage[32]; +static uint32_t image_call_count; + +void putch(char ch) +{ + (void)ch; +} + +void lcd_fill_image(uint16_t x_start, + uint16_t y_start, + uint16_t x_end, + uint16_t y_end, + uint32_t *data) +{ + (void)x_start; + (void)y_start; + (void)x_end; + (void)y_end; + (void)data; + ++image_call_count; +} + +rs_status_t rs_spisd_read_bytes(void *buffer, size_t byte_count, uintptr_t address) +{ + size_t offset; + + if ((buffer == NULL) || (address < TEST_STORAGE_ADDRESS)) { + return RS_EINVAL; + } + offset = (size_t)(address - TEST_STORAGE_ADDRESS); + if (byte_count > (sizeof(storage) - offset)) { + return RS_EIO; + } + for (size_t index = 0U; index < byte_count; ++index) { + ((uint8_t *)buffer)[index] = storage[offset + index]; + } + return RS_OK; +} + +static rs_status_t test_reader_read(void *context, + uint32_t offset, + void *buffer, + size_t byte_count) +{ + const uint8_t *bytes = context; + + if ((bytes == NULL) || (buffer == NULL)) { + return RS_EINVAL; + } + for (size_t index = 0U; index < byte_count; ++index) { + ((uint8_t *)buffer)[index] = bytes[offset + index]; + } + return RS_OK; +} + +static int test_string_helpers(void) +{ + char buffer[8] = {'x', '\0'}; + int32_t value; + + if (strncpy(buffer, "z", 0U) != buffer || buffer[0] != 'x') { + return 1; + } + if (strncmp("left", "right", 0U) != 0) { + return 2; + } + if (rs_strlcpy(buffer, "abcdefghi", sizeof(buffer)) != 9U || + strcmp(buffer, "abcdefg") != 0) { + return 3; + } + if (rs_strlcat(buffer, "x", sizeof(buffer)) != 8U || + strcmp(buffer, "abcdefg") != 0) { + return 4; + } + if (rs_strtoi32("-2147483648", &value) != RS_OK || value != INT32_MIN || + rs_strtoi32("2147483648", &value) != RS_EFORMAT || + rs_strtoi32("12x", &value) != RS_EFORMAT) { + return 5; + } + return 0; +} + +static int test_formatter(void) +{ + char buffer[32]; + + if (rs_snprintf(buffer, sizeof(buffer), "%#08x:%lld:%zu", 0x2AU, -42LL, + (size_t)7U) != 14 || strcmp(buffer, "0x00002a:-42:7") != 0) { + return 1; + } + if (rs_snprintf(buffer, 4U, "abcdef") != 6 || strcmp(buffer, "abc") != 0) { + return 2; + } + if (rs_snprintf(NULL, 0U, "value=%llu", UINT64_MAX) != 26) { + return 3; + } + if (rs_snprintf(buffer, sizeof(buffer), "%p", (void *)(uintptr_t)0x1234U) != 6 || + strcmp(buffer, "0x1234") != 0) { + return 4; + } + return 0; +} + +static int test_compiler_helpers(void) +{ + if ((__clzsi2(0U) != 32) || (__clzsi2(1U) != 31) || (__ffssi2(0U) != 0) || + (__ffssi2(1U) != 1) || (__ffssi2(0x10U) != 5)) { + return 1; + } + if ((__udivdi3(UINT64_MAX, 3U) != 6148914691236517205ULL) || + (__umoddi3(UINT64_MAX, 3U) != 0U) || + (__udivdi3(UINT64_MAX, UINT64_MAX) != 1U) || + (__umoddi3(100U, 7U) != 2U) || (__divdi3(-100LL, 7LL) != -14LL)) { + return 2; + } + return 0; +} + +static int test_wait_helper(void) +{ + volatile uint32_t value = 0x30U; + + if (rs_wait_mask(&value, 0x30U, 0x30U, 1U) != RS_OK || + rs_wait_mask(&value, 0x40U, 0x40U, 1U) != RS_ETIMEOUT || + rs_wait_mask(NULL, 1U, 1U, 1U) != RS_EINVAL || + rs_wait_value(&value, 0x30U, 1U) != RS_OK || + rs_wait_not_value(&value, 0U, 1U) != RS_OK || + rs_wait_not_value(&value, 0x30U, 1U) != RS_ETIMEOUT) { + return 1; + } + return 0; +} + +static int test_wav_parser(void) +{ + static const uint8_t wav[] = { + 'R', 'I', 'F', 'F', 40U, 0U, 0U, 0U, 'W', 'A', 'V', 'E', + 'f', 'm', 't', ' ', 16U, 0U, 0U, 0U, 1U, 0U, 1U, 0U, + 0x40U, 0x1FU, 0U, 0U, 0x80U, 0x3EU, 0U, 0U, 2U, 0U, 16U, 0U, + 'd', 'a', 't', 'a', 4U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, + }; + rs_wav_info_t info; + const rs_wav_reader_t reader = {test_reader_read, (void *)wav, sizeof(wav)}; + + if (rs_wav_parse(&reader, &info) != RS_OK || info.sample_rate != 8000U || + info.block_align != 2U || info.data_offset != 44U || info.data_size != 4U) { + return 1; + } + if (rs_wav_parse(&(rs_wav_reader_t){test_reader_read, (void *)wav, 12U}, &info) != + RS_EFORMAT) { + return 2; + } + return 0; +} + +static int test_video_parser(void) +{ + rs_video_info_t info; + + (void)memset(storage, 0, sizeof(storage)); + storage[0] = 2U; + storage[4] = 2U; + storage[8] = 1U; + if (rs_video_parse(storage, 24U, &info) != RS_OK || info.frame_size != 8U || + rs_video_parse(storage, 16U, &info) != RS_EFORMAT) { + return 1; + } + image_call_count = 0U; + if (rs_video_show_spisd(TEST_STORAGE_ADDRESS, 24U) != RS_OK || image_call_count != 1U) { + return 2; + } + return 0; +} + +int main(void) +{ + const int results[] = { + test_string_helpers(), + test_formatter(), + test_compiler_helpers(), + test_wait_helper(), + test_wav_parser(), + test_video_parser(), + }; + + for (size_t index = 0U; index < (sizeof(results) / sizeof(results[0])); ++index) { + if (results[index] != 0) { + return (int)(index + 1U); + } + } + return 0; +} diff --git a/tests/test_script_tools.py b/tests/test_script_tools.py index b426efa4..ffc5b031 100644 --- a/tests/test_script_tools.py +++ b/tests/test_script_tools.py @@ -22,6 +22,7 @@ sys.path.insert(0, str(FILELIST_SCRIPT_DIR)) from filelist import atomic_write, parse_filelists, write_filelist # noqa: E402 from generate_filelist import generate_all # noqa: E402 from scripts.analyze_warnings import normalize # noqa: E402 +from scripts.check_c_warnings import self_owned_warnings # noqa: E402 from scripts.dependency_lock import LockError, load_lock # noqa: E402 from scripts.install_toolchain import safe_extract # noqa: E402 from scripts.setup_helpers import download_file, ensure_git_repo # noqa: E402 @@ -398,6 +399,25 @@ def test_warning_normalization_keeps_ranges_and_removes_variant_hash(tmp_path: P ) +def test_c_warning_filter_excludes_vendored_sources(tmp_path: Path) -> None: + policy_dir = tmp_path / "quality" + policy_dir.mkdir() + (policy_dir / "embedded_c_policy.json").write_text( + (ROOT / "quality/embedded_c_policy.json").read_text(encoding="utf-8"), + encoding="utf-8", + ) + output = "\n".join( + ( + f"{tmp_path}/crt/src/hal/timer.c:9:1: warning: self-owned warning", + f"{tmp_path}/app/coremark/coremark-main/core_main.c:4:1: warning: vendor warning", + ) + ) + + warnings = self_owned_warnings(tmp_path, output) + + assert warnings == ["crt/src/hal/timer.c:9: warning: self-owned warning"] + + def test_metrics_collection_and_observe_policy(tmp_path: Path) -> None: variant = tmp_path / "variant" (variant / "sw").mkdir(parents=True)