From d9c90eef131e6d68ab7177c9bf2d47b6885c6790 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 6 Aug 2024 17:42:53 +0900 Subject: [PATCH 01/81] esp32s3-devkit/toywasm: enable ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK --- boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig b/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig index 0e08f0d287628..6b0aea34dc1bf 100644 --- a/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig +++ b/boards/xtensa/esp32s3/esp32s3-devkit/configs/toywasm/defconfig @@ -28,6 +28,7 @@ CONFIG_ESP32S3_RT_TIMER_TASK_STACK_SIZE=4096 CONFIG_ESP32S3_SPIFLASH=y CONFIG_ESP32S3_SPIRAM=y CONFIG_ESP32S3_SPIRAM_MODE_OCT=y +CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK=y CONFIG_ESP32S3_STORAGE_MTD_SIZE=0x1e80000 CONFIG_ESP32S3_UART0=y CONFIG_ESP32S3_WIFI=y @@ -71,7 +72,6 @@ CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_RAM_SIZE=114688 CONFIG_RAM_START=0x20000000 CONFIG_RR_INTERVAL=200 -CONFIG_SCHED_LPWORK=y CONFIG_SCHED_WAITPID=y CONFIG_SIG_DEFAULT=y CONFIG_SMP=y From d759611e90323566f995b1f0a1cafeb6e6b964c5 Mon Sep 17 00:00:00 2001 From: zouboan Date: Tue, 6 Aug 2024 16:14:04 +0800 Subject: [PATCH 02/81] Documentation/platforms:add documentation for Zynq MPSoC and ZCU111 Co-authored-by: Alan Carvalho de Assis --- .../arm64/zynq-mpsoc/boards/zcu111/index.rst | 320 ++++++++++++++++++ .../platforms/arm64/zynq-mpsoc/index.rst | 81 +++++ 2 files changed, 401 insertions(+) create mode 100644 Documentation/platforms/arm64/zynq-mpsoc/boards/zcu111/index.rst create mode 100644 Documentation/platforms/arm64/zynq-mpsoc/index.rst diff --git a/Documentation/platforms/arm64/zynq-mpsoc/boards/zcu111/index.rst b/Documentation/platforms/arm64/zynq-mpsoc/boards/zcu111/index.rst new file mode 100644 index 0000000000000..797e7b90f65c1 --- /dev/null +++ b/Documentation/platforms/arm64/zynq-mpsoc/boards/zcu111/index.rst @@ -0,0 +1,320 @@ +============================= +Zynq UltraScale+ RFSoC ZCU111 +============================= + +The `ZCU111 `_ is a +development board based on the Zynq UltraScale+ RFSoC(XCZU28DR) from XilinX(AMD). + +Features +======== + +- **RF Data Converter** + - **12-bit ADC:** 8, Max Rate 4.096G + - **14-bit DAC:** 8, Max Rate 6.554G + - **SD-FEC:** SD-FEC +- **Memory** + - **PS DDR4:** 4GB 64-bit SODIMM + - **SD-Card:** Yes + - **M.2 SATA Connector:** Yes + - **QSPI:** 2 +- **Communications & Networking** + - **USB UART/JTAG:** 1 + - **RJ45:** 1 + - **SFP+:** 4 + - **USB 3.0:** 1 +- **Expansion Connectors** + - **FMC-HPC Connector:** 2 + - **PMOD:** 2 + - **RFMC 1.0:** 2 + - **QSPI:** 2 +- **Control & I/O** + - **I2C:** Yes + - **PMBUS:** Yes + - **JTAG PC4 Header:** Yes +- **Boot Options** + - **ISD Boot:** Yes + - **QSPI Boot:** Yes + - **JTAG Boot:** Yes +- **DDR4 SODIMM:** 4GB 64-bit, 2400MT/s, attached to Processor Subsystem (PS) + +Serial Console +============== + +Serial console for the PS: + +===== ======== ============= +Pin Signal Notes +===== ======== ============= +MIO18 UART0 TX USB UART COM0 +MIO19 UART0 RX USB UART COM0 +===== ======== ============= + +PS-side UART interface and is connected to the FTDI U34 FT4232HL USB-to-Quad-UART +bridge port B Connect ZCU111 to our computer with the USB Cable. On our computer +start a Serial Terminal and connect to the USB Serial Port at **115200 bps**. +NuttX will appear in the Serial Console when it boots on zcu111. + +LEDs and Buttons +================ + +The PS-side pushbutton SW19 is connected to MIO22 (pin U1.Y28). The PS-side LED DS50, +which is physically placed adjacent to the pushbutton, is connected to MIO23(pin U1.U29). + +Configurations +============== + +Each configuration is maintained in a sub-directory and can be selected as follow:: + + tools/configure.sh zcu111: + +Where is one of the following: + +jtag +---- + +Basic NuttShell configuration for JTAG boot mode (nsh console enabled in UART0, +UART and JTAG exposed via FT4232HL USB-to-Quad-UART bridge port and USB cable). + +nsh +--- + +Basic NuttShell configuration for Flash boot mode. We need create boot image with +zynqmp_fsbl.elf, zynqmp_pmufw.elf, bl31.elf and nuttx.elf in Vivado SDK or XSCT +shell. Also we need copy BOOT.BIN into SD Card(in SD card boot mode) or Flash it +into the QSPI FLASH(in QSPI boot mode). + +ARM64 Toolchain +=============== + +There are two ways to install the toolchain for Zynq MPSoC: +The first way is download the ARM64 Toolchain ``aarch64-none-elf`` from +`Arm GNU Toolchain Downloads `_. +Add the downloaded toolchain ``gcc-arm-...-aarch64-none-elf/bin`` +to the ``PATH`` Environment Variable such as: + +.. code-block:: console + + $ echo "export PATH=/home/username/tools/gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf/bin:$PATH" >> ~/.profile + +You can edit your .profile files if you don't use bash. + +The second way is install Vivado SDK or Vitis development environment which included a complete +``aarch64-none-elf`` toolchain and we also add it to the ``PATH`` Environment Variable such as: + +.. code-block:: console + + $ echo "export PATH=/home/username/tools/Xilinx/SDK/2018.3/gnu/aarch64/lin/aarch64-none/bin:$PATH" >> ~/.profile + +You can edit your .profile files if you don't use bash. + +Note: nuttx.elf build by toolchain install in first way can't be debuged by Vivado SDK which use +toolchain of second way for gdb version incompatibility. + +Check the ARM64 Toolchain: + +.. code:: console + + $ aarch64-none-elf-gcc -v + +Building +======== + +There are two types of NuttX image for Zynq MPSoC: debug by JTAG and boot from FLASH. + +debug by jtag +------------- + +We just configure the NuttX project and build the project: + +.. code:: console + + $ cd nuttx + $ tools/configure.sh zcu111:jtag + $ make + +Set the Project to nuttx and Application to nuttx.elf for psu_cortexa53_0 in Vivado SDK Debug Configuration. +Just click Debug button then we can debug NuttX. + +boot from flash +--------------- + +To boot from FLASH, we have to create BOOT.BIN image and flash it into QSPI FLASH or SD card. To create BOOT.BIN +in addition to building nuttx.elf, we also need to build zynqmp_fsbl.elf, zynqmp_pmufw.elf and bl31.elf +To build nuttx.elf we just configure the NuttX project and build the project: + +.. code:: console + + $ cd nuttx + $ tools/configure.sh zcu111:nsh + $ make + +build bl31.elf +-------------- + +To build bl31.elf we should fetch Fetch sources of ARM Trusted Firmware (ATF) and checkout the tags that +corresponding to the SDK version. Take Vivado 2018.3 for example: + +.. code:: console + + $ git clone https://github.com/Xilinx/arm-trusted-firmware.git + $ cd arm-trusted-firmware + $ git checkout xilinx-v2018.3 + +By default, the Arm-trusted firmware builds for OCM space at address 0xFFFEA000, and ATF assume that UBoot +or nuttx.elf located at address 0x08000000. Then we just build bl31.elf with: + +.. code:: console + + $ make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 + +But, with DEBUG flag set to 1, it can't fit in OCM, so by default with DEBUG=1, it builds for DDR location +0x1000 with build flag DEBUG=1 mentioned while building. Alternatively, user has always an option to build +for the location of their choice by specifying the build flags ZYNQMP_ATF_MEM_BASE, ZYNQMP_ATF_MEM_SIZE while +building. The flag ZYNQMP_ATF_MEM_BASE specifies the base address of ATF and flag ZYNQMP_ATF_MEM_SIZE specifies +the maximum size the ATF image can be. what's more we can specifies the target address of Uboot or nuttx.elf +by PRELOADED_BL33_BASE. for zcu111:nsh configuration Example bl31 build command: + +.. code:: console + + $ make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 ZYNQMP_ATF_MEM_BASE=0x10000 ZYNQMP_ATF_MEM_SIZE=0x40000 PRELOADED_BL33_BASE=0x100000 + +If we don't dubug bl31 we just build bl31 in following command: + +.. code:: console + + $ make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 PRELOADED_BL33_BASE=0x100000 + +After the build process completes the bl31.elf binary is created within the /build/zynqmp/release/bl31 directory. + +build zynqmp_pmufw.elf +---------------------- + +The Platform Management Unit (PMU) in Zynq MPSoC has a Microblaze with 32 KB of ROM and 128 KB of RAM. The ROM is +pre-loaded with PMU Boot ROM (PBR) which performs pre-boot tasks and enters a service mode. For more details on PMU, +PBR and PMUFW load sequence, refer to Platform Management Unit (Chapter-6) in Zynq MPSoC TRM (UG1085). PMU RAM can +be loaded with a firmware (PMU Firmware) at run-time and can be used to extend or customize the functionality of PMU. +Some part of the RAM is reserved for PBR, leaving around 125.7 KB for PMU Firmware. +There are usually two flows to create and build a PMU Firmware image for the target, Xilinx Vitis or Vivado SDK IDE or +hsi command line. The PMU Firmware is provided as a template application for the PMU processor for any hardware platform +including the Zynq MPSoC device. The steps required to create and build it can be applied by selecting the appropriate +platform, processor, and template to create zynqmp_pmufw.elf. We can also create PMU Firmware from system hardware +project hdf file by hsi command line: + +.. code-block:: + + proc generate_pmufw {} { + if {[file exists pmu_fw/zynqmp_pmufw.elf] != 1} { + set pmufw_design [hsi::create_sw_design pmu_1 -proc psu_pmu_0 -app zynqmp_pmufw] + hsi::add_library libmetal + hsi::generate_app -dir pmu_fw -compile + return "pmu_fw/zynqmp_pmufw.elf" + } + return "pmu_fw/zynqmp_pmufw.elf" + } + +In order to call this procs, the user needs to open the hdf (hsi::open_hw_design): + +.. code-block:: + + proc create_pmufw {hdf} { + hsi::open_hw_design $hdf + set pmufw [generate_pmufw] + hsi::close_hw_design [hsi::current_hw_design] + } + +Create a TCL script with HSI commands above -> Create a TCL script with HSI commands above -> +Launch XSCT 2018.3 -> Change directory to the zipped directory -> source xsct_script.tcl -> +create_pmufw design_1_wrapper.hdf + +build zynqmp_fsbl.elf +--------------------- + +First Stage Bootloader (FSBL) for Zynq UltraScale+ MPSoC configures the FPGA with hardware bitstream (if it exists) +and loads the Operating System (OS) Image or Standalone (SA) Image or 2nd Stage Boot Loader image from the non-volatile +memory (SD/eMMC/QSPI) to Memory (DDR/TCM/OCM) and takes A53/R5 out of reset. It supports multiple partitions, and each +partition can be a code image or a bitstream. Each of these partitions, if required, will be authenticated and/or decrypted. +FSBL is loaded into OCM and handed off by CSU BootROM after authenticating and/or decrypting (as required) FSBL. +There are usually two flows to create and build a PMU Firmware image for the target, Xilinx Vitis or Vivado SDK IDE or +hsi command line. +To create FSBL by Vitis or Vivado SDK IDE just launch VITIS or Vivado SDK and do following flow: + +- Provide path where VITIS workspace and project need to be created. With this VITIS workspace will be created +- (Optional step) To work with local repos, Select "Xilinx" (ALT - x) -> Repositories. Against Local Repositories, + click on "New..." and provide path of the local repo +- Select File-->New-->Application Project to open "New Project" window, provide name for FSBL project +- In the “Platform” section, click on “Create a new platform from hardware (XSA)” and select pre-defined hardware platform for ZynqMP. + - Alternatively, to create a new/custom platform from a .xsa file, click on “+”, browse and select the XSA file and a new hardware platform is created. +- In the "Domain" window, select the processor psu_cortexa53_0/psu_cortexr5_0, OS as standalone and Language as C. +- Click Next and select "Zynq MP FSBL" +- Click "Finish" to generate the A53/R5 FSBL. This populates the FSBL code and also builds it (along with BSP) +- Debug prints in FSBL are now disabled by default. To enable debug prints, define symbol: FSBL_DEBUG_INFO. + - In VITIS this can be done by: right click on FSBL application project -> select “C/C++ Build Settings” -> “Tool Settings” tab -> Symbols (under ARM v8 gcc compiler) + - Click on Add (+) icon and Enter Value: FSBL_DEBUG_INFO, click on "OK" to close the "Enter Value" screen +- In case any of the source files (FSBL or BSP) need to be modified, browse the file, make the change and save the file, + build the project. elf file will be present in the Debug/Release folder of FSBL project. + +To create FSBL by XSCT command line just launch XSCT console and execute following TCL script with HSI commands: + +.. code-block:: + + proc generate_fsbl {} { + if {[file exists zynqmp_fsbl/zynqmp_fsbl.elf] != 1} { + set fsbl_design [hsi::create_sw_design fsbl_1 -proc psu_cortexa53_0 -app zynqmp_fsbl] + common::set_property APP_COMPILER "aarch64-none-elf-gcc" $fsbl_design + common::set_property -name APP_COMPILER_FLAGS -value "-DRSA_SUPPORT -DFSBL_DEBUG_INFO -DXPS_BOARD_ZCU111" -objects $fsbl_design + hsi::add_library libmetal + hsi::generate_app -dir zynqmp_fsbl -compile + } + return "zynqmp_fsbl/zynqmp_fsbl.elf" + } + +In order to call this procs, the user needs to open the hdf (hsi::open_hw_design): + +.. code-block:: + + proc create_fsbl {hdf} { + hsi::open_hw_design $hdf + set fsbl [generate_fsbl] + hsi::close_hw_design [hsi::current_hw_design] + } + +Create a TCL script with HSI commands above -> Create a TCL script with HSI commands above -> +Launch XSCT 2018.3 -> Change directory to the zipped directory -> source xsct_script.tcl -> +create_fsbl design_1_wrapper.hdf + +generate BOOT.bin image +----------------------- + +You can create BOOT.bin images using the BIF attributes and the Bootgen command. +For this configuration, the BIF file(named fsbl.bif) contains the following attributes: + +.. code-block:: + + the_ROM_image: + { + [fsbl_config]a53_x64 + [bootloader]zynqmp_fsbl.elf + [pmufw_image]zynqmp_pmufw.elf + [destination_cpu = a53-0, exception_level = el-3, trustzone]bl31.elf + [destination_cpu = a53-0, exception_level = el-1]nuttx.elf + } + +The Vitis IDE calls the following Bootgen command to generate the BOOT.bin image for this configuration: + +.. code-block:: + + bootgen -image fsbl.bif -arch zynqmp -o .\BOOT.bin + +Flash BOOT.bin to QSPI FLASH +---------------------------- + +We can flash BOOT.bin into QSPI FLASH in following flow: + +- In the Vivado SDK/Vitis IDE, select Xilinx -> Program Flash. +- In the Program Flash wizard, browse to and select the BOOT.bin image file that was created as a part of this example. +- Select **qspi-x8-dual_parallel** as the Flash type. +- Set the Offset as 0 and select the BOOT.bin file. +- Click Program to start the process of programming the QSPI flash with the BOOT.bin. +- Wait until you see the message “Flash Operation Successful” in the console. + +Set mode switch SW6 to QSPI32, NuttX will appear in the Serial Console when we power on zcu111. diff --git a/Documentation/platforms/arm64/zynq-mpsoc/index.rst b/Documentation/platforms/arm64/zynq-mpsoc/index.rst new file mode 100644 index 0000000000000..e254e9eaa614d --- /dev/null +++ b/Documentation/platforms/arm64/zynq-mpsoc/index.rst @@ -0,0 +1,81 @@ +====================== +Zynq UltraScale+ MPSoC +====================== + +The Zynq UltraScale+ MPSoC family consists of a system-on-chip (SoC) style integrated +processing system (PS) and a Programmable Logic (PL) unit, providing an extensible and +flexible SoC solution on a single die.There's 64-bit Quadcore ARM Cortex-A53 Processors +and Dualcore ARM Cortex-R5 Real-Time Processors in the MPSoC, zynq-mpsoc given support +for Quadcore ARM Cortex-A53 Processors of MPSoC + +Peripheral Support +================== + +The following list indicates peripherals supported in NuttX: + +========== ======= =============== +Peripheral Support Notes +========== ======= =============== +MIO Yes +EMIO Yes Depending on PL +I2C No +CAN No +NET No +SPI No +QSPI No +TIMER NO +UART Yes +WDT No +DMA No +SDI No +ADC No Depending on PL +DAC No Depending on PL +PCI NO Depending on PL +========== ======= =============== + +MIO/EMIO +-------- + +Key features of the GPIO peripheral are summarized as follows: + +- 78 GPIO interfaces to the device pins. + - Routed through the MIO multiplexer. + - Programmable I/O drive strength, slew rate, and 3-state control. +- 96 GPIO interfaces to the PL (four allocated by software to reset PL logic). + - Routed through the EMIO interface. + - Data inputs. + - Data outputs. + - Output enables. +- I/O interface is organized into six banks (3 MIO and 3 EMIO). + +Pins can be configured/operated using ``zynq_mio_*`` functions. To handled 96 GPIO in 3 +EMIO banks you should map GPIO to chip's pin by HDL design in PL logic. + +UART +---- + +Zynq UltraScale+ MPSoC have two high-speed UARTs (up to 1Mb/s). The UART controller is +a full-duplex asynchronous receiver and transmitter that supports a wide range of +programmable baud rates and I/O signal formats. The controller can accommodate +automatic parity generation and multi-master detection mode this may introduce a large +number of interrupts which may be undesirable. + +UART can be configured/operated using ``zynq_uart_*`` functions. Both receive and +transmit can be operated in interrupt mode and polling mode. + +Psci and debug +-------------- + +Default exception level is EL1 for the NuttX OS. However, if we debug NuttX by JTAG +the XSCT of Vivado SDK will set the Zynq MPSoC to EL3. so have to config NuttX to run on +EL3. Other levels are not supported at the moment. And in this operating conditon +we can't use SMC for there's no ATF support. + +Supported Boards +================ + +.. toctree:: + :glob: + :maxdepth: 1 + + boards/*/* From 52583fc17eed2d206b95b3ef93e26bd41b28ad67 Mon Sep 17 00:00:00 2001 From: Lup Yuen Lee Date: Wed, 7 Aug 2024 13:30:27 +0800 Subject: [PATCH 03/81] tools/ci: Add Rust Target for QEMU RISC-V 64-bit This PR updates the Docker Image for NuttX CI, so that it builds Rust Apps correctly for QEMU RISC-V 64-bit. We add the Rust Target for `riscv64gc-unknown-none-elf` to the Docker Image. In the next PR, we will call the Updated Docker Image to [compile the Rust App `leds_rust`](https://github.com/apache/nuttx/pull/12852), at every run of NuttX CI. This will validate whether Rust Apps are built correctly for QEMU RISC-V 64-bit. Modified Files: `tools/ci/docker/linux/Dockerfile`: Add Rust Target `riscv64gc-unknown-none-elf` for Docker CI `tools/ci/platforms/ubuntu.sh`: Same as above, but for Ubuntu CI `tools/ci/platforms/msys2.sh`: Same as above, but for MSYS2 CI --- tools/ci/docker/linux/Dockerfile | 3 ++- tools/ci/platforms/msys2.sh | 1 + tools/ci/platforms/ubuntu.sh | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/ci/docker/linux/Dockerfile b/tools/ci/docker/linux/Dockerfile index 78b43ca5c09fd..845f9bc18b70c 100644 --- a/tools/ci/docker/linux/Dockerfile +++ b/tools/ci/docker/linux/Dockerfile @@ -66,7 +66,8 @@ ENV RUSTUP_HOME=$RUST_HOME/rustup RUN mkdir -p $CARGO_HOME \ && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ && $CARGO_HOME/bin/rustup target add thumbv6m-none-eabi \ - && $CARGO_HOME/bin/rustup target add thumbv7m-none-eabi + && $CARGO_HOME/bin/rustup target add thumbv7m-none-eabi \ + && $CARGO_HOME/bin/rustup target add riscv64gc-unknown-none-elf RUN mkdir /tools/gn -p \ && cd /tools/gn \ diff --git a/tools/ci/platforms/msys2.sh b/tools/ci/platforms/msys2.sh index f5230e778c368..687b81cff4c8d 100755 --- a/tools/ci/platforms/msys2.sh +++ b/tools/ci/platforms/msys2.sh @@ -181,6 +181,7 @@ rust() { # Install targets supported from NuttX "$CARGO_HOME"/bin/rustup target add thumbv6m-none-eabi "$CARGO_HOME"/bin/rustup target add thumbv7m-none-eabi + "$CARGO_HOME"/bin/rustup target add riscv64gc-unknown-none-elf rm rustup-init.exe fi command rustc --version diff --git a/tools/ci/platforms/ubuntu.sh b/tools/ci/platforms/ubuntu.sh index e545b4f5aba2b..fdfaaa9bf25cc 100755 --- a/tools/ci/platforms/ubuntu.sh +++ b/tools/ci/platforms/ubuntu.sh @@ -230,6 +230,7 @@ rust() { # Install targets supported from NuttX rustup target add thumbv6m-none-eabi rustup target add thumbv7m-none-eabi + rustup target add riscv64gc-unknown-none-elf fi command rustc --version From 9ffac124658dc631ddc9158e929fbd28429c9dd6 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Thu, 26 Oct 2023 17:04:46 +0800 Subject: [PATCH 04/81] spi: Remove useless restrictions Signed-off-by: Shoukui Zhang --- drivers/spi/spi_bitbang.c | 3 --- drivers/spi/spi_driver.c | 3 --- drivers/spi/spi_transfer.c | 3 --- 3 files changed, 9 deletions(-) diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 94b40dfe4c0b4..953cb22af5338 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -35,8 +35,6 @@ #include -#ifdef CONFIG_SPI_BITBANG - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -559,4 +557,3 @@ void spi_destroy_bitbang(FAR struct spi_dev_s *dev) kmm_free(dev); } -#endif /* CONFIG_SPI_BITBANG */ diff --git a/drivers/spi/spi_driver.c b/drivers/spi/spi_driver.c index ec1ae8a90c1b0..23dbad4970ddb 100644 --- a/drivers/spi/spi_driver.c +++ b/drivers/spi/spi_driver.c @@ -37,8 +37,6 @@ #include #include -#ifdef CONFIG_SPI_DRIVER - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -393,4 +391,3 @@ int spi_register(FAR struct spi_dev_s *spi, int bus) return -ENOMEM; } -#endif /* CONFIG_SPI_DRIVER */ diff --git a/drivers/spi/spi_transfer.c b/drivers/spi/spi_transfer.c index 82d1e70c61f89..4b93d3148ca02 100644 --- a/drivers/spi/spi_transfer.c +++ b/drivers/spi/spi_transfer.c @@ -33,8 +33,6 @@ #include #include -#ifdef CONFIG_SPI_EXCHANGE - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -143,4 +141,3 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct spi_sequence_s *seq) return ret; } -#endif /* CONFIG_SPI_EXCHANGE */ From a6cea0d82e883564075c13b2e45e10dac4959823 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Thu, 26 Oct 2023 15:11:35 +0800 Subject: [PATCH 05/81] Restriction declaration spi_slave_unlink function Signed-off-by: Shoukui Zhang --- drivers/spi/spi_slave_driver.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi_slave_driver.c b/drivers/spi/spi_slave_driver.c index d23fadf14ac4f..c80ab1ed39a91 100644 --- a/drivers/spi/spi_slave_driver.c +++ b/drivers/spi/spi_slave_driver.c @@ -106,7 +106,10 @@ static ssize_t spi_slave_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); static int spi_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS static int spi_slave_unlink(FAR struct inode *inode); +#endif /* SPI Slave driver methods */ From 2bf13ffbb0751ec654c75599d4ace3cc40237cf4 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Thu, 26 Oct 2023 15:22:56 +0800 Subject: [PATCH 06/81] spi: Optimize access to private data Signed-off-by: Shoukui Zhang --- drivers/spi/spi_driver.c | 31 +++++++++++++------------- drivers/spi/spi_slave_driver.c | 40 +++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi_driver.c b/drivers/spi/spi_driver.c index 23dbad4970ddb..0774dcd956eba 100644 --- a/drivers/spi/spi_driver.c +++ b/drivers/spi/spi_driver.c @@ -116,16 +116,16 @@ static const struct file_operations g_spidrvr_fops = #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS static int spidrvr_open(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_driver_s *priv; int ret; - /* Get our private data structure */ + /* Sanity check */ - inode = filep->f_inode; + DEBUGASSERT(filep->f_inode->i_private != NULL); - priv = inode->i_private; - DEBUGASSERT(priv); + /* Get our private data structure */ + + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI driver state structure */ @@ -152,16 +152,16 @@ static int spidrvr_open(FAR struct file *filep) #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS static int spidrvr_close(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_driver_s *priv; int ret; - /* Get our private data structure */ + /* Sanity check */ - inode = filep->f_inode; + DEBUGASSERT(filep->f_inode->i_private != NULL); - priv = inode->i_private; - DEBUGASSERT(priv); + /* Get our private data structure */ + + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI driver state structure */ @@ -184,6 +184,7 @@ static int spidrvr_close(FAR struct file *filep) { nxmutex_destroy(&priv->lock); kmm_free(priv); + filep->f_inode->i_private = NULL; return OK; } @@ -218,19 +219,18 @@ static ssize_t spidrvr_write(FAR struct file *filep, FAR const char *buffer, static int spidrvr_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { - FAR struct inode *inode; FAR struct spi_driver_s *priv; FAR struct spi_sequence_s *seq; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("cmd=%d arg=%lu\n", cmd, arg); /* Get our private data structure */ - inode = filep->f_inode; - - priv = inode->i_private; - DEBUGASSERT(priv); + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI driver state structure */ @@ -305,6 +305,7 @@ static int spidrvr_unlink(FAR struct inode *inode) { nxmutex_destroy(&priv->lock); kmm_free(priv); + inode->i_private = NULL; return OK; } diff --git a/drivers/spi/spi_slave_driver.c b/drivers/spi/spi_slave_driver.c index c80ab1ed39a91..1e33b4f242e10 100644 --- a/drivers/spi/spi_slave_driver.c +++ b/drivers/spi/spi_slave_driver.c @@ -174,18 +174,17 @@ static const struct spi_slave_devops_s g_spisdev_ops = static int spi_slave_open(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; int ret; - DEBUGASSERT(filep->f_inode->i_private != NULL); + /* Sanity check */ + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep: %p\n", filep); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI Slave driver state structure */ @@ -229,18 +228,17 @@ static int spi_slave_open(FAR struct file *filep) static int spi_slave_close(FAR struct file *filep) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; int ret; - DEBUGASSERT(filep->f_inode->i_private != NULL); + /* Sanity check */ + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep: %p\n", filep); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; /* Get exclusive access to the SPI Slave driver state structure */ @@ -273,7 +271,7 @@ static int spi_slave_close(FAR struct file *filep) { nxmutex_destroy(&priv->lock); kmm_free(priv); - inode->i_private = NULL; + filep->f_inode->i_private = NULL; return OK; } @@ -302,18 +300,19 @@ static int spi_slave_close(FAR struct file *filep) static ssize_t spi_slave_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; size_t read_bytes; size_t remaining_words; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep=%p buffer=%p buflen=%zu\n", filep, buffer, buflen); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; if (buffer == NULL) { @@ -394,17 +393,18 @@ static ssize_t spi_slave_read(FAR struct file *filep, FAR char *buffer, static ssize_t spi_slave_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) { - FAR struct inode *inode; FAR struct spi_slave_driver_s *priv; size_t enqueued_bytes; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); spiinfo("filep=%p buffer=%p buflen=%zu\n", filep, buffer, buflen); /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; ret = nxmutex_lock(&priv->lock); if (ret < 0) @@ -453,13 +453,15 @@ static int spi_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) { FAR struct spi_slave_driver_s *priv; - FAR struct inode *inode; int ret; + /* Sanity check */ + + DEBUGASSERT(filep->f_inode->i_private != NULL); + /* Get our private data structure */ - inode = filep->f_inode; - priv = inode->i_private; + priv = filep->f_inode->i_private; ret = nxmutex_lock(&priv->lock); if (ret < 0) @@ -525,6 +527,8 @@ static int spi_slave_unlink(FAR struct inode *inode) FAR struct spi_slave_driver_s *priv; int ret; + /* Sanity check */ + DEBUGASSERT(inode->i_private != NULL); /* Get our private data structure */ From 6114c0b948d4ef379f72960b06a851aa9bc5942c Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Fri, 27 Oct 2023 19:14:34 +0800 Subject: [PATCH 07/81] i2c: Remove useless restrictions Signed-off-by: Shoukui Zhang --- drivers/i2c/i2c_driver.c | 3 --- drivers/i2c/pca9540bdp.c | 3 --- drivers/i2c/tca9548a.c | 3 --- 3 files changed, 9 deletions(-) diff --git a/drivers/i2c/i2c_driver.c b/drivers/i2c/i2c_driver.c index 8e35deb98ba46..06e7a99ee53ba 100644 --- a/drivers/i2c/i2c_driver.c +++ b/drivers/i2c/i2c_driver.c @@ -37,8 +37,6 @@ #include #include -#ifdef CONFIG_I2C_DRIVER - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -408,4 +406,3 @@ int i2c_register(FAR struct i2c_master_s *i2c, int bus) return -ENOMEM; } -#endif /* CONFIG_I2C_DRIVER */ diff --git a/drivers/i2c/pca9540bdp.c b/drivers/i2c/pca9540bdp.c index a83c318279967..321635c204973 100644 --- a/drivers/i2c/pca9540bdp.c +++ b/drivers/i2c/pca9540bdp.c @@ -36,8 +36,6 @@ #include "pca9540bdp.h" #include -#ifdef CONFIG_I2CMULTIPLEXER_PCA9540BDP - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -299,4 +297,3 @@ FAR struct pca9540bdp_dev_s * return priv; } -#endif /* CONFIG_I2CMULTIPLEXER_PCA9540BDP */ diff --git a/drivers/i2c/tca9548a.c b/drivers/i2c/tca9548a.c index ae2ddfa758a23..e4ad72228a252 100644 --- a/drivers/i2c/tca9548a.c +++ b/drivers/i2c/tca9548a.c @@ -36,8 +36,6 @@ #include #include -#ifdef CONFIG_I2CMULTIPLEXER_TCA9548A - #ifndef CONFIG_TCA9548A_I2C_FREQUENCY # define CONFIG_TCA9548A_I2C_FREQUENCY 400000 #endif @@ -409,4 +407,3 @@ FAR struct tca9548a_dev_s * return priv; } -#endif /* CONFIG_I2CMULTIPLEXER_TCA9548A */ From f4a234613e8d4d5b89d6f63adf5d34ec324620f8 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Tue, 24 Oct 2023 17:14:21 +0800 Subject: [PATCH 08/81] Add I2C Slave driver Signed-off-by: Shoukui Zhang --- drivers/i2c/CMakeLists.txt | 4 + drivers/i2c/Kconfig | 24 ++ drivers/i2c/Make.defs | 4 + drivers/i2c/i2c_slave_driver.c | 523 +++++++++++++++++++++++++++++++++ include/nuttx/i2c/i2c_slave.h | 27 ++ 5 files changed, 582 insertions(+) create mode 100644 drivers/i2c/i2c_slave_driver.c diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index d3f32ac00663f..b365491feead8 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -30,6 +30,10 @@ if(CONFIG_I2C) list(APPEND SRCS i2c_bitbang.c) endif() + if(CONFIG_I2C_SLAVE_DRIVER) + list(APPEND SRCS i2c_slave_driver.c) + endif() + # Include the selected I2C multiplexer drivers if(CONFIG_I2CMULTIPLEXER_PCA9540BDP) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 764fc7473db8f..a0883f5a20440 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -24,6 +24,30 @@ config I2C_SLAVE bool "I2C Slave" default n +menu "I2C Slave Support" + +config I2C_SLAVE_DRIVER + bool "I2C Slave driver" + default n + ---help--- + Enable I2C Slave driver + +config I2C_SLAVE_READBUFSIZE + int "I2C Slave driver read buffer size" + default 32 + depends on I2C_SLAVE_DRIVER + ---help--- + I2C Slave read buffer size + +config I2C_SLAVE_WRITEBUFSIZE + int "I2C Slave driver write buffer size" + default 32 + depends on I2C_SLAVE_DRIVER + ---help--- + I2C Slave write buffer size + +endmenu # I2C Slave Support + config I2C_POLLED bool "Polled I2C (no interrupts)" default n diff --git a/drivers/i2c/Make.defs b/drivers/i2c/Make.defs index d069ad80dc601..e823327de080d 100644 --- a/drivers/i2c/Make.defs +++ b/drivers/i2c/Make.defs @@ -32,6 +32,10 @@ ifeq ($(CONFIG_I2C_BITBANG),y) CSRCS += i2c_bitbang.c endif +ifeq ($(CONFIG_I2C_SLAVE_DRIVER),y) +CSRCS += i2c_slave_driver.c +endif + # Include the selected I2C multiplexer drivers ifeq ($(CONFIG_I2CMULTIPLEXER_PCA9540BDP),y) diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c new file mode 100644 index 0000000000000..1cb71262e1c5e --- /dev/null +++ b/drivers/i2c/i2c_slave_driver.c @@ -0,0 +1,523 @@ +/**************************************************************************** + * drivers/i2c/i2c_slave_driver.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DEVNAME_FMT "/dev/i2cslv%d" +#define DEVNAME_FMTLEN (11 + 3 + 1) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int i2c_slave_open(FAR struct file *filep); +static int i2c_slave_close(FAR struct file *filep); +static ssize_t i2c_slave_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t i2c_slave_write(FAR struct file *filep, + FAR const char *buffer, size_t buflen); +static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int i2c_slave_unlink(FAR struct inode *inode); +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct i2c_slave_driver_s +{ + /* Slave private data */ + + FAR struct i2c_slave_s *dev; + + /* Slave send buffer */ + + uint8_t write_buffer[CONFIG_I2C_SLAVE_WRITEBUFSIZE]; + + /* Slave receive buffer */ + + uint8_t read_buffer[CONFIG_I2C_SLAVE_READBUFSIZE]; + + /* Slave receive buffer length */ + + size_t read_length; + + /* Read buffer index */ + + size_t read_index; + + /* Wait for transfer to complete */ + + sem_t wait; + + /* Mutual exclusion */ + + mutex_t lock; + + /* The poll waiter */ + + FAR struct pollfd *fds; + + /* Number of open references */ + + int16_t crefs; + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + bool unlinked; /* Indicates if the driver has been unlinked */ +#endif +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_i2cslavefops = +{ + i2c_slave_open, /* open */ + i2c_slave_close, /* close */ + i2c_slave_read, /* read */ + i2c_slave_write, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* truncate */ + i2c_slave_poll /* poll */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , i2c_slave_unlink /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2c_slave_open + * + * Description: + * This function is called whenever the I2C Slave device is opened. + * + * Input Parameters: + * filep - File structure instance + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +static int i2c_slave_open(FAR struct file *filep) +{ + FAR struct i2c_slave_driver_s *priv; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + /* Increment the count of open references on the driver */ + + priv->crefs++; + DEBUGASSERT(priv->crefs > 0); + + nxmutex_unlock(&priv->lock); + return OK; +} + +/**************************************************************************** + * Name: i2c_slave_close + * + * Description: + * This routine is called when the I2C Slave device is closed. + * + * Input Parameters: + * filep - File structure instance + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +static int i2c_slave_close(FAR struct file *filep) +{ + FAR struct i2c_slave_driver_s *priv; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C slave driver state structure */ + + nxmutex_lock(&priv->lock); + + /* Decrement the count of open references on the driver */ + + DEBUGASSERT(priv->crefs > 0); + priv->crefs--; +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + if (priv->crefs <= 0 && priv->unlinked) + { + nxmutex_destroy(&priv->lock); + kmm_free(priv); + filep->f_inode->i_private = NULL; + return OK; + } +#endif + + nxmutex_unlock(&priv->lock); + return OK; +} + +/**************************************************************************** + * Name: i2c_slave_read + * + * Description: + * This routine is called when the application requires to read the data + * received by the I2C Slave device. + * + * Input Parameters: + * filep - File structure instance + * buffer - User-provided to save the data + * buflen - The maximum size of the user-provided buffer + * + * Returned Value: + * The positive non-zero number of bytes read on success, 0 on if an + * end-of-file condition, or a negated errno value on any failure. + * + ****************************************************************************/ + +static ssize_t i2c_slave_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct i2c_slave_driver_s *priv; + int ret; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + while (priv->read_length == 0) + { + nxmutex_unlock(&priv->lock); + if (filep->f_oflags & O_NONBLOCK) + { + return -EAGAIN; + } + + ret = nxsem_wait(&priv->wait); + if (ret < 0) + { + return ret; + } + + nxmutex_lock(&priv->lock); + } + + buflen = MIN(buflen, priv->read_length); + memcpy(buffer, priv->read_buffer + priv->read_index, buflen); + priv->read_index += buflen; + priv->read_length -= buflen; + nxmutex_unlock(&priv->lock); + return buflen; +} + +/**************************************************************************** + * Name: i2c_slave_write + * + * Description: + * This routine is called when the application needs to enqueue data to be + * transferred at the next leading clock edge of the I2C Slave controller. + * + * Input Parameters: + * filep - Instance of struct file to use with the write + * buffer - Data to write + * buflen - Length of data to write in bytes + * + * Returned Value: + * On success, the number of bytes written are returned (zero indicates + * nothing was written). On any failure, a negated errno value is returned. + * + ****************************************************************************/ + +static ssize_t i2c_slave_write(FAR struct file *filep, + FAR const char *buffer, size_t buflen) +{ + FAR struct i2c_slave_driver_s *priv; + size_t write_bytes; + int ret; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + write_bytes = MIN(buflen, CONFIG_I2C_SLAVE_WRITEBUFSIZE); + memcpy(priv->write_buffer, buffer, write_bytes); + ret = I2CS_WRITE(priv->dev, priv->write_buffer, write_bytes); + nxmutex_unlock(&priv->lock); + return ret < 0 ? ret : write_bytes; +} + +/**************************************************************************** + * Name: i2c_slave_poll + ****************************************************************************/ + +static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct i2c_slave_driver_s *priv; + int ret; + + DEBUGASSERT(filep->f_inode->i_private != NULL); + + /* Get our private data structure */ + + priv = filep->f_inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + if (setup) + { + pollevent_t eventset = 0; + + if (priv->fds == NULL) + { + priv->fds = fds; + fds->priv = &priv->fds; + } + else + { + ret = -EBUSY; + goto out; + } + + if (priv->read_length > 0) + { + eventset |= POLLIN; + } + + poll_notify(&priv->fds, 1, eventset); + } + else if (fds->priv != NULL) + { + priv->fds = NULL; + fds->priv = NULL; + } + +out: + nxmutex_unlock(&priv->lock); + return ret; +} + +/**************************************************************************** + * Name: i2c_slave_unlink + * + * Description: + * This routine is called when the I2C Slave device is unlinked. + * + * Input Parameters: + * inode - The inode associated with the I2C Slave device + * + * Returned Value: + * Zero is returned on success; a negated value is returned on any failure. + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int i2c_slave_unlink(FAR struct inode *inode) +{ + FAR struct i2c_slave_driver_s *priv; + + DEBUGASSERT(inode->i_private != NULL); + + /* Get our private data structure */ + + priv = inode->i_private; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + /* Are there open references to the driver data structure? */ + + if (priv->crefs <= 0) + { + nxmutex_destroy(&priv->lock); + kmm_free(priv); + inode->i_private = NULL; + return OK; + } + + /* No... just mark the driver as unlinked and free the resources when the + * last client closes their reference to the driver. + */ + + priv->unlinked = true; + nxmutex_unlock(&priv->lock); + return OK; +} +#endif + +static int i2c_slave_callback(FAR void *arg, size_t length) +{ + FAR struct i2c_slave_driver_s *priv = arg; + int semcount; + + /* Get exclusive access to the I2C Slave driver state structure */ + + nxmutex_lock(&priv->lock); + + priv->read_index = 0; + priv->read_length = length; + + while (nxsem_get_value(&priv->wait, &semcount) >= 0 && semcount <= 1) + { + nxsem_post(&priv->wait); + } + + nxmutex_unlock(&priv->lock); + + poll_notify(&priv->fds, 1, POLLIN); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2c_slave_register + * + * Description: + * Register the I2C Slave character device driver as 'devpath'. + * + * Input Parameters: + * dev - An instance of the I2C Slave interface to use to communicate + * with the I2C Slave device + * bus - The I2C Slave bus number. This will be used as the I2C device + * minor number. The I2C Slave character device will be + * registered as /dev/i2cslvN where N is the minor number + * addr - I2C Slave address + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, + int nbits) +{ + FAR struct i2c_slave_driver_s *priv; + char devname[DEVNAME_FMTLEN]; + int ret; + + /* Sanity check */ + + DEBUGASSERT(dev != NULL && (unsigned int)bus < 1000); + + priv = kmm_zalloc(sizeof(struct i2c_slave_driver_s)); + if (priv == NULL) + { + return -ENOMEM; + } + + snprintf(devname, DEVNAME_FMTLEN, DEVNAME_FMT, bus); + ret = register_driver(devname, &g_i2cslavefops, 0666, priv); + if (ret < 0) + { + kmm_free(priv); + return ret; + } + + nxsem_init(&priv->wait, 0, 0); + nxmutex_init(&priv->lock); + priv->dev = dev; + + ret = I2CS_SETOWNADDRESS(priv->dev, addr, nbits); + if (ret < 0) + { + goto out; + } + + ret = I2CS_READ(priv->dev, priv->read_buffer, + CONFIG_I2C_SLAVE_READBUFSIZE); + if (ret < 0) + { + goto out; + } + + ret = I2CS_REGISTERCALLBACK(priv->dev, i2c_slave_callback, priv); + if (ret > 0) + { + return OK; + } + +out: + nxmutex_destroy(&priv->lock); + nxsem_destroy(&priv->wait); + unregister_driver(devname); + kmm_free(priv); + return ret; +} diff --git a/include/nuttx/i2c/i2c_slave.h b/include/nuttx/i2c/i2c_slave.h index ef29ab6ceda60..ee33157958e57 100644 --- a/include/nuttx/i2c/i2c_slave.h +++ b/include/nuttx/i2c/i2c_slave.h @@ -223,6 +223,33 @@ extern "C" #define EXTERN extern #endif +#ifdef CONFIG_I2C_SLAVE_DRIVER + +/**************************************************************************** + * Name: i2c_slave_register + * + * Description: + * Register the I2C Slave character device driver as 'devpath'. + * + * Input Parameters: + * dev - An instance of the I2C Slave interface to use to communicate + * with the I2C Slave device + * bus - The I2C Slave bus number. This will be used as the I2C device + * minor number. The I2C Slave character device will be + * registered as /dev/i2cslvN where N is the minor number + * addr - I2C Slave address + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, + int nbit); + +#endif + #undef EXTERN #if defined(__cplusplus) } From 1ea19e7c540d348925ef0c75b6cf15f6fbdf842d Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Wed, 8 Nov 2023 15:01:09 +0800 Subject: [PATCH 09/81] fix i2c slave register failed Signed-off-by: Shoukui Zhang --- drivers/i2c/i2c_slave_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c index 1cb71262e1c5e..44160017dd180 100644 --- a/drivers/i2c/i2c_slave_driver.c +++ b/drivers/i2c/i2c_slave_driver.c @@ -509,7 +509,7 @@ int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, } ret = I2CS_REGISTERCALLBACK(priv->dev, i2c_slave_callback, priv); - if (ret > 0) + if (ret >= 0) { return OK; } From 20930383158fd62c9b61b02d53a20d2215d81fa9 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Thu, 23 Nov 2023 21:06:50 +0800 Subject: [PATCH 10/81] add setup and shutdown for i2c master and slave Signed-off-by: Shoukui Zhang --- drivers/i2c/i2c_driver.c | 28 +++++++++++++++-- drivers/i2c/i2c_slave_driver.c | 57 +++++++++++++++++++++++++++++----- include/nuttx/i2c/i2c_master.h | 34 ++++++++++++++++++++ include/nuttx/i2c/i2c_slave.h | 34 ++++++++++++++++++++ 4 files changed, 143 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/i2c_driver.c b/drivers/i2c/i2c_driver.c index 06e7a99ee53ba..1a78a64b2d708 100644 --- a/drivers/i2c/i2c_driver.c +++ b/drivers/i2c/i2c_driver.c @@ -135,13 +135,25 @@ static int i2cdrvr_open(FAR struct file *filep) return ret; } + /* I2c master initialize */ + + if (priv->i2c->ops->setup != NULL && priv->crefs == 0) + { + ret = I2C_SETUP(priv->i2c); + if (ret < 0) + { + goto out; + } + } + /* Increment the count of open references on the driver */ priv->crefs++; DEBUGASSERT(priv->crefs > 0); +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } #endif @@ -171,6 +183,17 @@ static int i2cdrvr_close(FAR struct file *filep) return ret; } + /* I2c master uninitialize */ + + if (priv->i2c->ops->shutdown != NULL && priv->crefs == 1) + { + ret = I2C_SHUTDOWN(priv->i2c); + if (ret < 0) + { + goto out; + } + } + /* Decrement the count of open references on the driver */ DEBUGASSERT(priv->crefs > 0); @@ -187,8 +210,9 @@ static int i2cdrvr_close(FAR struct file *filep) return OK; } +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } #endif diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c index 44160017dd180..6403847077882 100644 --- a/drivers/i2c/i2c_slave_driver.c +++ b/drivers/i2c/i2c_slave_driver.c @@ -103,6 +103,14 @@ struct i2c_slave_driver_s int16_t crefs; + /* I2C Slave address */ + + int addr; + + /* The number of address bits provided (7 or 10) */ + + int nbits; + #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS bool unlinked; /* Indicates if the driver has been unlinked */ #endif @@ -150,6 +158,7 @@ static const struct file_operations g_i2cslavefops = static int i2c_slave_open(FAR struct file *filep) { FAR struct i2c_slave_driver_s *priv; + int ret; DEBUGASSERT(filep->f_inode->i_private != NULL); @@ -161,13 +170,36 @@ static int i2c_slave_open(FAR struct file *filep) nxmutex_lock(&priv->lock); + /* I2c slave initialize */ + + if (priv->dev->ops->setup != NULL && priv->crefs == 0) + { + ret = I2CS_SETUP(priv->dev); + if (ret < 0) + { + goto out; + } + } + + /* Set i2c slave address */ + + ret = I2CS_SETOWNADDRESS(priv->dev, priv->addr, priv->nbits); + if (ret < 0) + { + if (priv->dev->ops->shutdown != NULL) + { + ret = I2CS_SHUTDOWN(priv->dev); + } + } + /* Increment the count of open references on the driver */ priv->crefs++; DEBUGASSERT(priv->crefs > 0); +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } /**************************************************************************** @@ -188,6 +220,7 @@ static int i2c_slave_open(FAR struct file *filep) static int i2c_slave_close(FAR struct file *filep) { FAR struct i2c_slave_driver_s *priv; + int ret = OK; DEBUGASSERT(filep->f_inode->i_private != NULL); @@ -199,6 +232,17 @@ static int i2c_slave_close(FAR struct file *filep) nxmutex_lock(&priv->lock); + /* I2c slave uninitialize */ + + if (priv->dev->ops->shutdown != NULL && priv->crefs == 1) + { + ret = I2CS_SHUTDOWN(priv->dev); + if (ret < 0) + { + goto out; + } + } + /* Decrement the count of open references on the driver */ DEBUGASSERT(priv->crefs > 0); @@ -213,8 +257,9 @@ static int i2c_slave_close(FAR struct file *filep) } #endif +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } /**************************************************************************** @@ -494,12 +539,8 @@ int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, nxsem_init(&priv->wait, 0, 0); nxmutex_init(&priv->lock); priv->dev = dev; - - ret = I2CS_SETOWNADDRESS(priv->dev, addr, nbits); - if (ret < 0) - { - goto out; - } + priv->addr = addr; + priv->nbits = nbits; ret = I2CS_READ(priv->dev, priv->read_buffer, CONFIG_I2C_SLAVE_READBUFSIZE); diff --git a/include/nuttx/i2c/i2c_master.h b/include/nuttx/i2c/i2c_master.h index 39ba782f8bba5..da74c9faa299d 100644 --- a/include/nuttx/i2c/i2c_master.h +++ b/include/nuttx/i2c/i2c_master.h @@ -171,6 +171,38 @@ # define I2C_RESET(d) ((d)->ops->reset(d)) #endif +/**************************************************************************** + * Name: I2C_SETUP + * + * Description: + * I2c master initialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2C_SETUP(d) ((d)->ops->setup(d)) + +/**************************************************************************** + * Name: I2C_SHUTDOWN + * + * Description: + * I2c master uninitialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2C_SHUTDOWN(d) ((d)->ops->shutdown(d)) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -186,6 +218,8 @@ struct i2c_ops_s #ifdef CONFIG_I2C_RESET CODE int (*reset)(FAR struct i2c_master_s *dev); #endif + CODE int (*setup)(FAR struct i2c_master_s *dev); + CODE int (*shutdown)(FAR struct i2c_master_s *dev); }; /* This structure contains the full state of I2C as needed for a specific diff --git a/include/nuttx/i2c/i2c_slave.h b/include/nuttx/i2c/i2c_slave.h index ee33157958e57..dd1c6c39c1367 100644 --- a/include/nuttx/i2c/i2c_slave.h +++ b/include/nuttx/i2c/i2c_slave.h @@ -170,6 +170,38 @@ #define I2CS_REGISTERCALLBACK(d,c,a) ((d)->ops->registercallback(d,c,a)) +/**************************************************************************** + * Name: I2CS_SETUP + * + * Description: + * I2c slave initialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2CS_SETUP(d) ((d)->ops->setup(d)) + +/**************************************************************************** + * Name: I2CS_SHUTDOWN + * + * Description: + * I2c slave uninitialize. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#define I2CS_SHUTDOWN(d) ((d)->ops->shutdown(d)) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -198,6 +230,8 @@ struct i2c_slaveops_s int (*registercallback)(FAR struct i2c_slave_s *dev, i2c_slave_callback_t *callback, FAR void *arg); + int (*setup)(FAR struct i2c_slave_s *dev); + int (*shutdown)(FAR struct i2c_slave_s *dev); }; /* I2C private data. This structure only defines the initial fields of the From 4e6f3e936051b0f2bf772c881493bfe8b76beb42 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Wed, 20 Dec 2023 09:48:56 +0800 Subject: [PATCH 11/81] I2c slave: Add POLLOUT event for notifie slave write success Signed-off-by: Shoukui Zhang --- drivers/i2c/i2c_slave_driver.c | 41 +++++++++++++++++++++++++++------- include/nuttx/i2c/i2c_slave.h | 9 +++++++- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c index 6403847077882..feb69db613ed0 100644 --- a/drivers/i2c/i2c_slave_driver.c +++ b/drivers/i2c/i2c_slave_driver.c @@ -91,6 +91,10 @@ struct i2c_slave_driver_s sem_t wait; + /* I2C Slave write flag */ + + bool writeable; + /* Mutual exclusion */ mutex_t lock; @@ -359,6 +363,11 @@ static ssize_t i2c_slave_write(FAR struct file *filep, write_bytes = MIN(buflen, CONFIG_I2C_SLAVE_WRITEBUFSIZE); memcpy(priv->write_buffer, buffer, write_bytes); ret = I2CS_WRITE(priv->dev, priv->write_buffer, write_bytes); + if (ret >= 0) + { + priv->writeable = false; + } + nxmutex_unlock(&priv->lock); return ret < 0 ? ret : write_bytes; } @@ -371,7 +380,7 @@ static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) { FAR struct i2c_slave_driver_s *priv; - int ret; + int ret = OK; DEBUGASSERT(filep->f_inode->i_private != NULL); @@ -402,6 +411,11 @@ static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, eventset |= POLLIN; } + if (priv->writeable) + { + eventset |= POLLOUT; + } + poll_notify(&priv->fds, 1, eventset); } else if (fds->priv != NULL) @@ -464,26 +478,36 @@ static int i2c_slave_unlink(FAR struct inode *inode) } #endif -static int i2c_slave_callback(FAR void *arg, size_t length) +static int i2c_slave_callback(FAR void *arg, i2c_slave_complete_t status, + size_t length) { FAR struct i2c_slave_driver_s *priv = arg; + pollevent_t events; int semcount; /* Get exclusive access to the I2C Slave driver state structure */ nxmutex_lock(&priv->lock); - priv->read_index = 0; - priv->read_length = length; + if (status == I2CS_RX_COMPLETE) + { + events = POLLIN; + priv->read_index = 0; + priv->read_length = length; - while (nxsem_get_value(&priv->wait, &semcount) >= 0 && semcount <= 1) + while (nxsem_get_value(&priv->wait, &semcount) >= 0 && semcount <= 1) + { + nxsem_post(&priv->wait); + } + } + else { - nxsem_post(&priv->wait); + events = POLLOUT; + priv->writeable = true; } nxmutex_unlock(&priv->lock); - - poll_notify(&priv->fds, 1, POLLIN); + poll_notify(&priv->fds, 1, events); return OK; } @@ -541,6 +565,7 @@ int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr, priv->dev = dev; priv->addr = addr; priv->nbits = nbits; + priv->writeable = true; ret = I2CS_READ(priv->dev, priv->read_buffer, CONFIG_I2C_SLAVE_READBUFSIZE); diff --git a/include/nuttx/i2c/i2c_slave.h b/include/nuttx/i2c/i2c_slave.h index dd1c6c39c1367..2bbaccf618508 100644 --- a/include/nuttx/i2c/i2c_slave.h +++ b/include/nuttx/i2c/i2c_slave.h @@ -206,9 +206,16 @@ * Public Types ****************************************************************************/ +typedef enum i2c_slave_complete_e +{ + I2CS_RX_COMPLETE = 0, + I2CS_TX_COMPLETE +} i2c_slave_complete_t; + /* The callback function */ -typedef int (i2c_slave_callback_t)(void *arg, size_t rx_len); +typedef int (i2c_slave_callback_t)(FAR void *arg, i2c_slave_complete_t state, + size_t len); /* The I2C vtable */ From f94160095ea2411317b3b37f177acbca4544ecd1 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Thu, 21 Dec 2023 10:43:26 +0800 Subject: [PATCH 12/81] Adapt i2c slave callback interface for rp2040 and s32k11x Signed-off-by: Shoukui Zhang --- arch/arm/src/rp2040/rp2040_i2c_slave.c | 15 ++++++++++++--- arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c | 12 +++++++++++- .../rddrone-bms772/src/s32k1xx_smbus_sbd.c | 15 ++++++++++++--- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/arch/arm/src/rp2040/rp2040_i2c_slave.c b/arch/arm/src/rp2040/rp2040_i2c_slave.c index af9e057dc58d6..c2b1d9f0665f5 100644 --- a/arch/arm/src/rp2040/rp2040_i2c_slave.c +++ b/arch/arm/src/rp2040/rp2040_i2c_slave.c @@ -152,6 +152,7 @@ static int i2c_interrupt(int irq, void *context, void *arg) rp2040_i2c_slave_t *priv = (rp2040_i2c_slave_t *)arg; uint32_t data_cmd; uint32_t state; + int length; state = getreg32(RP2040_I2C_IC_INTR_STAT(priv->controller)); @@ -159,7 +160,8 @@ static int i2c_interrupt(int irq, void *context, void *arg) if (state & RP2040_I2C_IC_INTR_STAT_R_RD_REQ) { - if (priv->tx_buf_ptr < priv->tx_buf_end) + length = priv->tx_buf_end - priv->tx_buf_ptr; + if (length > 0) { while (priv->tx_buf_ptr < priv->tx_buf_end && getreg32(RP2040_I2C_IC_TXFLR(priv->controller)) @@ -168,6 +170,11 @@ static int i2c_interrupt(int irq, void *context, void *arg) putreg32(*priv->tx_buf_ptr++, RP2040_I2C_IC_DATA_CMD(priv->controller)); } + + if (priv->callback != NULL) + { + priv->callback(priv, I2CS_TX_COMPLETE, length); + } } else { @@ -203,7 +210,8 @@ static int i2c_interrupt(int irq, void *context, void *arg) { if (priv->callback != NULL && priv->rx_buf_ptr > priv->rx_buffer) { - priv->callback(priv, priv->rx_buf_ptr - priv->rx_buffer); + priv->callback(priv, I2CS_RX_COMPLETE, + priv->rx_buf_ptr - priv->rx_buffer); priv->rx_buf_ptr = priv->rx_buffer; } @@ -216,7 +224,8 @@ static int i2c_interrupt(int irq, void *context, void *arg) { if (priv->callback != NULL && priv->rx_buf_ptr > priv->rx_buffer) { - priv->callback(priv, priv->rx_buf_ptr - priv->rx_buffer); + priv->callback(priv, I2CS_RX_COMPLETE, + priv->rx_buf_ptr - priv->rx_buffer); priv->rx_buf_ptr = priv->rx_buffer; } diff --git a/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c b/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c index 32792bbb0fc1b..533f97c5855b0 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c +++ b/arch/arm/src/s32k1xx/s32k1xx_lpi2c_slave.c @@ -427,9 +427,19 @@ static int s32k1xx_lpi2c_slave_isr_process( if ((priv->read_bufindex > 0) && (priv->callback != NULL)) { - priv->callback(priv->callback_arg, priv->read_bufindex); + priv->callback(priv->callback_arg, I2CS_RX_COMPLETE, + priv->read_bufindex); priv->read_bufindex = 0; } + + /* Execute the registered callback function if data was send */ + + if ((priv->write_bufindex > 0) && (priv->callback != NULL)) + { + priv->callback(priv->callback_arg, I2CS_TX_COMPLETE, + priv->write_bufindex); + priv->write_bufindex = 0; + } } /* Slave Bit Error (abort current transfer) */ diff --git a/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c b/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c index c870a77e243df..0d48fb45a0ebd 100644 --- a/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c +++ b/boards/arm/s32k1xx/rddrone-bms772/src/s32k1xx_smbus_sbd.c @@ -384,10 +384,12 @@ static ssize_t smbus_sbd_write(struct file *filep, const char *buffer, * ****************************************************************************/ -static int smbus_sbd_callback(void *arg, size_t rx_len) +static int smbus_sbd_callback(void *arg, i2c_slave_complete_t state, + size_t rx_len) { struct smbus_sbd_dev_s *dev; int buffer_length; + int ret = OK; int i; /* Retrieve the pointer to the SMBus SBD slave device struct */ @@ -726,8 +728,15 @@ static int smbus_sbd_callback(void *arg, size_t rx_len) * request has been received. */ - return I2CS_WRITE(dev->i2c_slave_dev, (const uint8_t *)dev->write_buffer, - buffer_length); + ret = I2CS_WRITE(dev->i2c_slave_dev, (const uint8_t *)dev->write_buffer, + buffer_length); + if (ret >= 0) + { + dev->i2c_slave_dev->callback(dev->i2c_slave_dev->callback_arg, + I2CS_TX_COMPLETE, buffer_length); + } + + return ret; } /**************************************************************************** From 75fa94af023b5a01bdff3021ccfe6e41bfdb4a9b Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Mon, 25 Dec 2023 20:46:06 +0800 Subject: [PATCH 13/81] i2c_slave: add poll waiters array Signed-off-by: Shoukui Zhang --- drivers/i2c/Kconfig | 7 +++++++ drivers/i2c/i2c_slave_driver.c | 23 +++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index a0883f5a20440..dfa74af883c7b 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -46,6 +46,13 @@ config I2C_SLAVE_WRITEBUFSIZE ---help--- I2C Slave write buffer size +config I2C_SLAVE_NPOLLWAITERS + int "Number of i2c slave poll waiters" + default 1 + depends on I2C_SLAVE_DRIVER + ---help--- + Number of waiters to i2c slave poll + endmenu # I2C Slave Support config I2C_POLLED diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c index feb69db613ed0..79ade78f6fb32 100644 --- a/drivers/i2c/i2c_slave_driver.c +++ b/drivers/i2c/i2c_slave_driver.c @@ -101,7 +101,7 @@ struct i2c_slave_driver_s /* The poll waiter */ - FAR struct pollfd *fds; + FAR struct pollfd *fds[CONFIG_I2C_SLAVE_NPOLLWAITERS]; /* Number of open references */ @@ -381,6 +381,7 @@ static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, { FAR struct i2c_slave_driver_s *priv; int ret = OK; + int i; DEBUGASSERT(filep->f_inode->i_private != NULL); @@ -395,12 +396,17 @@ static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, { pollevent_t eventset = 0; - if (priv->fds == NULL) + for (i = 0; i < CONFIG_I2C_SLAVE_NPOLLWAITERS; i++) { - priv->fds = fds; - fds->priv = &priv->fds; + if (!priv->fds[i]) + { + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } } - else + + if (i == CONFIG_I2C_SLAVE_NPOLLWAITERS) { ret = -EBUSY; goto out; @@ -416,11 +422,12 @@ static int i2c_slave_poll(FAR struct file *filep, FAR struct pollfd *fds, eventset |= POLLOUT; } - poll_notify(&priv->fds, 1, eventset); + poll_notify(priv->fds, CONFIG_I2C_SLAVE_NPOLLWAITERS, eventset); } else if (fds->priv != NULL) { - priv->fds = NULL; + struct pollfd **slot = fds->priv; + *slot = NULL; fds->priv = NULL; } @@ -507,7 +514,7 @@ static int i2c_slave_callback(FAR void *arg, i2c_slave_complete_t status, } nxmutex_unlock(&priv->lock); - poll_notify(&priv->fds, 1, events); + poll_notify(priv->fds, CONFIG_I2C_SLAVE_NPOLLWAITERS, events); return OK; } From 5df3f5d4f7289142979215232d8f3d299628c7bb Mon Sep 17 00:00:00 2001 From: zhangshoukui Date: Wed, 7 Aug 2024 10:16:06 +0800 Subject: [PATCH 14/81] Added the documentation about the iic slave driver Signed-off-by: zhangshoukui --- Documentation/components/drivers/special/i2c.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/components/drivers/special/i2c.rst b/Documentation/components/drivers/special/i2c.rst index fa722cbf2bd36..08d1464f31e3c 100644 --- a/Documentation/components/drivers/special/i2c.rst +++ b/Documentation/components/drivers/special/i2c.rst @@ -21,3 +21,11 @@ I2C Device Drivers - **Examples**: ``arch/z80/src/ez80/ez80_i2c.c``, ``arch/z80/src/z8/z8_i2c.c``, etc. + +- ``struct i2c_slaveops_s``. Each I2C slave device driver must implement + an instance of ``struct i2c_slaveops_s``. That structure defines a call + table with the following methods: + +- **Binding I2C Slave Drivers**. I2C slave drivers are normally directly + accessed by user code, We can read and write to device nodes using posix + interfaces. From 3f021d5429da49a1919da90fa746c19d8817d770 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Thu, 8 Aug 2024 06:18:26 +0800 Subject: [PATCH 15/81] riscv/fork: fix fp/s0 field position The fp/s0 field position shall be in line with the macro FORK_FP_OFFSET/FORK_S0_OFFSET. Signed-off-by: Yanfeng Liu --- arch/risc-v/src/common/riscv_fork.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/risc-v/src/common/riscv_fork.h b/arch/risc-v/src/common/riscv_fork.h index 26a2ec5925d8c..bfb2560f1faa0 100644 --- a/arch/risc-v/src/common/riscv_fork.h +++ b/arch/risc-v/src/common/riscv_fork.h @@ -119,6 +119,11 @@ struct fork_s { /* CPU registers */ +#ifdef CONFIG_RISCV_FRAMEPOINTER + uintreg_t fp; /* Frame pointer */ +#else + uintreg_t s0; /* Saved register s0 */ +#endif uintreg_t s1; /* Saved register s1 */ uintreg_t s2; /* Saved register s2 */ uintreg_t s3; /* Saved register s3 */ @@ -130,11 +135,6 @@ struct fork_s uintreg_t s9; /* Saved register s9 */ uintreg_t s10; /* Saved register s10 */ uintreg_t s11; /* Saved register s11 */ -#ifdef CONFIG_RISCV_FRAMEPOINTER - uintreg_t fp; /* Frame pointer */ -#else - uintreg_t s0; /* Saved register s0 */ -#endif uintreg_t sp; /* Stack pointer */ uintreg_t ra; /* Return address */ #ifdef RISCV_SAVE_GP From 77cfbf8914935c2b81329840c001fc1036fd9bf8 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Thu, 8 Aug 2024 06:25:58 +0800 Subject: [PATCH 16/81] riscv/fork: fix gp register handling This fixes the handling of gp register in fork. Signed-off-by: Yanfeng Liu --- arch/risc-v/src/common/fork.S | 4 ++++ arch/risc-v/src/common/riscv_fork.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/common/fork.S b/arch/risc-v/src/common/fork.S index 9134266feca0a..a7ca257f05998 100644 --- a/arch/risc-v/src/common/fork.S +++ b/arch/risc-v/src/common/fork.S @@ -123,6 +123,10 @@ up_fork: REGSTORE s0, FORK_S0_OFFSET(sp) #endif +#ifdef RISCV_SAVE_GP + REGSTORE gp, FORK_GP_OFFSET(sp) +#endif + addi a0, sp, FORK_SIZEOF REGSTORE a0, FORK_SP_OFFSET(sp) /* original SP */ REGSTORE x1, FORK_RA_OFFSET(sp) /* return address */ diff --git a/arch/risc-v/src/common/riscv_fork.c b/arch/risc-v/src/common/riscv_fork.c index 9187cc6ab5ef7..40e463b2aef7c 100644 --- a/arch/risc-v/src/common/riscv_fork.c +++ b/arch/risc-v/src/common/riscv_fork.c @@ -308,7 +308,7 @@ pid_t riscv_fork(const struct fork_s *context) #endif child->cmn.xcp.regs[REG_SP] = newsp; /* Stack pointer */ #ifdef RISCV_SAVE_GP - child->cmn.xcp.regs[REG_GP] = newsp; /* Global pointer */ + child->cmn.xcp.regs[REG_GP] = context->gp; /* Global pointer */ #endif #ifdef CONFIG_ARCH_FPU fregs = riscv_fpuregs(&child->cmn); From 8399a780d810beadf7a5cc3b34b7dfed9bb2bb6e Mon Sep 17 00:00:00 2001 From: Daniel Jasinski Date: Wed, 7 Aug 2024 15:22:01 -0400 Subject: [PATCH 17/81] build: Fix Toolchain.cmake for CONFIG_SIM_ASAN enabled This commit adds missing add_link_options to specify sanitizers also during linking stage. Signed-off-by: Daniel Jasinski --- arch/sim/src/cmake/Toolchain.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sim/src/cmake/Toolchain.cmake b/arch/sim/src/cmake/Toolchain.cmake index c787a9fe3076f..c1caedd3c6e39 100644 --- a/arch/sim/src/cmake/Toolchain.cmake +++ b/arch/sim/src/cmake/Toolchain.cmake @@ -78,12 +78,14 @@ if(CONFIG_SIM_ASAN) add_compile_options(-fsanitize-address-use-after-scope) add_compile_options(-fsanitize=pointer-compare) add_compile_options(-fsanitize=pointer-subtract) + add_link_options(-fsanitize=address) elseif(CONFIG_MM_KASAN_ALL) add_compile_options(-fsanitize=kernel-address) endif() if(CONFIG_SIM_UBSAN) add_compile_options(-fsanitize=undefined) + add_link_options(-fsanitize=undefined) else() if(CONFIG_MM_UBSAN_ALL) add_compile_options(${CONFIG_MM_UBSAN_OPTION}) From 3862b717286ddd6ad8375639daa294844b817ade Mon Sep 17 00:00:00 2001 From: Lup Yuen Lee Date: Thu, 8 Aug 2024 06:32:23 +0800 Subject: [PATCH 18/81] risc-v/qemu-rv: Add Build Config for leds64_rust This PR adds a new Build Config `rv-virt:leds64_rust` that builds the Rust App `leds_rust` for QEMU RISC-V 64-bit. The build requires the [Rust Target `riscv64gc-unknown-none-elf`](https://github.com/apache/nuttx/pull/12858): ```bash rustup target add riscv64gc-unknown-none-elf ``` New Files: `boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig`: Add new Build Config `rv-virt:leds64_rust` Updated Docs: `applications/examples/leds_rust/index.rst`: Add `leds_rust` example app `platforms/risc-v/qemu-rv/boards/rv-virt/index.rst`: Add `rv-virt:leds64_rust` config --- .../applications/examples/leds_rust/index.rst | 6 ++ .../risc-v/qemu-rv/boards/rv-virt/index.rst | 5 ++ .../rv-virt/configs/leds64_rust/defconfig | 76 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 Documentation/applications/examples/leds_rust/index.rst create mode 100644 boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig diff --git a/Documentation/applications/examples/leds_rust/index.rst b/Documentation/applications/examples/leds_rust/index.rst new file mode 100644 index 0000000000000..11ab85770f908 --- /dev/null +++ b/Documentation/applications/examples/leds_rust/index.rst @@ -0,0 +1,6 @@ +================================= +``leds_rust`` Toggle LEDs in Rust +================================= + +This is a simple test in Rust of the board LED driver at +``nuttx/drivers/leds/userled_*.c``. diff --git a/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst index e0a2a8a2b37af..16a186960043b 100644 --- a/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst +++ b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst @@ -257,6 +257,11 @@ leds64 Similar to the `nsh64`_ configuration, but with User LEDs support for 64-bit RISC-V. +leds64_rust +----------- + +Similar to the `leds64`_ configuration, but with ``leds_rust`` example enabled. + netnsh ------ diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig new file mode 100644 index 0000000000000..696083e9846ed --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/configs/leds64_rust/defconfig @@ -0,0 +1,76 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +CONFIG_16550_ADDRWIDTH=0 +CONFIG_16550_UART0=y +CONFIG_16550_UART0_BASE=0x10000000 +CONFIG_16550_UART0_CLOCK=3686400 +CONFIG_16550_UART0_IRQ=37 +CONFIG_16550_UART0_SERIAL_CONSOLE=y +CONFIG_16550_UART=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="rv-virt" +CONFIG_ARCH_BOARD_QEMU_RV_VIRT=y +CONFIG_ARCH_CHIP="qemu-rv" +CONFIG_ARCH_CHIP_QEMU_RV64=y +CONFIG_ARCH_CHIP_QEMU_RV=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_A=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_C=y +CONFIG_ARCH_CHIP_QEMU_RV_ISA_M=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BCH=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=6366 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEVICE_TREE=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_LEDS=y +CONFIG_EXAMPLES_LEDS_RUST=y +CONFIG_FS_HOSTFS=y +CONFIG_FS_PROCFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_LIBM=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/system/bin" +CONFIG_RAM_SIZE=33554432 +CONFIG_RAM_START=0x80000000 +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RISCV_SEMIHOSTING_HOSTFS=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SERIAL_UART_ARCH_MMIO=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2021 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=3072 +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_USEC_PER_TICK=1000 +CONFIG_USERLED=y +CONFIG_USERLED_LOWER=y From 3f3ad34f429ec071b7610ba0360c463c9fa5db84 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Wed, 27 Mar 2024 19:21:45 +0800 Subject: [PATCH 19/81] Fix greater-than-or-equal-to-zero issue unsigned_compare: This greater-than-or-equal-to-zero comparison without a signed value is always true. conn->lc_crefs >= 0 Signed-off-by: Shoukui Zhang --- net/local/local_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/local/local_conn.c b/net/local/local_conn.c index 55986393c5a1c..55e82899ff6ba 100644 --- a/net/local/local_conn.c +++ b/net/local/local_conn.c @@ -317,7 +317,7 @@ void local_free(FAR struct local_conn_s *conn) void local_addref(FAR struct local_conn_s *conn) { - DEBUGASSERT(conn->lc_crefs >= 0 && conn->lc_crefs < 255); + DEBUGASSERT(conn->lc_crefs < 255); conn->lc_crefs++; } From a3b94383ed6fb8df25f4e3df5dfa5cd47e9b9ec9 Mon Sep 17 00:00:00 2001 From: Shoukui Zhang Date: Sun, 28 Apr 2024 21:50:43 +0800 Subject: [PATCH 20/81] tmpfs: write end of file if open flag with O_APPEND Signed-off-by: Shoukui Zhang --- fs/tmpfs/fs_tmpfs.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c index e4f5e6b2579b5..34f2233630103 100644 --- a/fs/tmpfs/fs_tmpfs.c +++ b/fs/tmpfs/fs_tmpfs.c @@ -1605,7 +1605,15 @@ static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, /* Handle attempts to write beyond the end of the file */ - startpos = filep->f_pos; + if ((filep->f_oflags & O_APPEND) != 0) + { + startpos = tfo->tfo_size; + } + else + { + startpos = filep->f_pos; + } + nwritten = buflen; endpos = startpos + buflen; @@ -1625,13 +1633,14 @@ static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer, if (tfo->tfo_data != NULL) { memcpy(&tfo->tfo_data[startpos], buffer, nwritten); - filep->f_pos += nwritten; } else { DEBUGASSERT(tfo->tfo_size == 0 && nwritten == 0); } + filep->f_pos = endpos; + /* Release the lock on the file */ tmpfs_unlock_file(tfo); From 9cc25523b175b4e9f4b16a7cb6db231194113eb2 Mon Sep 17 00:00:00 2001 From: chao an Date: Sun, 4 Aug 2024 22:30:16 +0800 Subject: [PATCH 21/81] spinlock: add support of spin_trylock_irqsave() trylock spinlock in critical section: bool spin_trylock_irqsave(FAR volatile spinlock_t *lock, irqstate_t flags); bool spin_trylock_irqsave_wo_note(FAR volatile spinlock_t *lock, irqstate_t flags); Signed-off-by: chao an --- include/nuttx/spinlock.h | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/include/nuttx/spinlock.h b/include/nuttx/spinlock.h index 1d915a6314a51..ebb5d91328c59 100644 --- a/include/nuttx/spinlock.h +++ b/include/nuttx/spinlock.h @@ -626,6 +626,81 @@ irqstate_t spin_lock_irqsave(FAR volatile spinlock_t *lock) # define spin_lock_irqsave(l) ((void)(l), up_irq_save()) #endif +/**************************************************************************** + * Name: spin_trylock_irqsave_wo_note + * + * Description: + * Try once to lock the spinlock. Do not wait if the spinlock is already + * locked. + * + * This implementation is the same as the above spin_trylock() except that + * it does not perform instrumentation logic. + * + * Input Parameters: + * lock - A reference to the spinlock object to lock. + * flags - flag of interrupts status + * + * Returned Value: + * SP_LOCKED - Failure, the spinlock was already locked + * SP_UNLOCKED - Success, the spinlock was successfully locked + * + * Assumptions: + * Not running at the interrupt level. + * + ****************************************************************************/ + +#ifdef CONFIG_SPINLOCK +# define spin_trylock_irqsave_wo_note(l, f) \ +({ \ + f = up_irq_save(); \ + spin_trylock_wo_note(l) ? \ + true : ({ up_irq_restore(f); false; }); \ +}) +#else +# define spin_trylock_irqsave_wo_note(l, f) \ +({ \ + (void)(l); \ + f = up_irq_save(); \ + true; \ +}) +#endif /* CONFIG_SPINLOCK */ + +/**************************************************************************** + * Name: spin_trylock_irqsave + * + * Description: + * Try once to lock the spinlock. Do not wait if the spinlock is already + * locked. + * + * Input Parameters: + * lock - A reference to the spinlock object to lock. + * flags - flag of interrupts status + * + * Returned Value: + * SP_LOCKED - Failure, the spinlock was already locked + * SP_UNLOCKED - Success, the spinlock was successfully locked + * + * Assumptions: + * Not running at the interrupt level. + * + ****************************************************************************/ + +#ifdef CONFIG_SPINLOCK +# define spin_trylock_irqsave(l, f) \ +({ \ + f = up_irq_save(); \ + spin_trylock(l) ? \ + true : ({ up_irq_restore(f); false; }); \ +}) +#else +# define spin_trylock_irqsave(l, f) \ +({ \ + (void)(l); \ + f = up_irq_save(); \ + true; \ +}) +#endif /* CONFIG_SPINLOCK */ + /**************************************************************************** * Name: spin_unlock_irqrestore_wo_note * From bb29c39d5056474e5bc66c6f610de067b03fa1b4 Mon Sep 17 00:00:00 2001 From: rongyichang Date: Wed, 24 Jul 2024 20:09:25 +0800 Subject: [PATCH 22/81] drivers/touchscreen: add grab for touchscreen Providing the capability for applications to exclusively handle touch events Signed-off-by: rongyichang --- .../drivers/character/touchscreen.rst | 28 +++++ drivers/input/touchscreen_upper.c | 102 ++++++++++++++---- include/nuttx/input/touchscreen.h | 6 +- 3 files changed, 116 insertions(+), 20 deletions(-) diff --git a/Documentation/components/drivers/character/touchscreen.rst b/Documentation/components/drivers/character/touchscreen.rst index 00448e30afff0..ce47444ed2c0c 100644 --- a/Documentation/components/drivers/character/touchscreen.rst +++ b/Documentation/components/drivers/character/touchscreen.rst @@ -36,3 +36,31 @@ found in the following locations: ``boards////src/`` directory for boards that use an external touchscreen controller chip. + +Application Programming Interface +================================= + +The first thing to be done in order to use the touchscreen driver from an +application is to include the correct header filer. It contains the +Application Programming Interface to the driver. To do so, include + +.. code-block:: c + + #include + +Touchscreen driver is registered as a POSIX character device file into +``/dev`` namespace. It is necessary to open the device to get a file descriptor +for further operations. This can be done with standard POSIX ``open()`` call. + +The driver is accessed through ``read``, ``write``, ``poll`` and ``ioctl`` +interface, Following ``ioctl`` commands are available: + + * :c:macro:`TSIOC_GRAB` + +.. c:macro:: TSIOC_GRAB + +This command let the current handle has the device grabbed. When a handle grabs +a device it becomes sole recipient for all touchscreen events coming from the +device. An argument is an ``int32_t`` variable to enable or disable the grab. + + diff --git a/drivers/input/touchscreen_upper.c b/drivers/input/touchscreen_upper.c index b85930dab9d3e..18e5471c2244f 100644 --- a/drivers/input/touchscreen_upper.c +++ b/drivers/input/touchscreen_upper.c @@ -61,6 +61,7 @@ struct touch_upperhalf_s mutex_t lock; /* Manages exclusive access to this structure */ struct list_node head; /* Opened file buffer chain header node */ FAR struct touch_lowerhalf_s *lower; /* A pointer of lower half instance */ + FAR struct touch_openpriv_s *grab; /* A pointer of grab file */ }; /**************************************************************************** @@ -78,6 +79,9 @@ static int touch_ioctl(FAR struct file *filep, int cmd, static int touch_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); +static void touch_event_notify(FAR struct touch_openpriv_s *openpriv, + FAR const struct touch_sample_s *sample); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -163,6 +167,11 @@ static int touch_close(FAR struct file *filep) return ret; } + if (upper->grab == openpriv) + { + upper->grab = NULL; + } + list_delete(&openpriv->node); circbuf_uninit(&openpriv->circbuf); nxsem_destroy(&openpriv->waitsem); @@ -250,9 +259,10 @@ static ssize_t touch_read(FAR struct file *filep, FAR char *buffer, static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { - FAR struct inode *inode = filep->f_inode; - FAR struct touch_upperhalf_s *upper = inode->i_private; - FAR struct touch_lowerhalf_s *lower = upper->lower; + FAR struct touch_openpriv_s *openpriv = filep->f_priv; + FAR struct inode *inode = filep->f_inode; + FAR struct touch_upperhalf_s *upper = inode->i_private; + FAR struct touch_lowerhalf_s *lower = upper->lower; int ret; ret = nxmutex_lock(&upper->lock); @@ -261,13 +271,48 @@ static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) return ret; } - if (lower->control) - { - ret = lower->control(lower, cmd, arg); - } - else + switch (cmd) { - ret = -ENOTTY; + case TSIOC_GRAB: + { + int enable = (int)arg; + ret = OK; + if (enable) + { + if (upper->grab != NULL) + { + ret = -EBUSY; + } + else + { + upper->grab = openpriv; + } + } + else + { + if (upper->grab != openpriv) + { + ret = -EINVAL; + } + else + { + upper->grab = NULL; + } + } + } + break; + default: + { + if (lower->control) + { + ret = lower->control(lower, cmd, arg); + } + else + { + ret = -ENOTTY; + } + } + break; } nxmutex_unlock(&upper->lock); @@ -321,6 +366,27 @@ static int touch_poll(FAR struct file *filep, struct pollfd *fds, bool setup) return ret; } +/**************************************************************************** + * Name: touch_event_notify + ****************************************************************************/ + +static void touch_event_notify(FAR struct touch_openpriv_s *openpriv, + FAR const struct touch_sample_s *sample) +{ + int semcount; + + circbuf_overwrite(&openpriv->circbuf, sample, + SIZEOF_TOUCH_SAMPLE_S(sample->npoints)); + + nxsem_get_value(&openpriv->waitsem, &semcount); + if (semcount < 1) + { + nxsem_post(&openpriv->waitsem); + } + + poll_notify(&openpriv->fds, 1, POLLIN); +} + /**************************************************************************** * Public Function ****************************************************************************/ @@ -333,25 +399,23 @@ void touch_event(FAR void *priv, FAR const struct touch_sample_s *sample) { FAR struct touch_upperhalf_s *upper = priv; FAR struct touch_openpriv_s *openpriv; - int semcount; if (nxmutex_lock(&upper->lock) < 0) { return; } - list_for_every_entry(&upper->head, openpriv, struct touch_openpriv_s, node) + if (upper->grab) { - circbuf_overwrite(&openpriv->circbuf, sample, - SIZEOF_TOUCH_SAMPLE_S(sample->npoints)); - - nxsem_get_value(&openpriv->waitsem, &semcount); - if (semcount < 1) + touch_event_notify(upper->grab, sample); + } + else + { + list_for_every_entry(&upper->head, openpriv, + struct touch_openpriv_s, node) { - nxsem_post(&openpriv->waitsem); + touch_event_notify(openpriv, sample); } - - poll_notify(&openpriv->fds, 1, POLLIN); } nxmutex_unlock(&upper->lock); diff --git a/include/nuttx/input/touchscreen.h b/include/nuttx/input/touchscreen.h index 7a191bb943d28..34801e11deb8e 100644 --- a/include/nuttx/input/touchscreen.h +++ b/include/nuttx/input/touchscreen.h @@ -89,8 +89,12 @@ * int Y threshold value */ +#define TSIOC_GRAB _TSIOC(0x000e) /* arg: Pointer to + * int for enable grab + */ + #define TSC_FIRST 0x0001 /* First common command */ -#define TSC_NCMDS 13 /* Thirteen common commands */ +#define TSC_NCMDS 14 /* Fourteen common commands */ /* Backward compatible IOCTL */ From 2af8a886ab5bc7f9ca031e4664202226d983362d Mon Sep 17 00:00:00 2001 From: nuttxs Date: Thu, 8 Aug 2024 17:24:17 +0800 Subject: [PATCH 23/81] arch/xtensa/esp32: Replace nxsig_usleep() with up_udelay() to avoid context switching, and the actual time difference caused by the setting of TICK in nxsig_usleep() is quite large. --- arch/xtensa/src/esp32/esp32_emac.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/arch/xtensa/src/esp32/esp32_emac.c b/arch/xtensa/src/esp32/esp32_emac.c index 8734c9ff5871c..292d5068d6d59 100644 --- a/arch/xtensa/src/esp32/esp32_emac.c +++ b/arch/xtensa/src/esp32/esp32_emac.c @@ -233,6 +233,7 @@ struct esp32_emac_s ****************************************************************************/ static struct esp32_emac_s s_esp32_emac; +static mutex_t g_lock = NXMUTEX_INITIALIZER; /**************************************************************************** * Private Function Prototypes @@ -564,7 +565,7 @@ static int emac_config(void) /* Hardware reset PHY chip */ esp32_gpiowrite(EMAC_PHYRST_PIN, false); - nxsig_usleep(50); + up_udelay(50); esp32_gpiowrite(EMAC_PHYRST_PIN, true); #endif @@ -597,7 +598,7 @@ static int emac_config(void) break; } - nxsig_usleep(10); + up_udelay(10); } if (i >= EMAC_RESET_TO) @@ -942,7 +943,7 @@ static int emac_read_phy(uint16_t dev_addr, for (i = 0; i < EMAC_READPHY_TO; i++) { - nxsig_usleep(100); + up_udelay(100); val = emac_get_reg(EMAC_MAR_OFFSET); if (!(val & EMAC_PIB)) @@ -1004,7 +1005,7 @@ static int emac_write_phy(uint16_t dev_addr, for (i = 0; i < EMAC_WRITEPHY_TO; i++) { - nxsig_usleep(100); + up_udelay(100); val = emac_get_reg(EMAC_MAR_OFFSET); if (!(val & EMAC_PIB)) @@ -1047,7 +1048,7 @@ static int emac_wait_linkup(struct esp32_emac_s *priv) for (i = 0; i < EMAC_WAITLINK_TO; i++) { - nxsig_usleep(10); + up_udelay(10); ret = emac_read_phy(EMAC_PHY_ADDR, MII_MSR, &val); if (ret != 0) @@ -1184,7 +1185,7 @@ static int emac_init_phy(struct esp32_emac_s *priv) for (i = 0; i < EMAC_RSTPHY_TO; i++) { - nxsig_usleep(100); + up_udelay(100); ret = emac_read_phy(EMAC_PHY_ADDR, MII_MCR, &val); if (ret != 0) @@ -1947,11 +1948,16 @@ static int emac_rmmac(struct net_driver_s *dev, const uint8_t *mac) #ifdef CONFIG_NETDEV_IOCTL static int emac_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { -#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) - struct esp32_emacmac_s *priv = NET2PRIV(dev); -#endif int ret; + /* Get exclusive access to the device structures */ + + ret = nxmutex_lock(&g_lock); + if (ret < 0) + { + return ret; + } + switch (cmd) { #ifdef CONFIG_NETDEV_PHY_IOCTL @@ -2003,6 +2009,7 @@ static int emac_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) break; } + nxmutex_unlock(&g_lock); return ret; } #endif /* CONFIG_NETDEV_IOCTL */ From 6986cd4105ddfe3b5aa71eb7ae746a792af56e1a Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Fri, 5 Jul 2024 09:42:13 +0800 Subject: [PATCH 24/81] arch/riscv: unify in-kernel syscall This generalizes the in-kernel syscall approach from KERNEL mode to all build modes so that to unify in-kernel syscall invocations. As a result, machine mode ECALL and the supervisor folder are no longer needed. Signed-off-by: Yanfeng Liu --- arch/risc-v/include/syscall.h | 3 +- arch/risc-v/src/common/CMakeLists.txt | 3 +- arch/risc-v/src/common/Make.defs | 6 ++-- arch/risc-v/src/common/riscv_exception.c | 5 ---- .../{supervisor => }/riscv_perform_syscall.c | 2 +- .../src/common/{supervisor => }/riscv_sbi.c | 2 +- .../common/{supervisor => }/riscv_syscall.S | 2 +- .../src/common/supervisor/CMakeLists.txt | 28 ------------------- arch/risc-v/src/common/supervisor/Make.defs | 28 ------------------- 9 files changed, 10 insertions(+), 69 deletions(-) rename arch/risc-v/src/common/{supervisor => }/riscv_perform_syscall.c (97%) rename arch/risc-v/src/common/{supervisor => }/riscv_sbi.c (98%) rename arch/risc-v/src/common/{supervisor => }/riscv_syscall.S (98%) delete mode 100644 arch/risc-v/src/common/supervisor/CMakeLists.txt delete mode 100644 arch/risc-v/src/common/supervisor/Make.defs diff --git a/arch/risc-v/include/syscall.h b/arch/risc-v/include/syscall.h index 9d22006760810..ed49fa5c2f6d7 100644 --- a/arch/risc-v/include/syscall.h +++ b/arch/risc-v/include/syscall.h @@ -139,7 +139,8 @@ extern "C" long smh_call(unsigned int nbr, void *parm); -#if defined(CONFIG_ARCH_USE_S_MODE) && defined(__KERNEL__) +#if defined(__KERNEL__) + uintptr_t sys_call0(unsigned int nbr); uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1); uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2); diff --git a/arch/risc-v/src/common/CMakeLists.txt b/arch/risc-v/src/common/CMakeLists.txt index b1dd33db88710..74b270e4c52a5 100644 --- a/arch/risc-v/src/common/CMakeLists.txt +++ b/arch/risc-v/src/common/CMakeLists.txt @@ -33,6 +33,7 @@ list(APPEND SRCS riscv_releasestack.c riscv_schedulesigaction.c riscv_sigdeliver.c) list(APPEND SRCS riscv_stackframe.c riscv_tcbinfo.c riscv_swint.c) list(APPEND SRCS riscv_switchcontext.c riscv_usestack.c) +list(APPEND SRCS riscv_syscall.S riscv_perform_syscall.c) if(NOT CONFIG_ALARM_ARCH) if(NOT CONFIG_TIMER_ARCH) @@ -122,7 +123,7 @@ if(CONFIG_RISCV_PERCPU_SCRATCH) endif() if(CONFIG_ARCH_USE_S_MODE) - add_subdirectory(supervisor) + list(APPEND SRCS riscv_sbi.c) endif() target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/risc-v/src/common/Make.defs b/arch/risc-v/src/common/Make.defs index e3c46f6fcaa0b..bcd03e269249a 100644 --- a/arch/risc-v/src/common/Make.defs +++ b/arch/risc-v/src/common/Make.defs @@ -25,6 +25,7 @@ endif # Specify our general Assembly files CMN_ASRCS += riscv_vectors.S riscv_exception_common.S riscv_mhartid.S CMN_ASRCS += riscv_saveusercontext.S +CMN_ASRCS += riscv_syscall.S # Specify C code within the common directory to be included CMN_CSRCS += riscv_initialize.c riscv_swint.c riscv_mtimer.c @@ -35,6 +36,7 @@ CMN_CSRCS += riscv_idle.c riscv_modifyreg32.c riscv_nputs.c riscv_releasestack.c CMN_CSRCS += riscv_registerdump.c riscv_stackframe.c riscv_schedulesigaction.c CMN_CSRCS += riscv_sigdeliver.c riscv_switchcontext.c CMN_CSRCS += riscv_usestack.c riscv_tcbinfo.c +CMN_CSRCS += riscv_perform_syscall.c ifneq ($(CONFIG_ALARM_ARCH),y) ifneq ($(CONFIG_TIMER_ARCH),y) @@ -121,8 +123,6 @@ ifeq ($(CONFIG_RISCV_PERCPU_SCRATCH),y) CMN_CSRCS += riscv_percpu.c endif -# Kernel runs in supervisor mode or machine mode ? - ifeq ($(CONFIG_ARCH_USE_S_MODE),y) -include common/supervisor/Make.defs +CMN_CSRCS += riscv_sbi.c endif diff --git a/arch/risc-v/src/common/riscv_exception.c b/arch/risc-v/src/common/riscv_exception.c index cefa6c03f99ff..0ff9af828a47d 100644 --- a/arch/risc-v/src/common/riscv_exception.c +++ b/arch/risc-v/src/common/riscv_exception.c @@ -287,12 +287,7 @@ void riscv_exception_attach(void) irq_attach(RISCV_IRQ_ECALLS, riscv_exception, NULL); irq_attach(RISCV_IRQ_ECALLH, riscv_exception, NULL); - -#ifndef CONFIG_ARCH_USE_S_MODE - irq_attach(RISCV_IRQ_ECALLM, riscv_swint, NULL); -#else irq_attach(RISCV_IRQ_ECALLM, riscv_exception, NULL); -#endif irq_attach(RISCV_IRQ_INSTRUCTIONPF, riscv_exception, NULL); diff --git a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c b/arch/risc-v/src/common/riscv_perform_syscall.c similarity index 97% rename from arch/risc-v/src/common/supervisor/riscv_perform_syscall.c rename to arch/risc-v/src/common/riscv_perform_syscall.c index cd134fb4e1b07..c687ebdec4923 100644 --- a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c +++ b/arch/risc-v/src/common/riscv_perform_syscall.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/supervisor/riscv_perform_syscall.c + * arch/risc-v/src/common/riscv_perform_syscall.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with diff --git a/arch/risc-v/src/common/supervisor/riscv_sbi.c b/arch/risc-v/src/common/riscv_sbi.c similarity index 98% rename from arch/risc-v/src/common/supervisor/riscv_sbi.c rename to arch/risc-v/src/common/riscv_sbi.c index 626e2d068ff13..4eff3c167c012 100644 --- a/arch/risc-v/src/common/supervisor/riscv_sbi.c +++ b/arch/risc-v/src/common/riscv_sbi.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/supervisor/riscv_sbi.c + * arch/risc-v/src/common/riscv_sbi.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with diff --git a/arch/risc-v/src/common/supervisor/riscv_syscall.S b/arch/risc-v/src/common/riscv_syscall.S similarity index 98% rename from arch/risc-v/src/common/supervisor/riscv_syscall.S rename to arch/risc-v/src/common/riscv_syscall.S index bda64d3de2cfb..802037ed3b675 100644 --- a/arch/risc-v/src/common/supervisor/riscv_syscall.S +++ b/arch/risc-v/src/common/riscv_syscall.S @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc-v/src/common/supervisor/riscv_syscall.S + * arch/risc-v/src/common/riscv_syscall.S * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with diff --git a/arch/risc-v/src/common/supervisor/CMakeLists.txt b/arch/risc-v/src/common/supervisor/CMakeLists.txt deleted file mode 100644 index 376ded80b308c..0000000000000 --- a/arch/risc-v/src/common/supervisor/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# ############################################################################## -# arch/risc-v/src/common/supervisor/CMakeLists.txt -# -# Licensed to the Apache Software Foundation (ASF) under one or more contributor -# license agreements. See the NOTICE file distributed with this work for -# additional information regarding copyright ownership. The ASF licenses this -# file to you 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. -# -# ############################################################################## - -if(CONFIG_ARCH_USE_S_MODE) - set(SRCS) - - list(APPEND SRCS riscv_syscall.S riscv_perform_syscall.c riscv_sbi.c) - - target_sources(arch PRIVATE ${SRCS}) - -endif() diff --git a/arch/risc-v/src/common/supervisor/Make.defs b/arch/risc-v/src/common/supervisor/Make.defs deleted file mode 100644 index 65375a3f0979a..0000000000000 --- a/arch/risc-v/src/common/supervisor/Make.defs +++ /dev/null @@ -1,28 +0,0 @@ -############################################################################ -# arch/risc-v/src/common/supervisor/Make.defs -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. The -# ASF licenses this file to you 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. -# -############################################################################ - -# If the NuttX kernel runs in S-mode - -CMN_ASRCS += riscv_syscall.S -CMN_CSRCS += riscv_perform_syscall.c -CMN_CSRCS += riscv_sbi.c - -INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)common$(DELIM)supervisor -VPATH += common$(DELIM)supervisor From 01c37f70126d5546537bf5ce277088942d732646 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Thu, 8 Aug 2024 14:25:29 +0800 Subject: [PATCH 25/81] riscv/rv32m1: fix build issue This exports `return_from_exception` symbol to fix build issue with unified in-kernel syscall. Signed-off-by: Yanfeng Liu --- arch/risc-v/src/rv32m1/rv32m1_head.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/risc-v/src/rv32m1/rv32m1_head.S b/arch/risc-v/src/rv32m1/rv32m1_head.S index 879936103e89d..0b77171878744 100644 --- a/arch/risc-v/src/rv32m1/rv32m1_head.S +++ b/arch/risc-v/src/rv32m1/rv32m1_head.S @@ -34,6 +34,7 @@ /* Exported Symbols */ .global exception_common + .global return_from_exception .global __start .section .text @@ -155,6 +156,8 @@ exception_common: jal x1, rv32m1_dispatch_irq +return_from_exception: + /* If context switch is needed, return a new sp */ mv sp, a0 From bba82bea89e4174ca8aee3c9d1707fa63b0887f7 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Sun, 14 Jul 2024 08:42:29 +0800 Subject: [PATCH 26/81] build/cmake: allow gcc-riscv64-unknown-elf for PROTECTED This allows using Ubuntu stock gcc-riscv64-unknown-elf 10.2 toolchain for PROTECTED build with cmake. Signed-off-by: Yanfeng Liu --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0341964c7eecf..6cb7714a2e434 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -812,6 +812,11 @@ if(CONFIG_BUILD_PROTECTED) $<$:supc++> $<$>:-Wl,--end-group>) + target_include_directories( + nuttx_user SYSTEM + PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/include_arch) + add_custom_command( OUTPUT User.map COMMAND ${CMAKE_NM} nuttx_user > User.map From 01bac59cb70d4139371e541c4f991899ad77349c Mon Sep 17 00:00:00 2001 From: Nonpawit Ekburanawat Date: Wed, 7 Aug 2024 22:37:50 +0200 Subject: [PATCH 27/81] Add STM32H745I-DISCO Per Core Support - New defconfig for nsh CM4 and CM7 - New linker script for cm4 - Update linker script to include shared memory and condition for flash size - Update Make and CMake file to compile according to core - Added UART7 pin by default for CM4 serial output - Changed userled configuration to fix error Signed-off-by: Nonpawit Ekburanawat --- .../configs/nsh_cm4/defconfig | 47 +++++++ .../configs/nsh_cm7/defconfig | 51 ++++++++ .../stm32h7/stm32h745i-disco/include/board.h | 5 + .../stm32h745i-disco/scripts/Make.defs | 6 +- .../stm32h7/stm32h745i-disco/scripts/flash.ld | 26 ++++ .../stm32h745i-disco/scripts/flash_m4.ld | 123 ++++++++++++++++++ .../stm32h745i-disco/src/CMakeLists.txt | 7 +- .../stm32h745i-disco/src/stm32_userleds.c | 2 +- 8 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm4/defconfig create mode 100644 boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm7/defconfig create mode 100644 boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld diff --git a/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm4/defconfig b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm4/defconfig new file mode 100644 index 0000000000000..7b1048fb5fec5 --- /dev/null +++ b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm4/defconfig @@ -0,0 +1,47 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_STM32H7_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32h745i-disco" +CONFIG_ARCH_BOARD_STM32H745I_DISCO=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H745XI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM4=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_PROMPT_STRING="nsh-cm4> " +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x10000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32H7_FMC=y +CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY=y +CONFIG_STM32H7_UART7=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_UART7_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm7/defconfig b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm7/defconfig new file mode 100644 index 0000000000000..bcc2fad0802c3 --- /dev/null +++ b/boards/arm/stm32h7/stm32h745i-disco/configs/nsh_cm7/defconfig @@ -0,0 +1,51 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_STANDARD_SERIAL is not set +# CONFIG_STM32H7_USE_LEGACY_PINMAP is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32h745i-disco" +CONFIG_ARCH_BOARD_STM32H745I_DISCO=y +CONFIG_ARCH_CHIP="stm32h7" +CONFIG_ARCH_CHIP_STM32H745XI=y +CONFIG_ARCH_CHIP_STM32H7=y +CONFIG_ARCH_CHIP_STM32H7_CORTEXM7=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV7M_DCACHE=y +CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y +CONFIG_ARMV7M_DTCM=y +CONFIG_ARMV7M_ICACHE=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=4 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_PROMPT_STRING="nsh-cm7> " +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=245760 +CONFIG_RAM_START=0x20010000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32H7_FMC=y +CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY=y +CONFIG_STM32H7_USART3=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USART3_SERIAL_CONSOLE=y diff --git a/boards/arm/stm32h7/stm32h745i-disco/include/board.h b/boards/arm/stm32h7/stm32h745i-disco/include/board.h index 461d5268f6a65..cb8a113598125 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/include/board.h +++ b/boards/arm/stm32h7/stm32h745i-disco/include/board.h @@ -502,6 +502,11 @@ #define GPIO_USART3_RX (GPIO_USART3_RX_1 | GPIO_SPEED_100MHz) /* PB11 */ #define GPIO_USART3_TX (GPIO_USART3_TX_1 | GPIO_SPEED_100MHz) /* PB10 */ +/* UART7 (Discovery Virtual Console) */ + +#define GPIO_UART7_RX (GPIO_UART7_RX_1 | GPIO_SPEED_100MHz) /* PA8 */ +#define GPIO_UART7_TX (GPIO_UART7_TX_2 | GPIO_SPEED_100MHz) /* PB4 */ + /* I2C4 - Used by Touchscreen and Audio Codec */ #define GPIO_I2C4_SCL (GPIO_I2C4_SCL_1 | GPIO_SPEED_50MHz) /* PD12 */ diff --git a/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs b/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs index 53f84d9234439..fb95f1de7a191 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs +++ b/boards/arm/stm32h7/stm32h745i-disco/scripts/Make.defs @@ -22,7 +22,11 @@ include $(TOPDIR)/.config include $(TOPDIR)/tools/Config.mk include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs -LDSCRIPT = flash.ld +ifeq ($(CONFIG_ARCH_CHIP_STM32H7_CORTEXM7),y) + LDSCRIPT = flash.ld +else + LDSCRIPT = flash_m4.ld +endif ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) diff --git a/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld index 958e111c19aed..1257c37ee9495 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld +++ b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash.ld @@ -93,6 +93,9 @@ * the 0x0800:0000 address range. */ +#include + +#ifndef CONFIG_STM32H7_CORTEXM4_ENABLED MEMORY { itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K @@ -106,6 +109,22 @@ MEMORY sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K } +#else +MEMORY +{ + itcm (rwx) : ORIGIN = 0x00000000, LENGTH = 64K + flash (rx) : ORIGIN = 0x08000000, LENGTH = CONFIG_STM32H7_CORTEXM7_FLASH_SIZE + dtcm1 (rwx) : ORIGIN = 0x20000000, LENGTH = 64K + dtcm2 (rwx) : ORIGIN = 0x20010000, LENGTH = 64K + sram (rwx) : ORIGIN = 0x24000000, LENGTH = 512K + + /* shared memory on SRAM3 */ + + shmem (rwx) : ORIGIN = 0x30040000, LENGTH = 32K + sram4 (rwx) : ORIGIN = 0x38000000, LENGTH = 64K + bbram (rwx) : ORIGIN = 0x38800000, LENGTH = 4K +} +#endif OUTPUT_ARCH(arm) EXTERN(_vectors) @@ -170,6 +189,13 @@ SECTIONS _ebss = ABSOLUTE(.); } > sram + .shmem : + { + . = ALIGN(4); + *(.shmem); + KEEP(*(.shmem)) + } > shmem + /* Emit the the D3 power domain section for locating BDMA data * * Static data with locate_data(".sram4") will be located diff --git a/boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld new file mode 100644 index 0000000000000..c453148555f11 --- /dev/null +++ b/boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld @@ -0,0 +1,123 @@ +/**************************************************************************** + * boards/arm/stm32h7/stm32h745i-disco/scripts/flash_m4.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (theflash.ld + * "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. + * + ****************************************************************************/ + +#include + +#define STM32M4_FLASH_START (0x08000000 + CONFIG_STM32H7_CORTEXM7_FLASH_SIZE) + +#if CONFIG_STM32H7_CORTEXM7_FLASH_SIZE != 1048576 +# error TODO: not supported yet - BCM4_ADD0 must be configured +#endif + +/* Use 0x1xxxxxxx SRAM1-3 mapping for Cortex-M4 */ + +MEMORY +{ + flash (rx) : + ORIGIN = STM32M4_FLASH_START, + LENGTH = (2048K - CONFIG_STM32H7_CORTEXM7_FLASH_SIZE) + + /* SRAM1 and SRAM2 */ + + sram (rwx) : ORIGIN = 0x10000000, LENGTH = 128K + 128K + + /* shared memory on SRAM3 */ + + shmem (rwx) : ORIGIN = 0x10040000, LENGTH = 32K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : + { + _sinit = ABSOLUTE(.); + *(.init_array .init_array.*) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : + { + *(.ARM.extab*) + } > flash + + __exidx_start = ABSOLUTE(.); + .ARM.exidx : + { + *(.ARM.exidx*) + } > flash + __exidx_end = ABSOLUTE(.); + + _eronly = ABSOLUTE(.); + + .data : + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt b/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt index 985622e7f71ab..caab40630ab0f 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt +++ b/boards/arm/stm32h7/stm32h745i-disco/src/CMakeLists.txt @@ -52,4 +52,9 @@ endif() target_sources(board PRIVATE ${SRCS}) -set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") +if(CONFIG_ARCH_CHIP_STM32H7_CORTEXM7) + set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/flash.ld") +else() + set_property(GLOBAL PROPERTY LD_SCRIPT + "${NUTTX_BOARD_DIR}/scripts/flash_m4.ld") +endif() diff --git a/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c b/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c index 9f15fd0eb52e8..0e8056aa764a8 100644 --- a/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c +++ b/boards/arm/stm32h7/stm32h745i-disco/src/stm32_userleds.c @@ -53,7 +53,7 @@ static const uint32_t g_ledcfg[BOARD_NLEDS] = { GPIO_LED_GREEN, - GPIO_LED_BLUE, + GPIO_LED_ORANGE, GPIO_LED_RED, }; From 0be6dfb552de4553cd980c4ec130cf9ce12eb3fa Mon Sep 17 00:00:00 2001 From: Saurav Pal Date: Thu, 8 Aug 2024 16:38:56 +0000 Subject: [PATCH 28/81] fs/mnemofs: Refactor path logic, direntry size bug fix, open free bug fix Refactoring path logic to prevent logic flaws, direntry size bug fix to allow proper direntry traversal, open free bug fix to prevent memory leak after close. Signed-off-by: Saurav Pal --- .gitignore | 2 +- drivers/mtd/mtd_nandram.c | 19 +- drivers/mtd/mtd_nandwrapper.c | 6 +- fs/mnemofs/mnemofs.c | 249 ++++++---- fs/mnemofs/mnemofs.h | 412 ++++++++-------- fs/mnemofs/mnemofs_blkalloc.c | 38 +- fs/mnemofs/mnemofs_ctz.c | 560 +++++++++------------- fs/mnemofs/mnemofs_fsobj.c | 878 ++++++++++++++++++++-------------- fs/mnemofs/mnemofs_journal.c | 659 +++++++++++++++---------- fs/mnemofs/mnemofs_lru.c | 520 ++++++++++++++------ fs/mnemofs/mnemofs_master.c | 14 +- fs/mnemofs/mnemofs_rw.c | 32 +- fs/mnemofs/mnemofs_util.c | 58 +++ include/nuttx/mtd/nand_ram.h | 12 +- 14 files changed, 2016 insertions(+), 1443 deletions(-) diff --git a/.gitignore b/.gitignore index fa38fadba3cc8..030babedd6af6 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,4 @@ tools/gdb/__pycache__ /build .ccls-cache compile_commands.json -imx9-sdimage.img +imx9-sdimage.img \ No newline at end of file diff --git a/drivers/mtd/mtd_nandram.c b/drivers/mtd/mtd_nandram.c index cfaaef7366ed4..a2b96744166fd 100644 --- a/drivers/mtd/mtd_nandram.c +++ b/drivers/mtd/mtd_nandram.c @@ -25,6 +25,7 @@ * Included Files ****************************************************************************/ +#include #include #include @@ -89,8 +90,8 @@ #else -#define NAND_RAM_LOG -#define NAND_RAM_STATUS_LOG +#define NAND_RAM_LOG(str, ...) +#define NAND_RAM_STATUS_LOG(str, ...) #endif /* CONFIG_MTD_NAND_RAM_DEBUG */ @@ -197,10 +198,12 @@ static void nand_ram_storage_status(void) static inline void nand_ram_status(void) { +#ifdef CONFIG_MTD_NAND_RAM_DEBUG if (nand_ram_ins_i % NAND_RAM_STATUS_LEVEL == 0) { nand_ram_storage_status(); } +#endif } /**************************************************************************** @@ -353,12 +356,19 @@ int nand_ram_rawread(FAR struct nand_raw_s *raw, off_t block, if (data != NULL) { - memcpy(data, (const void *)read_page_data, NAND_RAM_PAGE_SIZE); + if (nand_ram_flash_spare[read_page].free == NAND_RAM_PAGE_FREE) + { + memset(data, 0, NAND_RAM_PAGE_SIZE); + } + else + { + memcpy(data, (const void *)read_page_data, NAND_RAM_PAGE_SIZE); + } } if (spare != NULL) { - memcpy(spare, (const void *)read_page_spare, NAND_RAM_PAGE_SIZE); + memcpy(spare, (const void *)read_page_spare, NAND_RAM_SPARE_SIZE); } NAND_RAM_LOG("[LOWER %lu | %s] Done\n", nand_ram_ins_i, "rawread"); @@ -420,6 +430,7 @@ int nand_ram_rawwrite(FAR struct nand_raw_s *raw, off_t block, nand_ram_flash_spare[write_page].n_write++; + memset((void *)write_page_data, 0, NAND_RAM_PAGE_SIZE); if (data != NULL) { memcpy((void *)write_page_data, data, NAND_RAM_PAGE_SIZE); diff --git a/drivers/mtd/mtd_nandwrapper.c b/drivers/mtd/mtd_nandwrapper.c index 83e6bbc9862d9..4c84340069aa9 100644 --- a/drivers/mtd/mtd_nandwrapper.c +++ b/drivers/mtd/mtd_nandwrapper.c @@ -328,7 +328,7 @@ int nand_wrapper_isbad(FAR struct mtd_dev_s *dev, off_t block) nxmutex_lock(&nand_wrapper_dev_mut); nand_wrapper_ins_i++; - NAND_WRAPPER_LOG("[UPPER %lu | %s] Blocks: %d\n", + NAND_WRAPPER_LOG("[UPPER %lu | %s] Block: %d\n", nand_wrapper_ins_i, "isbad", block); DEBUGASSERT(nand_dev && nand_dev->under.mtd.isbad); @@ -336,8 +336,8 @@ int nand_wrapper_isbad(FAR struct mtd_dev_s *dev, off_t block) if (ret >= 0) { - NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n", - nand_wrapper_ins_i, "isbad"); + NAND_WRAPPER_LOG("[UPPER %lu | %s] Done %d\n", + nand_wrapper_ins_i, "isbad", ret); } else { diff --git a/fs/mnemofs/mnemofs.c b/fs/mnemofs/mnemofs.c index 2009098fa3a4a..5cf0c0fef80ae 100644 --- a/fs/mnemofs/mnemofs.c +++ b/fs/mnemofs/mnemofs.c @@ -120,25 +120,25 @@ static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer, static off_t mnemofs_seek(FAR struct file *filep, off_t offset, int whence); static int mnemofs_ioctl(FAR struct file *filep, int cmd, - unsigned long arg); + unsigned long arg); static int mnemofs_truncate(FAR struct file *filep, off_t length); static int mnemofs_sync(FAR struct file *filep); static int mnemofs_dup(FAR const struct file *oldp, - FAR struct file *newp); + FAR struct file *newp); static int mnemofs_fstat(FAR const struct file *filep, - FAR struct stat *buf); + FAR struct stat *buf); static int mnemofs_opendir(FAR struct inode *mountpt, - FAR const char *relpath, - FAR struct fs_dirent_s **dir); + FAR const char *relpath, + FAR struct fs_dirent_s **dir); static int mnemofs_closedir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir); static int mnemofs_readdir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir, - FAR struct dirent *entry); + FAR struct fs_dirent_s *dir, + FAR struct dirent *entry); static int mnemofs_rewinddir(FAR struct inode *mountpt, - FAR struct fs_dirent_s *dir); + FAR struct fs_dirent_s *dir); static int mnemofs_bind(FAR struct inode *driver, FAR const void *data, FAR void** handle); @@ -151,9 +151,9 @@ static int mnemofs_statfs(FAR struct inode *mountpt, static int mnemofs_unlink(FAR struct inode *mountpt, FAR const char *relpath); static int mnemofs_mkdir(FAR struct inode *mountpt, - FAR const char *relpath, mode_t mode); + FAR const char *relpath, mode_t mode); static int mnemofs_rmdir(FAR struct inode *mountpt, - FAR const char *relpath); + FAR const char *relpath); static int mnemofs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, FAR const char *newrelpath); @@ -250,11 +250,11 @@ const struct mountpt_operations g_mnemofs_operations = static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, int oflags, mode_t mode) { - int ret = OK; - int flags; - struct mfs_pitr_s pitr; + int ret = OK; + int flags; FAR const char *child = NULL; FAR struct inode *inode; + struct mfs_pitr_s pitr; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; FAR struct mfs_ocom_s *fcom; @@ -298,7 +298,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, /* Check creation flags. */ flags = mfs_get_patharr(sb, relpath, &f->com->path, &f->com->depth); - if ((flags & MFS_NEXIST) != 0) + if ((flags & MFS_EXIST) == 0) { if ((flags & MFS_P_ISDIR) != 0) { @@ -307,8 +307,10 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, /* Add direntry to parent's directory file. */ f->com->new_ent = true; + mfs_pitr_init(sb, f->com->path, f->com->depth, &pitr, true); child = mfs_path2childname(relpath); + finfo("Child is: %s.", child); mfs_pitr_appendnew(sb, f->com->path, f->com->depth, &pitr, child, mode); mfs_pitr_free(&pitr); @@ -347,7 +349,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, /* TODO: Update mtime and atime. */ mfs_pitr_init(sb, f->com->path, f->com->depth, &pitr, true); - mfs_pitr_readdirent(sb, &pitr, &dirent); + mfs_pitr_readdirent(sb, f->com->path, &pitr, &dirent); if (dirent != NULL) { @@ -367,7 +369,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, mfs_pitr_free(&pitr); - finfo("Direntry is read and processed."); + finfo("Direntry processing done."); /* Check Offset flags. */ @@ -378,8 +380,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, * then it's truncated. Else, the truncate flag is ignored. */ - ret = mfs_lru_del(sb, 0, f->com->sz, f->com->sz, f->com->path, - f->com->depth); + ret = mfs_lru_del(sb, 0, f->com->sz, f->com->path, f->com->depth); if (predict_false(ret < 0)) { finfo("Error while truncating file. Ret: %d.", ret); @@ -392,8 +393,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, f->com->off = f->com->sz; } - finfo("Offset flags are set."); - + finfo("[TMP1] %p %p", &sb->of, &f->list); list_add_tail(&sb->of, &f->list); filep->f_priv = f; @@ -446,7 +446,7 @@ static int mnemofs_open(FAR struct file *filep, FAR const char *relpath, static int mnemofs_close(FAR struct file *filep) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -471,7 +471,7 @@ static int mnemofs_close(FAR struct file *filep) /* Flushing in-memory data to on-flash journal. */ - ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth, f->com->sz); + ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth); if (predict_false(ret < 0)) { finfo("Error while flushing file. Ret: %d.", ret); @@ -480,17 +480,18 @@ static int mnemofs_close(FAR struct file *filep) f->com->refcount--; - if (predict_true(f->com->refcount != 0)) + if (f->com->refcount == 0) { kmm_free(f->com->path); kmm_free(f->com); - kmm_free(f); finfo("Refcount is 0, open file structure freed."); } list_delete(&f->list); + kmm_free(f); filep->f_priv = NULL; + finfo("File entry removed from the open files list."); errout_with_lock: @@ -530,7 +531,7 @@ static int mnemofs_close(FAR struct file *filep) static ssize_t mnemofs_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { - int ret = 0; + int ret = 0; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -643,8 +644,8 @@ static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer, /* Write data to CTZ at the current offset. */ - ret = mfs_lru_wr(sb, f->com->off, buflen, f->com->sz, f->com->path, - f->com->depth, buffer); + ret = mfs_lru_wr(sb, f->com->off, buflen, f->com->path, f->com->depth, + buffer); if (ret < 0) { goto errout_with_lock; @@ -693,8 +694,8 @@ static ssize_t mnemofs_write(FAR struct file *filep, FAR const char *buffer, static off_t mnemofs_seek(FAR struct file *filep, off_t offset, int whence) { - int ret = OK; - mfs_t pos; + int ret = OK; + mfs_t pos; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -782,7 +783,7 @@ static off_t mnemofs_seek(FAR struct file *filep, off_t offset, int whence) static int mnemofs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct inode *drv; FAR struct mfs_sb_s *sb; @@ -844,7 +845,7 @@ static int mnemofs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) static int mnemofs_truncate(FAR struct file *filep, off_t length) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -869,8 +870,8 @@ static int mnemofs_truncate(FAR struct file *filep, off_t length) if (length < f->com->sz) { - ret = mfs_lru_del(sb, length, f->com->sz - length, f->com->sz, - f->com->path, f->com->depth); + ret = mfs_lru_del(sb, length, f->com->sz - length, f->com->path, + f->com->depth); if (predict_false(ret < 0)) { finfo("Error during truncate. Ret: %d.", ret); @@ -932,7 +933,7 @@ static int mnemofs_sync(FAR struct file *filep) f = filep->f_priv; DEBUGASSERT(f != NULL); - ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth, f->com->sz); + ret = mfs_lru_ctzflush(sb, f->com->path, f->com->depth); nxmutex_unlock(&MFS_LOCK(sb)); finfo("Lock released."); @@ -966,7 +967,7 @@ static int mnemofs_sync(FAR struct file *filep) static int mnemofs_dup(FAR const struct file *oldp, FAR struct file *newp) { - int ret = OK; + int ret = OK; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *of; @@ -1055,8 +1056,8 @@ static int mnemofs_dup(FAR const struct file *oldp, FAR struct file *newp) static int mnemofs_fstat(FAR const struct file *filep, FAR struct stat *buf) { - int ret = OK; - struct mfs_pitr_s pitr; + int ret = OK; + struct mfs_pitr_s pitr; FAR struct inode *inode; FAR struct mfs_sb_s *sb; FAR struct mfs_ofd_s *f; @@ -1081,9 +1082,10 @@ static int mnemofs_fstat(FAR const struct file *filep, FAR struct stat *buf) DEBUGASSERT(f != NULL); mfs_pitr_init(sb, f->com->path, f->com->depth, &pitr, true); - mfs_pitr_adv_tochild(&pitr, f->com->path, f->com->depth); - mfs_pitr_readdirent(sb, &pitr, &dirent); + mfs_pitr_adv_tochild(&pitr, f->com->path); + mfs_pitr_readdirent(sb, f->com->path, &pitr, &dirent); mfs_pitr_free(&pitr); + DEBUGASSERT(dirent != NULL); buf->st_mode = dirent->mode; @@ -1169,11 +1171,17 @@ static int mnemofs_opendir(FAR struct inode *mountpt, goto errout_with_lock; } + ret = mfs_lru_updatedinfo(sb, path, depth); + if (predict_false(ret < 0)) + { + goto errout_with_path; + } + pitr = kmm_zalloc(sizeof(*pitr)); if (predict_false(pitr == NULL)) { ret = -ENOMEM; - goto errout_with_lock; + goto errout_with_path; } fsdirent = kmm_zalloc(sizeof(*fsdirent)); @@ -1183,7 +1191,12 @@ static int mnemofs_opendir(FAR struct inode *mountpt, goto errout_with_pitr; } - mfs_pitr_init(sb, path, depth, pitr, false); + ret = mfs_pitr_init(sb, path, depth, pitr, false); + if (predict_false(ret < 0)) + { + finfo("Failed PITR initialization."); + goto errout_with_fsdirent; + } fsdirent->idx = 0; fsdirent->path = path; @@ -1199,9 +1212,15 @@ static int mnemofs_opendir(FAR struct inode *mountpt, finfo("Lock released."); return ret; +errout_with_fsdirent: + kmm_free(fsdirent); + errout_with_pitr: kmm_free(pitr); +errout_with_path: + mfs_free_patharr(path); + errout_with_lock: nxmutex_unlock(&MFS_LOCK(sb)); finfo("Lock released."); @@ -1271,8 +1290,8 @@ static int mnemofs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir, FAR struct dirent *entry) { - int ret = OK; - FAR struct mfs_sb_s *sb; + int ret = OK; + FAR struct mfs_sb_s *sb; FAR struct mfs_dirent_s *dirent; FAR struct mfs_fsdirent *fsdirent = (FAR struct mfs_fsdirent *) dir; @@ -1311,13 +1330,19 @@ static int mnemofs_readdir(FAR struct inode *mountpt, /* Regular direntries from here. */ - /* Here lies the `unlink` and `rmdir` bug, as sync can only update the - * current CTZ. + /* TODO: Need to think why *exactly* below line is needed. The LRU node + * seems to contain wrong size during opendir, but updating it here + * updates it to correct size, even though this updatedinfo is also + * called in opendir? */ - /* mfs_pitr_sync(sb, fsdirent->pitr, fsdirent->path, fsdirent->depth); */ + ret = mfs_lru_updatedinfo(sb, fsdirent->path, fsdirent->depth); + if (predict_false(ret < 0)) + { + goto errout_with_lock; + } - mfs_pitr_readdirent(sb, fsdirent->pitr, &dirent); + ret = mfs_pitr_readdirent(sb, fsdirent->path, fsdirent->pitr, &dirent); if (predict_false(ret < 0)) { goto errout_with_lock; @@ -1333,10 +1358,13 @@ static int mnemofs_readdir(FAR struct inode *mountpt, } memset(entry->d_name, 0, NAME_MAX + 1); - memcpy(entry->d_name, dirent->name, NAME_MAX); + memcpy(entry->d_name, dirent->name, dirent->namelen); entry->d_type = (S_ISDIR(dirent->mode) ? DTYPE_DIRECTORY: DTYPE_FILE); - mfs_pitr_adv(sb, fsdirent->pitr); + finfo("Size of direntry %u, current off %u.", MFS_DIRENTSZ(dirent), + fsdirent->pitr->c_off); + + mfs_pitr_adv_bydirent(fsdirent->pitr, dirent); mfs_free_dirent(dirent); errout_with_lock: @@ -1370,7 +1398,7 @@ static int mnemofs_readdir(FAR struct inode *mountpt, static int mnemofs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) { - int ret = OK; + int ret = OK; FAR struct mfs_sb_s *sb; struct mfs_fsdirent *fsdirent = (struct mfs_fsdirent *) dir; @@ -1503,6 +1531,8 @@ static int mnemofs_bind(FAR struct inode *driver, FAR const void *data, sb->log_pg_in_blk = log2(sb->pg_in_blk); sb->log_n_blks = log2(MFS_NBLKS(sb)); + list_initialize(&sb->of); + sb->rw_buf = kmm_zalloc(MFS_PGSZ(sb)); if (predict_false(sb->rw_buf == NULL)) { @@ -1762,11 +1792,10 @@ static int mnemofs_unlink(FAR struct inode *mountpt, FAR const char *relpath) static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, mode_t mode) { - int ret = OK; - int flags; - mfs_t depth; - FAR const char *child; - struct mfs_pitr_s pitr; + int ret = OK; + int flags; + mfs_t depth; + struct mfs_pitr_s pitr; FAR struct mfs_sb_s *sb; FAR struct mfs_path_s *path; @@ -1787,7 +1816,14 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, finfo("Lock acquired."); flags = mfs_get_patharr(sb, relpath, &path, &depth); - if ((flags & MFS_NEXIST) == 0) + if ((flags & MFS_EXIST) != 0) + { + finfo("File exists."); + + ret = -EEXIST; + goto errout_with_path; + } + else { if ((flags & MFS_P_EXIST) != 0) { @@ -1800,29 +1836,25 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, else { ret = -ENOTDIR; - goto errout_with_lock; + goto errout_with_path; } } else { ret = -ENOENT; - goto errout_with_lock; + goto errout_with_path; } } - else - { - ret = -EEXIST; - goto errout_with_lock; - } + memset(&path[depth - 1], 0, sizeof(struct mfs_path_s)); mfs_pitr_init(sb, path, depth, &pitr, true); - child = relpath; - finfo("Mode %x", mode); - ret = mfs_pitr_appendnew(sb, path, depth, &pitr, child, mode); + /* The last incomplete direntry will be added by mfs_pitr_appendnew. */ + + ret = mfs_pitr_appendnew(sb, path, depth, &pitr, relpath, mode); if (predict_false(ret < 0)) { - goto errout_with_pitr; + goto errout_with_path; } mfs_pitr_free(&pitr); @@ -1837,10 +1869,11 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, finfo("Mnemofs mkdir exited with ret %d.", ret); return ret; -errout_with_pitr: +errout_with_path: + mfs_free_patharr(path); + mfs_pitr_free(&pitr); -errout_with_lock: nxmutex_unlock(&MFS_LOCK(sb)); finfo("Lock released."); @@ -1869,10 +1902,10 @@ static int mnemofs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, static int mnemofs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) { - int ret = OK; - int flags; - mfs_t depth; - struct mfs_pitr_s pitr; + int ret = OK; + int flags; + mfs_t depth; + struct mfs_pitr_s pitr; FAR struct mfs_sb_s *sb; FAR struct mfs_path_s *path; @@ -1898,9 +1931,9 @@ static int mnemofs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) } mfs_pitr_init(sb, path, depth, &pitr, true); - mfs_pitr_adv_tochild(&pitr, path, depth); + mfs_pitr_adv_tochild(&pitr, path); - if (!mfs_obj_isempty(sb, &pitr)) + if (!mfs_obj_isempty(sb, path, &pitr)) { ret = -ENOTEMPTY; goto errout_with_pitr; @@ -1948,16 +1981,16 @@ static int mnemofs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, FAR const char *newrelpath) { - int ret = OK; - int oflags; - int nflags; - bool nexists; - bool odir = false; - bool ndir = false; - mfs_t odepth; - mfs_t ndepth; - struct mfs_pitr_s opitr; - struct mfs_pitr_s npitr; + int ret = OK; + int oflags; + int nflags; + bool nexists; + bool odir = false; + bool ndir = false; + mfs_t odepth; + mfs_t ndepth; + struct mfs_pitr_s opitr; + struct mfs_pitr_s npitr; FAR struct mfs_sb_s *sb; FAR struct mfs_path_s *opath; FAR struct mfs_path_s *npath; @@ -1978,7 +2011,7 @@ static int mnemofs_rename(FAR struct inode *mountpt, finfo("Lock acquired."); oflags = mfs_get_patharr(sb, oldrelpath, &opath, &odepth); - if ((oflags & MFS_NEXIST) != 0) + if ((oflags & MFS_EXIST) == 0) { ret = -ENOENT; goto errout_with_opath; @@ -1991,9 +2024,9 @@ static int mnemofs_rename(FAR struct inode *mountpt, goto errout_with_npath; } - odir = ((oflags & MFS_ISDIR) != 0); - ndir = ((nflags & MFS_ISDIR) != 0); - nexists = ((nflags & MFS_NEXIST) == 0); + odir = ((oflags & MFS_ISDIR) != 0); + ndir = ((nflags & MFS_ISDIR) != 0); + nexists = ((nflags & MFS_EXIST) != 0); if (nexists && odir && !ndir) { @@ -2016,11 +2049,11 @@ static int mnemofs_rename(FAR struct inode *mountpt, if (nexists) { - mfs_pitr_adv_tochild(&opitr, opath, odepth); - mfs_pitr_adv_tochild(&npitr, npath, ndepth); + mfs_pitr_adv_tochild(&opitr, opath); + mfs_pitr_adv_tochild(&npitr, npath); - mfs_pitr_readdirent(sb, &opitr, &odirent); - if (ndir && !mfs_obj_isempty(sb, &npitr)) + mfs_pitr_readdirent(sb, opath, &opitr, &odirent); + if (ndir && !mfs_obj_isempty(sb, npath, &npitr)) { ret = -ENOTEMPTY; goto errout_with_pitr; @@ -2031,7 +2064,7 @@ static int mnemofs_rename(FAR struct inode *mountpt, mfs_pitr_rm(sb, npath, ndepth); } - mfs_pitr_adv_tochild(&npitr, npath, ndepth); + mfs_pitr_adv_tochild(&npitr, npath); mfs_pitr_appenddirent(sb, npath, ndepth, &npitr, odirent); mfs_pitr_rmdirent(sb, opath, odepth, &opitr, odirent); @@ -2086,7 +2119,7 @@ static int mnemofs_stat(FAR struct inode *mountpt, FAR const char *relpath, FAR struct mfs_path_s *path; FAR struct mfs_dirent_s *dirent = NULL; - finfo("Mnemofs stat for path %s.", relpath); + finfo("Mnemofs stat for path \"%s\".", relpath); DEBUGASSERT(mountpt != NULL); sb = mountpt->i_private; @@ -2101,26 +2134,33 @@ static int mnemofs_stat(FAR struct inode *mountpt, FAR const char *relpath, finfo("Lock acquired."); ret_flags = mfs_get_patharr(sb, relpath, &path, &depth); - if (ret_flags & MFS_NEXIST) + if ((ret_flags & MFS_EXIST) == 0) { ret = -ENOENT; - goto errout_with_lock; + goto errout_with_path; } - finfo("Got path array. Depth %u for path \"%s\"", depth, relpath); + finfo("Got path array. Depth %u for path \"%s\". Return flags %u.", depth, + relpath, ret_flags); + + ret = mfs_lru_updatedinfo(sb, path, depth); + if (predict_false(ret < 0)) + { + goto errout_with_path; + } mfs_pitr_init(sb, path, depth, &pitr, true); - mfs_pitr_adv_tochild(&pitr, path, depth); + mfs_pitr_adv_tochild(&pitr, path); - ret = mfs_pitr_readdirent(sb, &pitr, &dirent); + ret = mfs_pitr_readdirent(sb, path, &pitr, &dirent); if (predict_false(ret < 0)) { - goto errout_with_lock; + goto errout_with_path; } else if (dirent == NULL) { ret = -ENOENT; - goto errout_with_lock; + goto errout_with_path; } finfo("Read stats."); @@ -2136,13 +2176,14 @@ static int mnemofs_stat(FAR struct inode *mountpt, FAR const char *relpath, mfs_free_dirent(dirent); mfs_pitr_free(&pitr); + +errout_with_path: mfs_free_patharr(path); -errout_with_lock: finfo("Lock released."); nxmutex_unlock(&MFS_LOCK(sb)); errout: - finfo("ret %d", ret); + finfo("Ret %d", ret); return ret; } diff --git a/fs/mnemofs/mnemofs.h b/fs/mnemofs/mnemofs.h index df1d1040b3c56..ab6c2476eb977 100644 --- a/fs/mnemofs/mnemofs.h +++ b/fs/mnemofs/mnemofs.h @@ -88,9 +88,12 @@ #define MFS_NBLKS(sb) ((sb)->n_blks) #define MFS_NPGS(sb) (MFS_NBLKS(sb) * MFS_PGINBLK(sb)) +#define MFS_HASHSZ 16 #define MFS_CTZ_SZ(l) ((l)->sz) -#define MFS_DIRENTSZ(dirent) (sizeof(struct mfs_dirent_s) \ - + (dirent)->namelen) +#define MFS_DIRENTSZ(dirent) ((mfs_t) (sizeof(struct mfs_dirent_s) \ + + (dirent)->namelen)) + +#define MFS_JRNL_LIM(sb) (MFS_JRNL(sb).n_blks) /* TODO: 50-75% */ /**************************************************************************** * Public Types @@ -112,7 +115,7 @@ enum MFS_PATH_FLAGS { MFS_ISDIR = (1 << 0), /* Path is a directory. */ MFS_ISFILE = (1 << 1), /* Path is a file. */ - MFS_NEXIST = (1 << 2), /* Path No Exist */ + MFS_EXIST = (1 << 2), /* Path Exists */ MFS_FINPATH = (1 << 3), /* File in midele of path before bottom most * child. Not reachable. */ @@ -227,7 +230,10 @@ struct mfs_node_s mfs_t sz; mfs_t range_min; mfs_t range_max; - FAR struct mfs_path_s path[]; + struct timespec st_mtim; + struct timespec st_atim; + struct timespec st_ctim; + FAR struct mfs_path_s *path; }; /* Common Part Open File Descriptor */ @@ -253,9 +259,9 @@ struct mfs_ofd_s struct mfs_dirent_s { - uint8_t name_hash; /* Should be at start to improve efficiency. */ - mfs_t sz; + uint16_t name_hash; /* Should be at start to improve efficiency. */ uint16_t mode; + mfs_t sz; struct timespec st_atim; /* Time of last access */ struct timespec st_mtim; /* Time of last modification */ struct timespec st_ctim; /* Time of last status change */ @@ -271,9 +277,12 @@ struct mfs_pitr_s struct mfs_path_s p; /* Parent representation */ mfs_t depth; mfs_t c_off; /* Current offset. */ - mfs_t sz; /* Parent's size. */ }; +/* TODO: depth >= 1 */ + +/* IMP TODO: sizeof(x) != size of buffer required to store it. Need to fix. */ + /**************************************************************************** * Public Data ****************************************************************************/ @@ -411,131 +420,157 @@ static inline mfs_t mfs_popcnt(mfs_t x) /* mnemofs_journal.c */ /**************************************************************************** - * Name: mfs_jrnl_newlog + * Name: mfs_jrnl_init * * Description: - * Add a new log to the journal. + * Initialize journal if device is already formatted. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Length of path. - * new_ctz - The updated location. + * sb - Superblock instance of the device. + * blk - First block of the journal. * * Returned Value: * 0 - OK * < 0 - Error * - * Assumptions/Limitations: - * Assumes the CTZ list to be updated is `path[depth - 1].ctz`. - * ****************************************************************************/ -int mfs_jrnl_newlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz); +int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk); /**************************************************************************** - * Name: mfs_jrnl_updatepath + * Name: mfs_jrnl_fmt * * Description: - * Updates the path of a CTZ list by applies all changes from the journal. + * Format a journal to the device. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Length of path. + * sb - Superblock instance of the device. + * blk1 - First master block for the journal. + * blk2 - Second master block for the journal. * * Returned Value: * 0 - OK * < 0 - Error * * Assumptions/Limitations: - * Assumes the CTZ list to be updated is `path[depth - 1].ctz`. + * If blk1 == 0 and blk2 == 0, this means that this will also format in the + * master blocks. If this is not satisfied, the provided values will be + * taken to denote the master nodes. * ****************************************************************************/ -int mfs_jrnl_updatepath(FAR const struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth); +int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2); /**************************************************************************** - * Name: mfs_jrnl_init + * Name: mfs_jrnl_free * * Description: - * Initialize journal if device is already formatted. + * Free the journal. * * Input Parameters: - * sb - Superblock instance of the device. - * blk - First block of the journal. + * sb - Superblock instance of the device. + * + ****************************************************************************/ + +void mfs_jrnl_free(FAR struct mfs_sb_s * const sb); + +/**************************************************************************** + * Name: mfs_jrnl_blkidx2blk + * + * Description: + * Gets the block number of a journal block at an index. + * + * Input Parameters: + * sb - Superblock instance of the device. + * blk_idx - Index of the block who's block number to find. * * Returned Value: - * 0 - OK - * < 0 - Error + * Block number. + * + * Assumptions/Limitations: + * Assumes valid index. This index can also include master blocks. Also + * assumes, for now, that the entire journal array can fit in the first + * block. * ****************************************************************************/ -int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk); +mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, + const mfs_t blk_idx); /**************************************************************************** - * Name: mfs_jrnl_fmt + * Name: mfs_jrnl_updatedinfo * * Description: - * Format a journal to the device. + * Update the path information from the journal. * * Input Parameters: - * sb - Superblock instance of the device. - * blk1 - First master block for the journal. - * blk2 - Second master block for the journal. + * sb - Superblock instance of the device. + * path - "Base state" path. + * depth - Path depth. * * Returned Value: * 0 - OK * < 0 - Error * * Assumptions/Limitations: - * If blk1 == 0 and blk2 == 0, this means that this will also format in the - * master blocks. If this is not satisfied, the provided values will be - * taken to denote the master nodes. + * This applies updates over data that is already gathered from the data + * section of the flash. The data section is the "base state" over which + * the updates in the journal are applied. * ****************************************************************************/ -int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2); +int mfs_jrnl_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth); /**************************************************************************** - * Name: mfs_jrnl_blkidx2blk + * Name: mfs_jrnl_wrlog * * Description: - * Gets the block number of a journal block at an index. + * Write a log for LRU node when its popped from the LRU. * * Input Parameters: * sb - Superblock instance of the device. - * blk_idx - Index of the block who's block number to find. + * node - LRU node. + * loc_new - New location of the CTZ skip list. + * sz_new - New size of the CTZ skip list. * * Returned Value: - * Block number. + * 0 - OK + * < 0 - Error * * Assumptions/Limitations: - * Assumes valid index. This index can also include master blocks. Also - * assumes, for now, that the entire journal array can fit in the first - * block. + * When a node from LRU is flushed, it's written to the data in any space + * that is available according to the block allocator, and the new location + * is recorded as a log along with the old location. Any log of this same + * CTZ skip list in the journal will use this "snapshot" of the location, + * ie. the updated path will be used until another log of the same CTZ + * skip list is stored, after which the path will be updated again, and + * so on. * ****************************************************************************/ -mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, - const mfs_t blk_idx); +int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb, + const struct mfs_node_s node, + const struct mfs_ctz_s loc_new, const mfs_t sz_new); /**************************************************************************** - * Name: mfs_jrnl_free + * Name: mfs_jrnl_flush * * Description: - * Free the journal. + * Flush the entire journal. This is the entry point of the entire flush + * operation and includes messing with the master node as well. * * Input Parameters: * sb - Superblock instance of the device. * + * Returned Value: + * 0 - OK + * < 0 - Error + * ****************************************************************************/ -void mfs_jrnl_free(FAR struct mfs_sb_s * const sb); +int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb); /* mnemofs_blkalloc.c */ @@ -639,12 +674,16 @@ void mfs_ba_blkmarkdel(FAR struct mfs_sb_s * const sb, mfs_t blk); * Input Parameters: * sb - Superblock instance of the device. * + * Returned Value: + * 0 - OK + * < 0 - Error + * * Assumptions/Limitations: * This assumes a locked environment when called. * ****************************************************************************/ -void mfs_ba_delmarked(FAR struct mfs_sb_s * const sb); +int mfs_ba_delmarked(FAR struct mfs_sb_s * const sb); /**************************************************************************** * Name: mfs_ba_markusedpg @@ -847,6 +886,10 @@ int mfs_erase_nblks(FAR const struct mfs_sb_s * const sb, const off_t blk, uint8_t mfs_arrhash(FAR const char *arr, ssize_t len); +/* TODO: Put below in place of above. */ + +uint16_t mfs_hash(FAR const char *arr, ssize_t len); + /**************************************************************************** * Name: mfs_ser_8 * @@ -990,6 +1033,12 @@ FAR char *mfs_ser_ctz(FAR const struct mfs_ctz_s * const x, FAR const char *mfs_deser_ctz(FAR const char * const in, FAR struct mfs_ctz_s * const x); +FAR char *mfs_ser_path(FAR const struct mfs_path_s * const x, + FAR char * const out); + +FAR const char *mfs_deser_path(FAR const char * const in, + FAR struct mfs_path_s * const x); + /**************************************************************************** * Name: mfs_ser_timespec * @@ -1080,7 +1129,7 @@ mfs_t mfs_v2n(mfs_t n); * Name: mfs_set_msb * * Description: - * Set the least significant of the most significant unset bits. + * The mosr significant set bit location. * * Input Parameters: * n - Number. @@ -1092,104 +1141,76 @@ mfs_t mfs_v2n(mfs_t n); mfs_t mfs_set_msb(mfs_t n); +bool mfs_ctz_eq(FAR const struct mfs_ctz_s * const a, + FAR const struct mfs_ctz_s * const b); + +bool mfs_path_eq(FAR const struct mfs_path_s * const a, + FAR const struct mfs_path_s * const b); + /* mnemofs_ctz.c */ /**************************************************************************** - * Name: mfs_ctz_rdfromoff + * Name: mfs_ctz_rdfromoff_new * * Description: - * Read data from data offset in a CTZ list. This includes updates from the - * journal. The ctz list is taken as the last element in the path, got - * using `path[depth - 1]`. + * Read from a specific offset into the data in a CTZ file. New version. * * Input Parameters: * sb - Superblock instance of the device. - * data_off - Data offset into the CTZ list. - * path - CTZ representation of the relpath. - * depth - Depth of the path. - * buf - Buffer will be populated with the contents. - * buflen - Length of `buf`. - * - * Returned Value: - * 0 - OK - * < 0 - Error + * ctz - CTZ list. + * data_off - Offset into the data. + * len - Length of the buffer. + * buf - Buffer to store read contents. * * Assumptions/Limitations: - * This updates the value of path to reflect the latest location. + * The CTZ list provided should be the updated location from the journal. * ****************************************************************************/ -int mfs_ctz_rdfromoff(FAR struct mfs_sb_s * const sb, mfs_t data_off, - FAR struct mfs_path_s * const path, const mfs_t depth, - FAR char *buf, mfs_t buflen); +int mfs_ctz_rdfromoff(FAR const struct mfs_sb_s * const sb, + const struct mfs_ctz_s ctz, mfs_t data_off, + mfs_t len, FAR char * buf); /**************************************************************************** - * Name: mfs_ctz_wrtooff + * Name: mfs_ctz_wrtnode_new * * Description: - * Replace `o_bytes` of data from CTZ list with `n_bytes` of data from - * `buf` at CTZ data offset `data_off`. - * - * In mnemofs, the CTZ lists are all stored in a Copy On Write manner. - * Hence to update a CTZ list, the common CTZ blocks will be kept as it is, - * then in the CTZ block containing `data_off`, the bytes appearing before - * `data_off` (which remain unchanged) will be copied to the new CTZ block - * then `n_bytes` of content from `buf` will follow, and then the data from - * `data_off + o_bytes` will follow (both these will be copied to new - * CTZ blocks as well due to Copy On Write). - * - * The new location will be written to the journal upon success as well. + * Write an LRU node to the flash. It also adds a log of it to the journal. * * Input Parameters: - * sb - Superblock instance of the device. - * data_off - Data offset into the CTZ list. - * o_bytes - Number of bytes in old CTZ list from `data_off` that will be - * replaced. - * n_bytes - Number of bytes in new CTZ list from `data_off` that will be - * replacing `o_bytes`. - * o_ctz_sz - The size in bytes of the old CTZ list. - * path - CTZ representation of the relpath. - * depth - Depth of the path. - * buf - Buffer that contains the data to be replaced in CTZ list. - * ctz - CTZ list to be updated with the new position. - * - * Returned Value: - * 0 - OK - * < 0 - Error + * sb - Superblock instance of the device. + * node - LRU node * * Assumptions/Limitations: - * This updates the value of path to reflect the latest location.s + * - Assumes path is updated by journal. This will also write corresponding + * journal log. + * + * - This is the most computationally heavy part of the entire file system + * from a human POV, and one of the most for MCU or computer (as init + * methods are heavier). * ****************************************************************************/ -int mfs_ctz_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t o_bytes, const mfs_t n_bytes, - mfs_t o_ctz_sz, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf, - FAR struct mfs_ctz_s *ctz); +int mfs_ctz_wrtnode(FAR struct mfs_sb_s * const sb, + const struct mfs_node_s * const node); + +/* mnemofs_lru.c */ /**************************************************************************** - * Name: mfs_ctz_nwrtooff + * Name: mfs_lru_ctzflush * * Description: - * Write deltas of an LRU node to flash. + * Flush the updates of a CTZ list inside the LRU to the flash. * * Input Parameters: - * sb - Superblock instance of the device. - * node - LRU Node. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * ctz_sz - Number of bytes in the data of the CTZ list. - * new_ctz - New CTZ location + * sb - Superblock instance of the device. + * path - CTZ representation of the relpath. + * depth - Depth of path. * ****************************************************************************/ -int mfs_ctz_nwrtooff(FAR struct mfs_sb_s * const sb, - FAR struct mfs_node_s *node, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz, FAR struct mfs_ctz_s *new_ctz); - -/* mnemofs_lru.c */ +int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, const mfs_t depth); /**************************************************************************** * Name: mfs_lru_del @@ -1201,15 +1222,14 @@ int mfs_ctz_nwrtooff(FAR struct mfs_sb_s * const sb, * sb - Superblock instance of the device. * off - Offset into the data. * bytes - Number of bytes to delete. - * ctz_sz - Number of bytes in the data of the CTZ list. * path - CTZ representation of the relpath. * depth - Depth of path. * ****************************************************************************/ -int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t off, - mfs_t bytes, mfs_t ctz_sz, - FAR struct mfs_path_s * const path, const mfs_t depth); +int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t data_off, + mfs_t bytes, FAR struct mfs_path_s * const path, + const mfs_t depth); /**************************************************************************** * Name: mfs_lru_wr @@ -1221,7 +1241,6 @@ int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t off, * sb - Superblock instance of the device. * data_off - Offset into the data. * bytes - Number of bytes to delete. - * ctz_sz - Number of bytes in the data of the CTZ list. * path - CTZ representation of the relpath. * depth - Depth of path. * buf - Buffer. @@ -1229,26 +1248,21 @@ int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t off, ****************************************************************************/ int mfs_lru_wr(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t bytes, mfs_t ctz_sz, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf); + mfs_t bytes, FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char *buf); /**************************************************************************** - * Name: mfs_lru_ctzflush + * Name: mfs_lru_init * * Description: - * Flush the updates of a CTZ list inside the LRU to the flash. + * Initialize LRU. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * ctz_sz - Size of the CTZ file. + * sb - Superblock instance of the device. * ****************************************************************************/ -int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz); +void mfs_lru_init(FAR struct mfs_sb_s * const sb); /**************************************************************************** * Name: mfs_lru_rdfromoff @@ -1266,40 +1280,52 @@ int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -int mfs_lru_rdfromoff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, +int mfs_lru_rdfromoff(FAR const struct mfs_sb_s * const sb, + const mfs_t data_off, FAR struct mfs_path_s * const path, const mfs_t depth, FAR char *buf, const mfs_t buflen); /**************************************************************************** - * Name: mfs_lru_init + * Name: mfs_lru_updatedinfo * * Description: - * Initialize LRU. + * Update information of the path. * * Input Parameters: - * sb - Superblock instance of the device. + * sb - Superblock instance of the device. + * path - CTZ representation of the relpath. + * depth - Depth of path. + * + * Assumptions/Limitations: + * The will update path. * ****************************************************************************/ -void mfs_lru_init(FAR struct mfs_sb_s * const sb); +int mfs_lru_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth); /**************************************************************************** - * Name: mfs_lru_updatedsz + * Name: mfs_lru_updatectz * * Description: - * Update size of a CTZ list. + * Update CTZ location of an fs object. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * n_sz - New size. + * sb - Superblock instance of the device. + * path - Old CTZ representation of the relpath. + * depth - Depth of path. + * new_ctz - New CTZ location. + * + * Assumptions/Limitations: + * The update the CTZ portion of the direntry in the parent. + * This updates the path as well. * ****************************************************************************/ -void mfs_lru_updatedsz(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, mfs_t *n_sz); +int mfs_lru_updatectz(FAR struct mfs_sb_s * sb, + FAR struct mfs_path_s * const path, const mfs_t depth, + const struct mfs_ctz_s new_ctz); /* mnemofs_master.c */ @@ -1436,8 +1462,8 @@ mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -int mfs_get_patharr(FAR struct mfs_sb_s *const sb, - FAR const char *relpath, FAR struct mfs_path_s **path, +int mfs_get_patharr(FAR const struct mfs_sb_s * const sb, + FAR const char * relpath, FAR struct mfs_path_s **path, FAR mfs_t *depth); /**************************************************************************** @@ -1472,7 +1498,8 @@ void mfs_free_patharr(FAR struct mfs_path_s *path); ****************************************************************************/ bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr); + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr); /**************************************************************************** * Name: mfs_pitr_init @@ -1509,9 +1536,9 @@ bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -void mfs_pitr_init(FAR struct mfs_sb_s * const sb, +int mfs_pitr_init(FAR const struct mfs_sb_s * const sb, FAR const struct mfs_path_s * const path, - const mfs_t depth, FAR struct mfs_pitr_s *pitr, + const mfs_t depth, FAR struct mfs_pitr_s * const pitr, bool child); /**************************************************************************** @@ -1529,7 +1556,7 @@ void mfs_pitr_init(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -void mfs_pitr_free(FAR struct mfs_pitr_s * const pitr); +void mfs_pitr_free(FAR const struct mfs_pitr_s * const pitr); /**************************************************************************** * Name: mfs_pitr_adv @@ -1547,11 +1574,12 @@ void mfs_pitr_free(FAR struct mfs_pitr_s * const pitr); * ****************************************************************************/ -void mfs_pitr_adv(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr); +int mfs_pitr_adv(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr); /**************************************************************************** - * Name: mfs_pitr_adv_dirent + * Name: mfs_pitr_adv_bydirent * * Description: * Advance a pitr to the next direntry by using current direntry. @@ -1567,8 +1595,8 @@ void mfs_pitr_adv(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -void mfs_pitr_adv_dirent(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_dirent_s * const dirent); +void mfs_pitr_adv_bydirent(FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_dirent_s * const dirent); /**************************************************************************** * Name: mfs_pitr_adv_off @@ -1598,7 +1626,6 @@ void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, * Input Parameters: * pitr - Parent iterator. * path - CTZ representation of the relpath - * depth - Depth of path. * * Assumptions/Limitations: * This assumes that the pitr is initialized for the immediate parent of the @@ -1607,8 +1634,7 @@ void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, ****************************************************************************/ void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth); + FAR const struct mfs_path_s * const path); /**************************************************************************** * Name: mfs_pitr_reset @@ -1623,30 +1649,6 @@ void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, void mfs_pitr_reset(FAR struct mfs_pitr_s * const pitr); -/**************************************************************************** - * Name: mfs_pitr_sync - * - * Description: - * Sync a pitr. - * - * In mnemofs, when moving between locked contexts, it may happen that a - * a CTZ is moved to some place is between. This updates the location by - * reading the journal to check for any related logs in the journal. - * Updates contained in the LRU do not update the location of a CTZ list. - * - * Input Parameters: - * sb - Superblock instance of the device. - * pitr - Parent iterator. - * path - CTZ representation of the relpath - * depth - Depth of path. - * - ****************************************************************************/ - -void mfs_pitr_sync(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth); - /**************************************************************************** * Name: mfs_pitr_readdirent * @@ -1667,7 +1669,8 @@ void mfs_pitr_sync(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -int mfs_pitr_readdirent(FAR struct mfs_sb_s * const sb, +int mfs_pitr_readdirent(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, FAR struct mfs_pitr_s * const pitr, FAR struct mfs_dirent_s **dirent); @@ -1734,7 +1737,7 @@ bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb, int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, FAR struct mfs_path_s * const path, const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, + FAR struct mfs_pitr_s * const pitr, FAR const struct mfs_dirent_s * const dirent); /**************************************************************************** @@ -1745,24 +1748,27 @@ int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, * initialized in pitr. This creates the direntry. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Depth of path. - * pitr - Parent Iterator. - * dirent - Directory entry to be added. - * mode - Mode of the file/directory. + * sb - Superblock instance of the device. + * path - CTZ representation of the relpath. + * depth - Depth of path. + * pitr - Parent Iterator. + * relpath - Relative path of the fs object. + * mode - Mode of the file/directory. * * Returned Value: * 0 - OK * < 0 - Error * + * Assumptions/Limitations: + * This assumes that the fs object desired to be appended appears at the + * end of the entire relpath. + * ****************************************************************************/ int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, - FAR const char * const child_name, const mode_t mode); + FAR struct mfs_path_s * const path, const mfs_t depth, + FAR struct mfs_pitr_s * const pitr, + FAR const char * const relpath, const mode_t mode); /**************************************************************************** * Name: mfs_pitr_rmdirent diff --git a/fs/mnemofs/mnemofs_blkalloc.c b/fs/mnemofs/mnemofs_blkalloc.c index 254675995f4c5..9bc135c6d1ca1 100644 --- a/fs/mnemofs/mnemofs_blkalloc.c +++ b/fs/mnemofs/mnemofs_blkalloc.c @@ -91,7 +91,7 @@ * Pre-processor Definitions ****************************************************************************/ -#define BMAP_GET(bmap, idx, off) ((bmap)[(idx)] & (1 << (off))) +#define BMAP_GET(bmap, idx, off) (((bmap)[(idx)] & (1 << (off))) != 0) #define BMAP_SET(bmap, idx, off) ((bmap)[(idx)] |= (1 << (off))) #define DEL_ARR_BLK(sb, blk) (MFS_BA((sb)).k_del[(blk) * sizeof(size_t)]) #define DEL_ARR_PG(sb, pg) (DEL_ARR_BLK(sb, MFS_PG2BLK((sb), (pg)))) @@ -134,14 +134,8 @@ static int is_blk_writeable(FAR struct mfs_sb_s * const sb, * idx - Populated later with the index of page in MFS_BA(sb).bmap_upgs * off - Populated later with the offset of page in MFS_BA(sb).bmap_upgs * - * Returned Value: - * MFS_BLK_BAD - If the block of the page is a bad block. - * MFS_PG_USED - If the page is being used. - * MFS_BLK_ERASABLE - If page can be allocated, but block needs erase. - * MFS_PG_FREE - If the page is free. - * * Assumptions/Limitations: - * Does not check validity of the page number. + * Does not check validity of the index. * ****************************************************************************/ @@ -503,13 +497,28 @@ void mfs_ba_pgmarkdel(FAR struct mfs_sb_s * const sb, mfs_t pg) void mfs_ba_blkmarkdel(FAR struct mfs_sb_s * const sb, mfs_t blk) { - mfs_erase_blk(sb, blk); - DEL_ARR_BLK(sb, blk) = 0; + DEL_ARR_BLK(sb, blk) = MFS_PGINBLK(sb); } -void mfs_ba_delmarked(FAR struct mfs_sb_s * const sb) +int mfs_ba_delmarked(FAR struct mfs_sb_s * const sb) { - /* TODO */ + int ret = OK; + mfs_t i; + + for (i = 1; i < MFS_NBLKS(sb); i++) + { + if (DEL_ARR_BLK(sb, i) == MFS_PGINBLK(sb)) + { + ret = mfs_erase_blk(sb, i); + + if (ret != OK) + { + return ret; + } + } + } + + return ret; } /* Mark a page as being used. Used by master node during initial format and @@ -517,15 +526,16 @@ void mfs_ba_delmarked(FAR struct mfs_sb_s * const sb) void mfs_ba_markusedpg(FAR struct mfs_sb_s * const sb, mfs_t pg) { - mfs_t idx; + mfs_t idx; uint8_t off; + pg2bmap(pg, &idx, &off); BMAP_SET(MFS_BA(sb).bmap_upgs, idx, off); /* Set as used */ } void mfs_ba_markusedblk(FAR struct mfs_sb_s * const sb, mfs_t blk) { - mfs_t i = 0; + mfs_t i = 0; mfs_t pg = MFS_BLK2PG(sb, blk); for (i = 0; i < MFS_PGINBLK(sb); i++) diff --git a/fs/mnemofs/mnemofs_ctz.c b/fs/mnemofs/mnemofs_ctz.c index f24111f34eb8b..9db41c664397d 100644 --- a/fs/mnemofs/mnemofs_ctz.c +++ b/fs/mnemofs/mnemofs_ctz.c @@ -157,7 +157,11 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, static mfs_t ctz_idx_nptrs(const mfs_t idx) { - return idx == 0 ? 0 : mfs_ctz(idx) + 1; + mfs_t ret; + + ret = (idx == 0) ? 0 : mfs_ctz(idx) + 1; + finfo("Number of pointers for %u index is %u.", idx, ret); + return ret; } /**************************************************************************** @@ -179,17 +183,29 @@ static mfs_t ctz_idx_nptrs(const mfs_t idx) static void ctz_off2loc(FAR const struct mfs_sb_s * const sb, mfs_t off, FAR mfs_t *idx, FAR mfs_t *pgoff) { - const mfs_t den = MFS_PGSZ(sb) - 8; - if (off < MFS_PGSZ(sb)) + const mfs_t wb = sizeof(mfs_t); + const mfs_t den = MFS_PGSZ(sb) - 2 * wb; + + if (off < den) { *idx = 0; *pgoff = off; return; } - *idx = floor((off - 4 * (__builtin_popcount((off / den) - 1) + 2)) - / den); - *pgoff = off - den * (*idx) - 4 * __builtin_popcount(*idx); + if (idx != NULL) + { + *idx = (off - wb * (__builtin_popcount((off / den) - 1) + 2)) / den; + } + + if (pgoff != NULL) + { + *pgoff = off - den * (*idx) - wb * __builtin_popcount(*idx) + - (ctz_idx_nptrs(*idx) * wb); + } + + finfo("Offset %u. Calculated index %u and page offset %u.", off, *idx, + *pgoff); } /**************************************************************************** @@ -210,7 +226,11 @@ static void ctz_off2loc(FAR const struct mfs_sb_s * const sb, mfs_t off, static mfs_t ctz_blkdatasz(FAR const struct mfs_sb_s * const sb, const mfs_t idx) { - return MFS_PGSZ(sb) - (ctz_idx_nptrs(idx) * MFS_LOGPGSZ(sb)); + mfs_t ret; + + ret = MFS_PGSZ(sb) - (ctz_idx_nptrs(idx) * MFS_LOGPGSZ(sb)); + finfo("Block data size for index %u is %u.", idx, ret); + return ret; } /**************************************************************************** @@ -261,6 +281,11 @@ static mfs_t ctz_travel(FAR const struct mfs_sb_s * const sb, mfs_t idx_src, mfs_read_page(sb, buf, 4, pg, MFS_PGSZ(sb) - (4 * pow)); mfs_deser_mfs(buf, &pg); idx -= (1 << pow); + + if (pg == 0) + { + return 0; + } } if (idx == idx_dest) @@ -278,8 +303,16 @@ static mfs_t ctz_travel(FAR const struct mfs_sb_s * const sb, mfs_t idx_src, mfs_deser_mfs(buf, &pg); idx -= (1 << pow); diff -= (1 << pow); + + if (pg == 0) + { + return 0; + } } + finfo("Travel from index %u at page %u to index %u at page %u.", idx_src, + pg_src, idx_dest, pg); + return pg; } @@ -299,11 +332,11 @@ static mfs_t ctz_travel(FAR const struct mfs_sb_s * const sb, mfs_t idx_src, * buffer, then write the data to the flash. * * Input Parameters: - * sb - Superblock instance of the device. - * ctz - CTZ list to use as a reference. - * idx - Index of the block who's supposed pointers are to be copied. - * buf - Buffer representing the entire CTZ block where pointers are - * copied to. + * sb - Superblock instance of the device. + * ctz - CTZ list to use as a reference. + * idx - Index of the block who's supposed pointers are to be copied. + * buf - Buffer representing the entire CTZ block where pointers are + * copied to. * * Assumptions/Limitations: * This assumes `idx` is not more than `ctz->idx_e + 1`. @@ -330,12 +363,19 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, if (idx != ctz.idx_e + 1) { + /* We travel to the second last "known" CTZ block. */ + ctz.pg_e = ctz_travel(sb, ctz.idx_e, ctz.pg_e, idx - 1); ctz.idx_e = idx - 1; } buf += MFS_PGSZ(sb); /* Go to buf + pg_sz */ + DEBUGASSERT(idx == ctz.idx_e + 1); + + finfo("Copying %u pointers for CTZ (%u, %u) at index %u.", n_ptrs, + ctz.idx_e, ctz.pg_e, idx); + for (i = 0; i < n_ptrs; i++) { if (predict_false(i == 0)) @@ -355,6 +395,8 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, buf -= MFS_CTZ_PTRSZ; mfs_ser_mfs(prev_pg, buf); + + finfo("Copied %u page number to %uth pointer.", prev_pg, i); } } @@ -362,409 +404,257 @@ static void ctz_copyidxptrs(FAR const struct mfs_sb_s * const sb, * Public Functions ****************************************************************************/ -int mfs_ctz_rdfromoff(FAR struct mfs_sb_s * const sb, mfs_t data_off, - FAR struct mfs_path_s * const path, const mfs_t depth, - FAR char *buf, mfs_t buflen) +int mfs_ctz_rdfromoff(FAR const struct mfs_sb_s * const sb, + const struct mfs_ctz_s ctz, mfs_t data_off, + mfs_t len, FAR char * buf) { - int ret = OK; - mfs_t sz; - mfs_t pg; - mfs_t idx; - mfs_t off; - struct mfs_ctz_s ctz; - - /* Get updated location from the journal */ - - finfo("Journal upd!"); - DEBUGASSERT(depth > 0); - mfs_jrnl_updatepath(sb, path, depth); - ctz = path[depth - 1].ctz; - - ctz_off2loc(sb, data_off, &idx, &off); - - /* TODO: Make the traversal in reverse direction. It would cause - * a lot less traversals. - */ - - while (idx <= ctz.idx_e && off - data_off < buflen) - { - sz = ctz_blkdatasz(sb, idx); - pg = ctz_travel(sb, ctz.idx_e, ctz.pg_e, idx); - - ret = mfs_read_page(sb, buf, sz, pg, off); - if (predict_false(ret < 0)) - { - return ret; - } - - off = 0; - idx++; - buf += sz; - } - - return ret; -} - -int mfs_ctz_nwrtooff(FAR struct mfs_sb_s * const sb, - FAR struct mfs_node_s *node, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz, FAR struct mfs_ctz_s *new_ctz) -{ - int ret = OK; - bool del; - mfs_t pg; - mfs_t sz; - mfs_t inc; - mfs_t idx; - mfs_t bytes; - mfs_t pgoff; - mfs_t itr_min; - mfs_t itr_max; - mfs_t neg_off; /* Negative offset due to delete. */ - FAR char *buf = NULL; - const mfs_t range_min = node->range_min; - const mfs_t range_max = node->range_max; - struct mfs_ctz_s ctz; - FAR struct mfs_delta_s *delta = NULL; - - buf = kmm_zalloc(MFS_PGSZ(sb)); - if (predict_false(buf == NULL)) + int ret = OK; + mfs_t i; + mfs_t rd_sz; + mfs_t cur_pg; + mfs_t cur_idx; + mfs_t cur_pgoff; + mfs_t end_idx; + mfs_t end_pgoff; + mfs_t pg_rd_sz; + + ctz_off2loc(sb, data_off + len, &cur_idx, &cur_pgoff); + ctz_off2loc(sb, data_off, &end_idx, &end_pgoff); + + if (ctz.idx_e < cur_idx || ctz.idx_e < end_idx) { - ret = -ENOMEM; goto errout; } - /* CoW of items in block before range_min */ + cur_pg = ctz_travel(sb, ctz.idx_e, ctz.pg_e, cur_idx); + rd_sz = 0; - ctz_off2loc(sb, range_min, &idx, &pgoff); - DEBUGASSERT(depth > 0); - pg = ctz_travel(sb, path[depth - 1].ctz.idx_e, path[depth - 1].ctz.pg_e, - idx); - if (predict_false(pg == 0)) + if (predict_false(cur_pg == 0)) { - ret = -EINVAL; - goto errout_with_buf; + goto errout; } - ctz.idx_e = idx - 1; - ctz.pg_e = pg; - mfs_read_page(sb, buf, pgoff, pg, pgoff); - - /* Updates */ - - bytes = range_min; - itr_max = range_min; - neg_off = 0; - del = false; + /* O(n) read by reading in reverse. */ - while (bytes < range_max) + if (cur_idx != end_idx) { - if (!del) - { - memset(buf, 0, MFS_PGSZ(sb)); - sz = ctz_blkdatasz(sb, ctz.idx_e + 1); - itr_min = itr_max; - itr_max += sz; - ctz_copyidxptrs(sb, ctz, ctz.idx_e + 1, buf); - } - else + for (i = cur_idx; i >= end_idx; i--) { - inc = itr_max - itr_min; - itr_min = itr_max; - itr_min = sz - inc; - } - - del = false; - mfs_ctz_rdfromoff(sb, itr_min + neg_off, path, depth, buf + pgoff, sz); - - list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) - { - if (delta->off + delta->n_b <= itr_min || itr_max <= delta->off) + if (predict_false(i == cur_idx)) { - /* Out of range */ - - continue; + pg_rd_sz = cur_pgoff; + ret = mfs_read_page(sb, buf - pg_rd_sz, pg_rd_sz, cur_pg, + 0); + cur_pgoff = 0; } - - inc = MIN(itr_max, delta->off + delta->n_b) - delta->off; - - if (delta->upd != NULL) + else if (predict_false(i == end_idx)) { - /* Update */ - - memcpy(buf + pgoff + (delta->off - itr_min), delta->upd, inc); + pg_rd_sz = ctz_blkdatasz(sb, i) - end_pgoff; + ret = mfs_read_page(sb, buf - pg_rd_sz, pg_rd_sz, cur_pg, + end_pgoff); } else { - /* Delete */ - - memmove(buf + pgoff + (delta->off - itr_min), - buf + pgoff + (delta->off - itr_min) + inc, - itr_max - (delta->off + inc)); - itr_max -= inc; - neg_off += inc; - del = true; + pg_rd_sz = ctz_blkdatasz(sb, i); + ret = mfs_read_page(sb, buf - pg_rd_sz, pg_rd_sz, cur_pg, + 0); } - } - bytes += itr_max - itr_min; - - if (!del) - { - pgoff = 0; - pg = mfs_ba_getpg(sb); - if (pg == 0) + if (predict_false(ret == 0)) { - ret = -ENOSPC; - goto errout_with_buf; + ret = -EINVAL; + goto errout; } - mfs_write_page(sb, buf, MFS_PGSZ(sb), pg, 0); - ctz.pg_e = pg; - ctz.idx_e++; + buf -= pg_rd_sz; } - else - { - pgoff += itr_max - itr_min; - } - } - /* Copy rest of the file. */ + cur_pg = ctz_travel(sb, cur_idx, cur_pg, cur_idx - 1); - if (del) - { - mfs_ctz_rdfromoff(sb, itr_max + neg_off, path, depth, buf + pgoff, - sz - pgoff); - pg = mfs_ba_getpg(sb); - if (pg == 0) + if (predict_false(cur_pg == 0)) { - ret = -ENOSPC; - goto errout_with_buf; + ret = -EINVAL; + goto errout; } - - mfs_write_page(sb, buf, MFS_PGSZ(sb), pg, 0); - ctz.pg_e = pg; - ctz.idx_e++; - itr_max += sz - pgoff; - pgoff = 0; } - - while (bytes < ctz_sz) + else { - sz = ctz_blkdatasz(sb, ctz.idx_e + 1); - mfs_ctz_rdfromoff(sb, itr_max + neg_off, path, depth, buf, - MIN(MFS_PGSZ(sb), ctz_sz - bytes)); - pg = mfs_ba_getpg(sb); - if (pg == 0) + ret = mfs_read_page(sb, buf, len, cur_pg, end_pgoff); + + if (predict_false(ret == 0)) { - ret = -ENOSPC; - goto errout_with_buf; + ret = -EINVAL; + goto errout; } - - mfs_write_page(sb, buf, MFS_PGSZ(sb), pg, 0); - bytes += MIN(MFS_PGSZ(sb), ctz_sz - bytes); } - /* TODO: Check for cases where delete, but no further data at the end. - * , which might cause an infinite loop. - */ - -errout_with_buf: - kmm_free(buf); - errout: return ret; } -int mfs_ctz_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t o_bytes, const mfs_t n_bytes, - mfs_t o_ctz_sz, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf, - FAR struct mfs_ctz_s *ctz) +int mfs_ctz_wrtnode(FAR struct mfs_sb_s * const sb, + FAR const struct mfs_node_s * const node) { - int ret = OK; - bool partial; - mfs_t partial_bytes; /* Bytes partially filled. */ - mfs_t pg; - mfs_t off; - mfs_t idx; - mfs_t bytes; - mfs_t o_pg; - mfs_t o_off; - mfs_t o_idx; - mfs_t o_rembytes; - mfs_t o_data_off; - mfs_t n_pg; - mfs_t n_data_off; - mfs_t ctz_blk_datasz; - FAR char *data; - struct mfs_ctz_s o_ctz; - struct mfs_ctz_s n_ctz; - - data = kmm_zalloc(MFS_PGSZ(sb)); - if (predict_false(data == NULL)) + int ret = OK; + bool written = false; + mfs_t prev; + mfs_t rem_sz; + mfs_t new_pg; + mfs_t cur_pg; + mfs_t cur_idx; + mfs_t cur_pgoff; + mfs_t lower; + mfs_t upper; + mfs_t upper_og; + mfs_t lower_upd; + mfs_t upper_upd; + mfs_t del_bytes; + FAR char *buf = NULL; + FAR char *tmp = NULL; + struct mfs_ctz_s ctz; + FAR struct mfs_delta_s *delta; + + /* Traverse common CTZ blocks. */ + + ctz_off2loc(sb, node->range_min, &cur_idx, &cur_pgoff); + ctz = node->path[node->depth - 1].ctz; + cur_pg = ctz_travel(sb, ctz.idx_e, ctz.pg_e, cur_idx); + + /* So, till cur_idx - 1, the CTZ blocks are common. */ + + buf = kmm_zalloc(MFS_PGSZ(sb)); + if (predict_false(buf == NULL)) { ret = -ENOMEM; goto errout; } - /* Get updated location from the journal. */ - - DEBUGASSERT(depth > 0); - mfs_jrnl_updatepath(sb, path, depth); - o_ctz = path[depth - 1].ctz; - - /* TODO: Make the traversal in reverse direction. It would cause - * a lot less traversals. + /* Initially, there might be some offset in cur_idx CTZ blocks that is + * unmodified as well. */ - ctz_off2loc(sb, data_off, &idx, &off); + tmp = buf; + mfs_read_page(sb, tmp, cur_pgoff, cur_pg, 0); + tmp += cur_pgoff; - /* Reach the common part. */ + /* Modifications. */ - if (idx != 0 && off != 0) - { - pg = ctz_travel(sb, o_ctz.idx_e, o_ctz.pg_e, idx - 1); - n_ctz.idx_e = idx - 1; - n_ctz.pg_e = pg; - } - else - { - pg = o_ctz.pg_e; - n_ctz.idx_e = 0; - n_ctz.pg_e = pg; - finfo("CTZ: %u %u %u", pg, n_ctz.idx_e, n_ctz.pg_e); - } + prev = 0; + rem_sz = node->sz; + lower = node->range_min; + del_bytes = 0; - /* Add new data from buf. */ + /* [lower, upper) range. Two pointer approach. Window gets narrower + * for every delete falling inside it. + */ - partial = false; - o_rembytes = o_ctz_sz - (data_off + o_bytes); - bytes = data_off; - if (n_bytes != 0) + while (rem_sz > 0) { - while (bytes < data_off + n_bytes) - { - n_pg = mfs_ba_getpg(sb); - if (n_pg) - { - ret = -ENOSPC; - goto errout_with_data; - } + upper = MIN(prev + lower + ctz_blkdatasz(sb, cur_idx), rem_sz); + upper_og = upper; - ctz_copyidxptrs(sb, n_ctz, idx, data); /* Handles idx == 0. */ - ctz_blk_datasz = ctz_blkdatasz(sb, idx); - - if (predict_false(off != 0)) + list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) + { + if (delta->upd == NULL) { - /* This happens at max for the first iteration of the loop. */ - - mfs_read_page(sb, data, off, - ctz_travel(sb, o_ctz.idx_e, o_ctz.pg_e, idx), 0); - bytes += off; - } + /* Delete */ - memcpy(data + off, buf + bytes, - MIN(ctz_blk_datasz - off, n_bytes - bytes)); - if (n_bytes - bytes < ctz_blk_datasz - off && o_rembytes != 0) - { - partial = true; - partial_bytes = n_bytes - bytes; + lower_upd = MAX(lower, delta->off); + upper_upd = MIN(upper, delta->off + delta->n_b); + + if (lower_upd >= upper_upd) + { + /* Skip this delta. */ + + continue; + } + else + { + del_bytes += upper_upd - lower_upd; + memmove(tmp + lower_upd, tmp + upper_upd, + upper - upper_upd); + upper -= upper_upd; + } } else { - bytes += ctz_blk_datasz - off; + /* Update */ + + ret = mfs_ctz_rdfromoff(sb, ctz, lower, upper - lower, + tmp); + if (predict_false(ret < 0)) + { + goto errout_with_buf; + } } + } - if (predict_false(off != 0)) - { - /* This happens at max for the first iteration of the loop. */ + /* rem_sz check for final write. */ - off = 0; - } + if (upper == upper_og || rem_sz == upper - lower) + { + prev = 0; + + /* Time to write a page for new CTZ list. */ - if (predict_true(!partial)) + new_pg = mfs_ba_getpg(sb); + if (predict_false(new_pg == 0)) { - mfs_write_page(sb, data, MFS_PGSZ(sb), n_pg, 0); - n_ctz.idx_e = idx; - n_ctz.pg_e = pg; + ret = -ENOSPC; + goto errout_with_buf; } - else + + ctz_copyidxptrs(sb, ctz, cur_idx, buf); + ret = mfs_write_page(sb, buf, MFS_PGSZ(sb), new_pg, 0); + if (predict_false(ret == 0)) { - /* In this case, we have a situation where there is still - * some empty area left in the page, and there is some data - * that is waiting to be fit in there, so we won't write it - * to the flash JUST yet. We'll fill in the rest of the data - * and THEN write it. - * - * It's okay to leave the loop as this case will happen, if at - * all, on the last iteration of the loop. - */ - - n_ctz.idx_e = idx; - n_ctz.pg_e = pg; - break; + ret = -EINVAL; + goto errout_with_buf; } - idx++; + memset(buf, 0, MFS_PGSZ(sb)); + tmp = buf; + cur_idx++; + + written = true; + } + else + { + tmp += upper - lower; - memset(data, 0, MFS_PGSZ(sb)); + written = false; } + + prev = upper - lower; + rem_sz -= upper - lower; + lower = upper; } - o_data_off = data_off + o_bytes; - n_data_off = data_off + n_bytes; + DEBUGASSERT(written); + + /* TODO: Need to verify for cases where the delete extends outside, etc. */ - /* Completing partially filled data, if present. */ + /* Write log. */ - if (partial) + ctz.idx_e = cur_idx; + ctz.pg_e = new_pg; + ret = mfs_jrnl_wrlog(sb, *node, ctz, node->sz); + if (predict_false(ret < 0)) { - ctz_off2loc(sb, o_data_off, &o_idx, &o_off); - o_pg = ctz_travel(sb, o_ctz.idx_e, o_ctz.pg_e, o_idx); - mfs_read_page(sb, data + partial_bytes, - ctz_blkdatasz(sb, n_ctz.idx_e) - partial_bytes, o_pg, - o_off); - mfs_write_page(sb, data, MFS_PGSZ(sb), n_ctz.pg_e, 0); - - o_data_off += partial_bytes; - n_data_off += partial_bytes; - partial_bytes = 0; - partial = false; + goto errout_with_buf; } - /* Adding old bytes in. */ - - while (o_data_off < o_ctz_sz) + if (MFS_JRNL(sb).log_cblkidx >= MFS_JRNL_LIM(sb)) { - memset(data, 0, MFS_PGSZ(sb)); - - pg = mfs_ba_getpg(sb); - if (predict_false(pg == 0)) + ret = mfs_jrnl_flush(sb); + if (predict_false(ret < 0)) { - ret = -ENOSPC; - goto errout_with_data; + goto errout_with_buf; } - - ctz_blk_datasz = ctz_blkdatasz(sb, n_ctz.idx_e + 1); - ctz_copyidxptrs(sb, n_ctz, n_ctz.idx_e + 1, data); - - mfs_ctz_rdfromoff(sb, o_data_off, path, depth, data, ctz_blk_datasz); - mfs_write_page(sb, data, MFS_PGSZ(sb), pg, 0); - - n_ctz.idx_e++; - n_ctz.pg_e = pg; - - o_data_off += ctz_blk_datasz; } - mfs_jrnl_newlog(sb, path, depth, n_ctz); - - /* path is not updated to point to the new ctz. This is upto the caller. */ - - *ctz = n_ctz; - -errout_with_data: - kmm_free(data); +errout_with_buf: + kmm_free(buf); errout: return ret; diff --git a/fs/mnemofs/mnemofs_fsobj.c b/fs/mnemofs/mnemofs_fsobj.c index aea7ccd51dbdb..1d5fbd5e07978 100644 --- a/fs/mnemofs/mnemofs_fsobj.c +++ b/fs/mnemofs/mnemofs_fsobj.c @@ -63,6 +63,7 @@ ****************************************************************************/ #include +#include #include #include "mnemofs.h" @@ -81,15 +82,27 @@ static mfs_t nobjs_in_path(FAR const char * relpath); static const char *next_child(FAR const char *relpath); +static const char *last_child(FAR const char *relpath); static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x, FAR char * const out); static FAR const char *mfs_deser_dirent(FAR const char * const in, FAR struct mfs_dirent_s * const x); +static int search_ctz_by_name(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char * const name, + const mfs_t namelen, FAR mfs_t *off, + FAR struct mfs_dirent_s **dirent); + /**************************************************************************** * Private Data ****************************************************************************/ +const struct mfs_path_s empty_fsobj = +{ + 0 +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -117,6 +130,14 @@ static mfs_t nobjs_in_path(FAR const char *relpath) { mfs_t count; + /* If mount point is "/hi", then operations on "/hi/bye" and "/hi/hello/a" + * give respective relpaths as "bye" and "hello/a". Since mnemofs counts + * the root as 1 FS object, these respectively contain 2 and 3 FS objects + * in the path. The last FS object might be a file or a directory, but + * everything else is a directory. The number of FS objects in the path + * is the depth of the FS object the path refers to. + */ + if (*relpath == 0) { return 1; @@ -124,7 +145,7 @@ static mfs_t nobjs_in_path(FAR const char *relpath) count = 2; - while (*relpath == 0) + while (*relpath != 0) { if (*relpath == '/') { @@ -138,7 +159,7 @@ static mfs_t nobjs_in_path(FAR const char *relpath) } /**************************************************************************** - * Name: nobjs_in_path + * Name: next_child * * Description: * Give the pointer to next child that appears in the path. @@ -164,7 +185,38 @@ static const char *next_child(FAR const char *relpath) relpath++; } - return NULL; + return relpath; +} + +/**************************************************************************** + * Name: next_child + * + * Description: + * Give the pointer to next child that appears in the path. + * + * Input Parameters: + * relpath - Relative Path. + * + * Returned Value: + * The pointer to the next child. This is not allocated, but points to the + * inside relpath itself. + * + ****************************************************************************/ + +static const char *last_child(FAR const char *relpath) +{ + const mfs_t len = strlen(relpath); + mfs_t i; + + for (i = len - 1; i > 0; i--) + { + if (relpath[i - 1] == '/') + { + return relpath + i; + } + } + + return relpath; } /**************************************************************************** @@ -187,9 +239,9 @@ static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x, { FAR char *o = out; - o = mfs_ser_8(x->name_hash, o); + o = mfs_ser_16(x->name_hash, o); + o = mfs_ser_16(x->mode, o); o = mfs_ser_mfs(x->sz, o); - o = mfs_ser_mfs((mfs_t) x->mode, o); o = mfs_ser_timespec(&x->st_atim, o); o = mfs_ser_timespec(&x->st_mtim, o); o = mfs_ser_timespec(&x->st_ctim, o); @@ -220,9 +272,9 @@ static FAR const char *mfs_deser_dirent(FAR const char * const in, { FAR const char *i = in; - i = mfs_deser_8(i, &x->name_hash); + i = mfs_deser_16(i, &x->name_hash); + i = mfs_deser_16(i, &x->mode); i = mfs_deser_mfs(i, &x->sz); - i = mfs_deser_mfs(i, (mfs_t *) &x->mode); i = mfs_deser_timespec(i, &x->st_atim); i = mfs_deser_timespec(i, &x->st_mtim); i = mfs_deser_timespec(i, &x->st_ctim); @@ -263,8 +315,7 @@ mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb, } else if (depth == 1) { - sz = MFS_MN(sb).root_sz; - mfs_lru_updatedsz(sb, path, depth, &sz); + sz = MFS_MN(sb).root_sz; /* Updated size. */ /* Journal updated to the root creates a new master node entry. TODO * this and moving of the journal. @@ -277,218 +328,138 @@ mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb, return path[depth - 1].sz; } -int mfs_get_patharr(FAR struct mfs_sb_s *const sb, - FAR const char *relpath, FAR struct mfs_path_s **path, - FAR mfs_t *depth) +bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr) { - int ret; - bool found; - bool isfile; - mfs_t sz; - mfs_t idx; - uint8_t hash; - const mfs_t len = nobjs_in_path(relpath); - FAR const char *next; - struct mfs_pitr_s pitr; - FAR struct mfs_dirent_s *dirent; + bool ret; + FAR struct mfs_dirent_s *dirent = NULL; - ret = 0; - idx = 0; - isfile = false; - found = true; + mfs_pitr_readdirent(sb, path, pitr, &dirent); + ret = (dirent->sz == 0); + mfs_free_dirent(dirent); - *path = kmm_zalloc(len * sizeof(struct mfs_ctz_s)); - if (predict_false(*path == NULL)) - { - return -ENOMEM; - } + return ret; +} - *depth = len; - (*path)[idx].ctz = MFS_MN(sb).root_ctz; - (*path)[idx].off = 0; - (*path)[idx].sz = mfs_get_fsz(sb, *path, 1); +void mfs_free_dirent(FAR struct mfs_dirent_s *dirent) +{ + kmm_free(dirent); - finfo("Path \"%s\" depth %u.", relpath, len); + finfo("Dirent freed."); +} - if (len == 1) - { - ret |= MFS_P_EXIST | MFS_P_ISDIR | MFS_ISDIR; - goto errout; - } - else if (len == 2) - { - ret |= MFS_P_EXIST | MFS_P_ISDIR; - } +bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb, + FAR const struct mfs_path_s * const path, + const mfs_t depth) +{ + FAR struct mfs_ofd_s *ofd = NULL; - for (idx = 1; idx < len; idx++) + list_for_every_entry(&sb->of, ofd, struct mfs_ofd_s, list) { - mfs_pitr_init(sb, *path, idx - 1, &pitr, false); - - if (predict_false(idx == 1)) - { - next = relpath; - } - else + if (ofd->com->depth != depth) { - next = next_child(relpath); + continue; } - sz = next - relpath; - hash = mfs_arrhash(relpath, sz); + /* TODO: Ensure when an LRU's delta is flushed to the journal, the + * new location is updated in the LRU AND the open files, if it is + * open. + */ - for (; ; ) + if (mfs_path_eq(&ofd->com->path[depth - 1], &path[depth - 1])) { - mfs_pitr_readdirent(sb, &pitr, &dirent); - if (predict_false(dirent == NULL)) - { - found = false; - ret |= MFS_NEXIST; - break; - } - - if (dirent->name_hash == hash && - !strncmp(dirent->name, relpath, sz)) - { - (*path)[idx - 1].ctz = dirent->ctz; - (*path)[idx - 1].off = pitr.c_off; - (*path)[idx - 1].sz = dirent->sz; - - mfs_free_dirent(dirent); - - if (len >= 2 && idx == len - 2) - { - ret |= MFS_P_EXIST; - ret |= (S_ISDIR(dirent->mode) ? MFS_P_ISDIR : - (MFS_FINPATH | MFS_NEXIST)); - } - else if (idx == len - 1) - { - ret |= (S_ISDIR(dirent->mode) ? MFS_ISDIR : MFS_ISFILE); - } - else - { - ret |= (S_ISDIR(dirent->mode) ? 0 : - (MFS_FINPATH | MFS_NEXIST)); - } - - break; - } - - if (!S_ISDIR(dirent->mode)) - { - isfile = true; - } - - mfs_pitr_adv_dirent(&pitr, dirent); - - mfs_free_dirent(dirent); + return true; + } + } - if (isfile) - { - /* At max, only the last element is allowed to be a file. */ + return false; +} - break; - } - } +int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, + FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_dirent_s * const dirent) +{ + int ret = OK; + struct mfs_pitr_s p_pitr; + FAR struct mfs_dirent_s *p_dirent = NULL; - mfs_pitr_free(&pitr); + mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); + mfs_pitr_adv_tochild(&p_pitr, path); + mfs_pitr_readdirent(sb, path, &p_pitr, &p_dirent); - if (!found) - { - break; - } + ret = mfs_lru_del(sb, pitr->c_off, MFS_DIRENTSZ(dirent), path, depth); - relpath = next; - finfo("Next path \"%s\"", relpath); - } + mfs_free_dirent(p_dirent); + mfs_pitr_free(&p_pitr); -errout: - finfo("Path array for \"%s\", returned flags: %u.", relpath, ret); return ret; } -void mfs_free_patharr(FAR struct mfs_path_s *path) -{ - kmm_free(path); -} - -bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr) +int mfs_pitr_rm(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth) { + int ret = OK; + struct mfs_pitr_s pitr; FAR struct mfs_dirent_s *dirent = NULL; - bool ret; - mfs_pitr_readdirent(sb, pitr, &dirent); - ret = (dirent->sz == 0); + mfs_pitr_init(sb, path, depth, &pitr, true); + mfs_pitr_readdirent(sb, path, &pitr, &dirent); + ret = mfs_pitr_rmdirent(sb, path, depth, &pitr, dirent); mfs_free_dirent(dirent); + mfs_pitr_free(&pitr); return ret; } -void mfs_pitr_init(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, FAR struct mfs_pitr_s *pitr, - bool child) +int mfs_pitr_init(FAR const struct mfs_sb_s * const sb, + FAR const struct mfs_path_s * const path, + const mfs_t depth, FAR struct mfs_pitr_s * const pitr, + bool child) { - const uint8_t diff = child ? 1 : 0; - mfs_t p_depth; + /* Ensure updated CTZ location from the journal before this. */ + + int ret = OK; + const int diff = child ? 1 : 0; + const mfs_t p_depth = depth - diff; if (predict_false(depth < diff)) { - return; + ret = -EINVAL; + goto errout; } - p_depth = depth - diff; + pitr->c_off = 0; + pitr->depth = p_depth; - if (p_depth == 0) + if (predict_true(p_depth != 0)) { - /* Master Node */ - - pitr->sz = 0; - memset(&pitr->p, 0, sizeof(pitr->p)); + pitr->p = path[p_depth - 1]; } else { - pitr->p.ctz = path[p_depth - 1].ctz; - pitr->sz = path[p_depth - 1].sz; - } - - pitr->depth = p_depth; - pitr->c_off = 0; - - finfo("Pitr initialized for parent CTZ at (%u, %u) at" - " depth %u for file size %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->depth, pitr->sz); -} - -void mfs_pitr_free(FAR struct mfs_pitr_s * const pitr) -{ - finfo("Pitr for CTZ (%u, %u) at depth %u freed.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->depth); - - memset(pitr, 0, sizeof(*pitr)); -} + /* 0 or gabage value is fine for master node, not required. */ -void mfs_pitr_adv(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr) -{ - FAR struct mfs_dirent_s *dirent; + pitr->p.ctz.idx_e = 0; + pitr->p.ctz.pg_e = 0; + pitr->p.off = 0; + pitr->p.sz = 1; /* For 1 traversal to get root. */ + } - mfs_pitr_readdirent(sb, pitr, &dirent); - mfs_pitr_adv_dirent(pitr, dirent); - mfs_free_dirent(dirent); + finfo("Pitr initialized at depth %u, with CTZ (%u, %u) and size %u.", + p_depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->p.sz); - finfo("Pitr for CTZ (%u, %u) advanced to offset %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); +errout: + return ret; } -void mfs_pitr_adv_dirent(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_dirent_s * const dirent) +void mfs_pitr_free(FAR const struct mfs_pitr_s * const pitr) { - pitr->c_off += MFS_DIRENTSZ(dirent); - - finfo("Pitr for CTZ (%u, %u) advanced to offset %u using dirent.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); + finfo("Pitr at depth %u with CTZ (%u, %u) freed.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); } void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, @@ -496,119 +467,105 @@ void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, { pitr->c_off += off; - finfo("Pitr for CTZ (%u, %u) advanced to offset %u by offset %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off, off); + finfo("Pitr at depth %u with CTZ (%u, %u) advanced by %u to %u offset.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, off, pitr->c_off); } -void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth) +void mfs_pitr_adv_bydirent(FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_dirent_s * const dirent) { - if (pitr->depth == 0) - { - return; - } - - pitr->c_off = path[depth - 1].off; - - finfo("Pitr for CTZ (%u, %u) at depth %u advanced to offset %u.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, depth, path[depth - 1].off); -} - -void mfs_pitr_reset(FAR struct mfs_pitr_s * const pitr) -{ - pitr->c_off = 0; + mfs_pitr_adv_off(pitr, MFS_DIRENTSZ(dirent)); - finfo("Pitr for CTZ (%u, %u) reset.", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); + finfo("Pitr at depth %u with CTZ (%u, %u) advanced by %u to %u offset.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, + MFS_DIRENTSZ(dirent), pitr->c_off); } -void mfs_pitr_sync(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth) +void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_path_s * const path) { - finfo("Pitr for CTZ (%u, %u) syncing...", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); - - /* TODO: mfs_jrnl_updatectz(sb, &pitr->p.ctz, pitr->depth); */ - - pitr->sz = mfs_get_fsz(sb, path, depth - 1); + /* (pitr->depth + 1) - 1 is the child's index. */ - DEBUGASSERT(depth == pitr->depth); + pitr->c_off = path[pitr->depth].off; - finfo("New location is (%u, %u).", - pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); + finfo("Pitr at depth %u with CTZ (%u, %u) advanced to %u offset.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); } -int mfs_pitr_readdirent(FAR struct mfs_sb_s * const sb, +int mfs_pitr_readdirent(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, FAR struct mfs_pitr_s * const pitr, FAR struct mfs_dirent_s **dirent) { - int ret = OK; - mfs_t sz = 0; - const mfs_t len = sizeof(struct mfs_dirent_s) - + NAME_MAX + 1; - char dirent_data[len]; - struct mfs_dirent_s *dirent_rd = NULL; - - /* No harm in reading more. The namelen will stop all the included - * unnecessary characters during deserialization, and if there are none, - * the rest will be just empty. - */ - - memset(dirent_data, 0, len); + int ret = OK; + mfs_t sz; + const mfs_t len = sizeof(struct mfs_dirent_s) \ + + NAME_MAX + 1; + char rd[len]; + FAR struct mfs_dirent_s *d = NULL; + FAR struct mfs_dirent_s *tmp = NULL; + + if (dirent == NULL) + { + return ret; + } *dirent = NULL; + memset(rd, 0, len); - dirent_rd = kmm_zalloc(len); - if (predict_false(dirent_rd == NULL)) + d = kmm_zalloc(len); + if (predict_false(d == NULL)) { + ret = -ENOMEM; goto errout; } - - if (pitr->depth == 0) + else if (pitr->c_off >= pitr->p.sz) { - dirent_rd->ctz = MFS_MN(sb).root_ctz; - dirent_rd->mode = MFS_MN(sb).root_mode; - dirent_rd->st_atim = MFS_MN(sb).root_st_atim; - dirent_rd->st_ctim = MFS_MN(sb).root_st_ctim; - dirent_rd->st_mtim = MFS_MN(sb).root_st_mtim; - dirent_rd->mode = MFS_MN(sb).root_mode; - dirent_rd->sz = MFS_MN(sb).root_sz; - dirent_rd->namelen = 1; - dirent_rd->name_hash = 0; - - memcpy(dirent_rd->name, "", 2); + goto errout_with_d; } - else + else if (pitr->depth == 0) { - mfs_lru_rdfromoff(sb, pitr->c_off, &pitr->p, pitr->depth, - dirent_data, len); - mfs_deser_dirent(dirent_data, dirent_rd); - - finfo("Got direntry with name %s", dirent_rd->name); + d->name[0] = 0; + d->namelen = 0; + d->ctz = MFS_MN(sb).root_ctz; + d->mode = MFS_MN(sb).root_mode; + d->name_hash = mfs_hash(d->name, d->namelen); + d->st_atim = MFS_MN(sb).root_st_atim; + d->st_ctim = MFS_MN(sb).root_st_ctim; + d->st_mtim = MFS_MN(sb).root_st_mtim; + d->sz = MFS_MN(sb).root_sz; + + pitr->c_off = 1; /* To prevent infinite loop. */ } - - sz = MFS_DIRENTSZ(dirent_rd); - if (dirent_rd->namelen == 0) + else { - /* Not found direntry. */ + ret = mfs_lru_rdfromoff(sb, pitr->c_off, path, pitr->depth, rd, len); + if (predict_false(ret < 0)) + { + goto errout_with_d; + } - goto errout_with_dirent_rd; + mfs_deser_dirent(rd, d); } - *dirent = kmm_zalloc(sz); - if (predict_false(*dirent == NULL)) + sz = MFS_DIRENTSZ(d); + tmp = kmm_realloc(d, sz); + if (predict_true(tmp != NULL)) { - ret = -ENOMEM; - goto errout_with_dirent_rd; + d = tmp; } - memcpy(*dirent, dirent_rd, sz); + *dirent = d; + DEBUGASSERT(pitr->depth == 0 || strcmp(d->name, "")); + finfo("Read direntry at %u offset, %u depth for CTZ (%u, %u). " \ + "Direntry name: \"%s\" with name length %u.", + pitr->c_off, pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, + d->name, d->namelen); + + return ret; -errout_with_dirent_rd: - kmm_free(dirent_rd); +errout_with_d: + kmm_free(d); if (ret < 0) { @@ -618,171 +575,370 @@ int mfs_pitr_readdirent(FAR struct mfs_sb_s * const sb, { finfo("No direntry found."); } - else - { - finfo("Reading direntry done for %s.", (*dirent)->name); - } errout: return ret; } -void mfs_free_dirent(FAR struct mfs_dirent_s *dirent) +int mfs_pitr_adv(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s *path, + FAR struct mfs_pitr_s * const pitr) { - kmm_free(dirent); + int ret = OK; + FAR struct mfs_dirent_s *dirent; - finfo("Dirent freed."); + ret = mfs_pitr_readdirent(sb, path, pitr, &dirent); + if (predict_false(ret < 0)) + { + goto errout; + } + + mfs_pitr_adv_bydirent(pitr, dirent); + mfs_free_dirent(dirent); + + finfo("Pitr for CTZ (%u, %u) advanced to offset %u.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); + +errout: + return ret; } -bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth) +static int search_ctz_by_name(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char * const name, + const mfs_t namelen, FAR mfs_t *off, + FAR struct mfs_dirent_s **dirent) { - FAR struct mfs_ofd_s *ofd = NULL; + /* NOTE: depth is of the parent here. */ - list_for_every_entry(&sb->of, ofd, struct mfs_ofd_s, list) + /* Applies LRU updates. */ + + int ret = OK; + uint16_t name_hash; + struct mfs_pitr_s pitr; + FAR struct mfs_dirent_s *nd; + bool found = false; + + *dirent = NULL; + + if (depth == 0) { - if (ofd->com->depth != depth) + DEBUGASSERT(namelen == 0); + + nd = kmm_zalloc(sizeof(struct mfs_dirent_s)); + if (predict_false(nd == NULL)) { - continue; + ret = -ENOMEM; + goto errout; } - /* TODO: Ensure when an LRU's delta is flushed to the journal, the - * new location is updated in the LRU AND the open files, if it is - * open. - */ + *off = 0; + nd->namelen = namelen; + nd->ctz = MFS_MN(sb).root_ctz; + nd->mode = MFS_MN(sb).root_mode; + nd->name_hash = mfs_hash(nd->name, nd->namelen); + nd->st_atim = MFS_MN(sb).root_st_atim; + nd->st_ctim = MFS_MN(sb).root_st_ctim; + nd->st_mtim = MFS_MN(sb).root_st_mtim; + nd->sz = MFS_MN(sb).root_sz; + + *dirent = nd; + goto errout; + } + + name_hash = mfs_hash(name, namelen); - if (ofd->com->path[depth - 1].off == path[depth - 1].off && - ofd->com->path[depth - 1].ctz.pg_e == path[depth - 1].ctz.pg_e && - ofd->com->path[depth - 1].ctz.idx_e == path[depth - 1].ctz.idx_e) + ret = mfs_lru_updatedinfo(sb, path, depth); + if (predict_false(ret < 0)) + { + goto errout; + } + + ret = mfs_pitr_init(sb, path, depth, &pitr, false); + if (predict_false(ret < 0)) + { + goto errout; + } + + for (; ; ) + { + /* Readdirent takes care of LRU updates. */ + + ret = mfs_pitr_readdirent(sb, path, &pitr, &nd); + if (predict_false(ret < 0 || nd == NULL)) { - return true; + ret = -ENONET; + goto errout; } + + if (nd->name_hash == name_hash && + !strncmp(nd->name, name, MIN(nd->namelen, namelen))) + { + found = true; + path[depth].sz = nd->sz; + path[depth].ctz = nd->ctz; + path[depth].off = pitr.c_off; + *off = pitr.c_off; + break; + } + + mfs_pitr_adv_bydirent(&pitr, nd); + mfs_free_dirent(nd); } - return false; +errout: + if (found) + { + finfo("Searched \"%.*s\" direntry inside CTZ (%u, %u) at depth %u," + " size %u.", namelen, name, path[depth - 1].ctz.idx_e, + path[depth - 1].ctz.pg_e, depth, path[depth - 1].sz); + *dirent = nd; + } + else + { + ret = -ENOENT; + finfo("Can not find requested direntry in parent. Ret: %d.", ret); + } + + return ret; } -int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, - FAR const char * const child_name, - const mode_t mode) +int mfs_get_patharr(FAR const struct mfs_sb_s * const sb, + FAR const char * relpath, FAR struct mfs_path_s **path, + FAR mfs_t *depth) { - int ret = OK; - mfs_t len; - mfs_t pg; - struct mfs_dirent_s *dirent = NULL; - struct timespec ts; + int ret = OK; + int ret_flags = 0; + mfs_t i; + mfs_t sz; + mfs_t off; + mfs_t n_objs; + mfs_t name_len; + FAR const char *cur = NULL; + FAR const char *next = NULL; + struct mfs_ctz_s ctz; + FAR struct mfs_path_s *np = NULL; + FAR struct mfs_dirent_s *dirent = NULL; + + *path = NULL; + n_objs = nobjs_in_path(relpath); + np = kmm_zalloc(n_objs * sizeof(struct mfs_path_s)); + if (predict_false(np == NULL)) + { + ret = -ENOMEM; + goto errout; + } - len = strlen(child_name); + ctz = MFS_MN(sb).root_ctz; + sz = MFS_MN(sb).root_sz; + np[0].sz = sz; + np[0].ctz = ctz; + np[0].off = 0; + cur = relpath; + next = next_child(cur); + name_len = *next == 0 ? next - cur : next - cur - 1; - dirent = kmm_zalloc(sizeof(*dirent) + len); - if (predict_false(dirent == NULL)) + if (predict_false(n_objs == 1)) { - return -ENOMEM; - } + ret_flags |= MFS_ISDIR | MFS_EXIST; - clock_gettime(CLOCK_REALTIME, &ts); + /* This will not go into the loop. */ + } + else if (predict_false(n_objs == 2)) + { + ret_flags |= MFS_P_EXIST | MFS_P_ISDIR; + } - /* TODO: Confirm if creation for directory in VFS gives true for - * S_ISDIR(). - */ + /* MFS_MN(sb).root_* is always up to date, no need for journal update. */ - pg = mfs_ba_getpg(sb); - if (predict_false(pg == 0)) + for (i = 1; i < n_objs; i++) { - return -ENOSPC; + /* np[i] is the fs object at depth i + 1. */ + + /* Need to update journal for every level in the path as, for eg., the + * child can be deleted, etc. Same goes for LRU, which is taken care of + * by search_ctz_by_name function. + */ + + ret = search_ctz_by_name(sb, np, i, cur, name_len, &off, &dirent); + if (predict_false(ret < 0)) + { + goto errout_with_ret_flags; + } + + if (i < n_objs - 2 && !S_ISDIR(dirent->mode)) + { + ret_flags |= MFS_FINPATH; + goto errout_with_ret_flags; + } + else if (i == n_objs - 2) + { + ret_flags |= MFS_P_EXIST; + if (S_ISDIR(dirent->mode)) + { + ret_flags |= MFS_P_ISDIR; + } + else + { + ret_flags |= MFS_FINPATH; + goto errout_with_ret_flags; + } + } + else /* if (i == n_objs - 1) */ + { + ret_flags |= MFS_EXIST; + if (S_ISDIR(dirent->mode)) + { + ret_flags |= MFS_ISDIR; + } + else + { + ret_flags |= MFS_ISFILE; + } + } + + np[i].ctz = dirent->ctz; + np[i].off = off; + np[i].sz = dirent->sz; + + ctz = dirent->ctz; + + mfs_free_dirent(dirent); + + cur = next; + next = next_child(cur); + name_len = *next == 0 ? next - cur : next - cur - 1; } - dirent->sz = 0; - dirent->mode = mode; - dirent->ctz.pg_e = pg; - dirent->ctz.idx_e = 0; - dirent->st_atim = ts; - dirent->st_mtim = ts; - dirent->st_ctim = ts; - dirent->namelen = len; - strncpy(dirent->name, child_name, len); + ret = ret_flags; + *depth = n_objs; + *path = np; - ret = mfs_pitr_appenddirent(sb, path, depth, pitr, dirent); - finfo("New direntry %p with name \"%s\" appended to CTZ (%u, %u) " - "at offset %u depth %u.", - dirent, dirent->name, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, - pitr->c_off, pitr->depth); + finfo("Got path array with flags %u, depth %u.", ret, n_objs); + return ret; - mfs_free_dirent(dirent); +errout_with_ret_flags: + ret = ret_flags; + *depth = n_objs; + *path = np; + /* mfs_free_patharr(np) : All callers will free np (ie. path) when done + * with it. + */ + +errout: + finfo("Got path array with flags %u, depth %u.", ret, n_objs); return ret; } +void mfs_free_patharr(FAR struct mfs_path_s *path) +{ + kmm_free(path); +} + +void mfs_pitr_reset(FAR struct mfs_pitr_s * const pitr) +{ + pitr->c_off = 0; + + finfo("Pitr for CTZ (%u, %u) reset.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); +} + int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, FAR struct mfs_path_s * const path, const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, + FAR struct mfs_pitr_s * const pitr, FAR const struct mfs_dirent_s * const dirent) { - int ret = OK; - const mfs_t len = MFS_DIRENTSZ(dirent); - char dirent_data[len]; - struct mfs_pitr_s p_pitr; - FAR struct mfs_dirent_s *p_dirent = NULL; + /* Depth is depth of the child to be appended. */ - memset(dirent_data, 0, len); - mfs_ser_dirent(dirent, dirent_data); + int ret = OK; + const mfs_t len = MFS_DIRENTSZ(dirent); + char wd[len]; - mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); - mfs_pitr_adv_tochild(&p_pitr, path, depth - 1); - mfs_pitr_readdirent(sb, &p_pitr, &p_dirent); + if (pitr->depth == 0) + { + /* Root is the only child of the master node. */ + + ret = -EINVAL; + goto errout; + } - ret = mfs_lru_wr(sb, p_dirent->sz, len, p_dirent->sz, path, depth - 1, - dirent_data); + /* TOFO: If the parent directory is newly formed (ie. size is 0), then + * allocate space for it. This can be done better. Just allocate page when + * its created and added first to LRU, and then add a check to ensure it + * doesn't get re-allocated when written. A field like "new" would be + * helpful in the LRU node for this. + */ - mfs_free_dirent(p_dirent); - mfs_pitr_free(&p_pitr); + memset(wd, 0, len); - finfo("Appended direntry for \"%s\" at depth %u.", dirent->name, depth); + mfs_ser_dirent(dirent, wd); + ret = mfs_lru_wr(sb, pitr->p.sz, len, path, pitr->depth, wd); + if (predict_false(ret < 0)) + { + goto errout; + } +errout: return ret; } -int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth, - FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_dirent_s * const dirent) +int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, const mfs_t depth, + FAR struct mfs_pitr_s * const pitr, + FAR const char * const relpath, const mode_t mode) { - FAR struct mfs_dirent_s *p_dirent = NULL; - struct mfs_pitr_s p_pitr; - int ret = OK; + /* Depth is depth of the child to be appended. */ - mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); - mfs_pitr_adv_tochild(&p_pitr, path, depth - 1); - mfs_pitr_readdirent(sb, &p_pitr, &p_dirent); + int ret = OK; + struct timespec ts; + FAR const char *cur = last_child(relpath); + FAR const char *next = next_child(cur); + FAR struct mfs_dirent_s *d = NULL; + const mfs_t len = *next == 0 ? next - cur : next - cur - 1; - ret = mfs_lru_del(sb, pitr->c_off, MFS_DIRENTSZ(dirent), p_dirent->sz, - path, depth); + DEBUGASSERT(depth > 0); - mfs_free_dirent(p_dirent); - mfs_pitr_free(&p_pitr); + d = kmm_zalloc(sizeof(struct mfs_dirent_s) + len); + if (predict_false(d == NULL)) + { + ret = -ENOMEM; + goto errout; + } - return ret; -} + clock_gettime(CLOCK_REALTIME, &ts); -int mfs_pitr_rm(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth) -{ - int ret = OK; - struct mfs_pitr_s pitr; - FAR struct mfs_dirent_s *dirent = NULL; + d->ctz = empty_fsobj.ctz; + d->mode = mode; + d->st_atim = ts; + d->st_mtim = ts; + d->st_ctim = ts; + d->namelen = len; + strncpy(d->name, cur, d->namelen); + d->name_hash = mfs_hash(d->name, d->namelen); + d->sz = 0; - mfs_pitr_init(sb, path, depth, &pitr, true); - mfs_pitr_readdirent(sb, &pitr, &dirent); - ret = mfs_pitr_rmdirent(sb, path, depth, &pitr, dirent); - mfs_free_dirent(dirent); - mfs_pitr_free(&pitr); + /* Add the new direntry in this path. */ + + path[depth - 1].ctz = d->ctz; + path[depth - 1].off = pitr->p.sz; + path[depth - 1].sz = d->sz; + + ret = mfs_pitr_appenddirent(sb, path, depth, pitr, d); + if (predict_false(ret < 0)) + { + goto errout_with_d; + } + + finfo("Direntry appended to Pitr with %u depth, and CTZ (%u, %u). " \ + "Direntry name: \"%.*s\" with name length %u at offset %u.", + pitr->depth, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, d->namelen, + d->name, d->namelen, path[depth - 1].off); +errout_with_d: + mfs_free_dirent(d); + +errout: return ret; } diff --git a/fs/mnemofs/mnemofs_journal.c b/fs/mnemofs/mnemofs_journal.c index 2fdc6d2d1bc2b..907bb6f1ea233 100644 --- a/fs/mnemofs/mnemofs_journal.c +++ b/fs/mnemofs/mnemofs_journal.c @@ -87,6 +87,11 @@ * Pre-processor Definitions ****************************************************************************/ +#define MFS_JRNL_SUFFIXSZ (8 + 2) /* 8 byte magic sequence + no. of blks */ +#define MFS_LOGSZ(depth) (sizeof(mfs_t) * 2 + sizeof(struct mfs_ctz_s) + \ + sizeof(struct mfs_path_s) * depth + \ + sizeof(struct timespec) * 3 + sizeof(uint16_t)) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -97,26 +102,35 @@ * search methods of higher functions. */ -/* There is a byte-long hash that follows this on-flash. */ +/* New journal log structure being phased in. */ struct jrnl_log_s { - mfs_t depth; - struct mfs_ctz_s new; - FAR struct mfs_ctz_s path[]; + /* A field denoting the size of the below elements is added here on-flash. + */ + + mfs_t depth; + mfs_t sz_new; + struct mfs_ctz_s loc_new; + struct timespec st_mtim_new; + struct timespec st_atim_new; + struct timespec st_ctim_new; + FAR struct mfs_path_s *path; + uint16_t hash; }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static int jrnl_wrlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz); -static int jrnl_rdlog(FAR const struct mfs_sb_s * const sb, mfs_t pg, - mfs_t idx, FAR mfs_t *new_pg, FAR mfs_t *new_idx, - FAR struct jrnl_log_s **log); -static void jrnl_log_free(FAR struct jrnl_log_s *log); +static int jrnl_rdlog(FAR const struct mfs_sb_s *const sb, + FAR mfs_t *blkidx, FAR mfs_t *pg_in_blk, + FAR struct jrnl_log_s *log); + +FAR static const char *deser_log(FAR const char * const in, + FAR struct jrnl_log_s * const x); +FAR static char *ser_log(FAR const struct jrnl_log_s * const x, + FAR char * const out); /**************************************************************************** * Private Data @@ -131,102 +145,143 @@ static void jrnl_log_free(FAR struct jrnl_log_s *log); ****************************************************************************/ /**************************************************************************** - * Name: jrnl_wrlog + * Name: jrnl_rdlog * * Description: - * Appends a log to the journal. + * Read a log to the journal from given location, and update location to + * point to next log location. * * Input Parameters: - * sb - Superblock instance of the device. - * path - CTZ representation of the relpath. - * depth - Length of path. - * new_ctz - The updated location. + * sb - Superblock instance of the device. + * blkidx - Journal Block Index of the current block. + * pg_in_blk - Page offset in the block. + * log - To populate with the log. * * Returned Value: * 0 - OK * < 0 - Error * * Assumptions/Limitations: - * Assumes the CTZ list to be updated is `path[depth - 1].ctz`. + * This function does NOT care about start of the journal, or even, if + * the initial requested area is inside the journal. It will malfunction + * if not used properly. Usually this is used in an iterative manner, and + * hence the first time blkidx and pg_in_blk are initialized, they should + * be derived from the values in MFS_JRNL(sb) respectively. + * + * This updates the blkidx and pg_in_blk to point to the next log, and + * returns an -ENOSPC when end of journal is reached in traversal. + * + * Free the log after use. * ****************************************************************************/ -static int jrnl_wrlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz) +static int jrnl_rdlog(FAR const struct mfs_sb_s *const sb, + FAR mfs_t *blkidx, FAR mfs_t *pg_in_blk, + FAR struct jrnl_log_s *log) { - int ret = OK; - mfs_t i; - mfs_t pg; - mfs_t idx; - mfs_t sz; - mfs_t blk; - mfs_t n_pgs; - mfs_t rem_sz; - FAR char *tmp; - FAR char *buf = NULL; + int ret = OK; + char tmp[4]; + mfs_t i; + mfs_t len; + mfs_t n_pgs; + mfs_t rd_sz; + mfs_t log_sz; + mfs_t jrnl_pg; + mfs_t jrnl_blk; + FAR char *buf = NULL; + FAR char *buftmp = NULL; - /* FUTURE TODO: Group logs together. Common hash and a prefix for number - * of logs together. - */ + DEBUGASSERT(*pg_in_blk % MFS_PGSZ(sb) == 0); - /* Serialize. */ + jrnl_blk = mfs_jrnl_blkidx2blk(sb, *blkidx); + jrnl_pg = MFS_BLK2PG(sb, jrnl_blk) + *pg_in_blk; - sz = sizeof(struct jrnl_log_s) + depth * sizeof(struct mfs_ctz_s) + 1; - buf = kmm_zalloc(sz); - if (predict_false(buf == NULL)) + /* First 4 bytes contain the size of the entire log. */ + + ret = mfs_read_page(sb, tmp, 4, jrnl_pg, 0); + if (predict_false(ret < 0)) { - ret = -ENOMEM; goto errout; } - tmp = buf; - tmp = mfs_ser_mfs(depth, tmp); - tmp = mfs_ser_ctz(&new_ctz, tmp); - for (i = 0; i < depth; i++) + mfs_deser_mfs(tmp, &log_sz); + n_pgs = MFS_CEILDIVIDE(log_sz, MFS_PGSZ(sb)); + + buf = kmm_zalloc(log_sz); + if (predict_false(buf == NULL)) { - tmp = mfs_ser_ctz(&path[i].ctz, tmp); + ret = -ENOMEM; + goto errout; } - tmp = mfs_ser_8(mfs_arrhash(buf, sz - 1), tmp); /* Hash */ + buftmp = buf; + rd_sz = 0; + for (i = 0; i < n_pgs && rd_sz < log_sz; i++) + { + /* This if-statement exists to remove calculation behind + * MIN(MFS_PGSZ(sb), log_sz - rd_sz) + */ - /* Write. */ + if (i == 0 && i != n_pgs - 1) + { + ret = mfs_read_page(sb, buftmp, MFS_PGSZ(sb), jrnl_pg, + sizeof(mfs_t)); + len = MFS_PGSZ(sb); + } + else if (i == 0) + { + ret = mfs_read_page(sb, buftmp, log_sz, jrnl_pg, sizeof(mfs_t)); + len = log_sz; + } + else if (i == n_pgs - 1) + { + ret = mfs_read_page(sb, buftmp, log_sz - rd_sz, jrnl_pg, 0); + len = log_sz - rd_sz; + } + else + { + ret = mfs_read_page(sb, buftmp, MFS_PGSZ(sb), jrnl_pg, 0); + len = MFS_PGSZ(sb); + } - pg = MFS_JRNL(sb).log_cpg; - idx = MFS_JRNL(sb).log_cblkidx; - blk = MFS_PG2BLK(sb, pg); - n_pgs = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); /* Ceil */ - tmp = buf; + buftmp += len; + rd_sz += len; - for (i = 0; i < n_pgs; i++) - { - rem_sz = MIN(MFS_PGSZ(sb), buf + sz - tmp); - ret = mfs_write_page(sb, tmp, rem_sz, pg, 0); - if (predict_false(ret < 0)) + if (predict_false(ret == 0)) { + ret = -EINVAL; /* TODO: Need to check when this occurs. */ goto errout_with_buf; } - pg++; + /* Move to next block if needed. */ - if (pg - MFS_BLK2PG(sb, blk) >= MFS_PGINBLK(sb)) + jrnl_pg++; + if (jrnl_pg - MFS_BLK2PG(sb, jrnl_blk) >= MFS_PGINBLK(sb)) { - idx++; - if (idx >= MFS_JRNL(sb).n_blks) + (*blkidx)++; + + if (*blkidx >= MFS_JRNL(sb).n_blks) { - /* TODO: Time for journal flushing and moving. */ + /* Not finished reading log yet, and the journal is over. */ + + ret = -ENOSPC; + goto errout_with_buf; } - blk = mfs_jrnl_blkidx2blk(sb, idx); - pg = MFS_BLK2PG(sb, blk); + jrnl_blk = mfs_jrnl_blkidx2blk(sb, *blkidx); + jrnl_pg = MFS_BLK2PG(sb, jrnl_blk); } + } - tmp += rem_sz; + if (predict_false(deser_log(buf, log) == NULL)) + { + ret = -ENOMEM; + goto errout_with_buf; } - MFS_JRNL(sb).log_cpg = pg; - MFS_JRNL(sb).log_cblkidx = idx; - MFS_JRNL(sb).n_logs += 1; + /* blkidx has been up to date throughout the program. */ + + *pg_in_blk = jrnl_pg - MFS_BLK2PG(sb, jrnl_blk); errout_with_buf: kmm_free(buf); @@ -236,217 +291,128 @@ static int jrnl_wrlog(FAR struct mfs_sb_s * const sb, } /**************************************************************************** - * Name: jrnl_rdlog + * Name: ser_log * * Description: - * Read a log to the journal from given location. + * Serialize a log. * * Input Parameters: - * sb - Superblock instance of the device. - * pg - Page number of the start of the log. - * idx - Index of the start of the log. - * new_pg - Page number of the start of the next log. - * new_idx - Index of the start of the next log. - * log - To populate with the log. + * n - Log to serialize + * out - Output array where to serialize. * * Returned Value: - * 0 - OK - * < 0 - Error + * Pointer to byte after the end of serialized value. * * Assumptions/Limitations: - * This assumes that at any possibly attainable locations in the journal, - * there will atleast be 4 bytes of data left in that page to read. + * This assumes the out buffer has enough space to hold the inline path. * - * Everything stored in the journal blocks is multiple of 4, and any block - * size is a power of 2, so any block size greater than 4 should also be a - * multiple of 4. - * - * Free the log after use. + * This doesn't require the hash to be pre-calculated. * ****************************************************************************/ -static int jrnl_rdlog(FAR const struct mfs_sb_s * const sb, mfs_t pg, - mfs_t idx, FAR mfs_t *new_pg, FAR mfs_t *new_idx, - FAR struct jrnl_log_s **log) +FAR static char *ser_log(FAR const struct jrnl_log_s * const x, + FAR char * const out) { - int ret = OK; - char buftmp[4]; - mfs_t n_pgs; - mfs_t i; - mfs_t sz; - mfs_t blk; - mfs_t depth; - mfs_t rem_sz; - uint8_t hash; - FAR char *buf = NULL; - FAR char *tmp; - FAR const char *tmp2; - - blk = MFS_PG2BLK(sb, pg); - - /* Read depth. */ - - mfs_read_page(sb, buftmp, 5, pg, 0); - mfs_deser_mfs(buftmp, &depth); - - sz = sizeof(struct jrnl_log_s) + (depth * sizeof(struct mfs_ctz_s)) + 1; - buf = kmm_zalloc(sz); - if (predict_false(buf == NULL)) - { - ret = -ENOMEM; - goto errout; - } - - *log = kmm_zalloc(sz - 1); - if (predict_false(*log == NULL)) - { - goto errout_with_buf; - } - - /* Read the log. */ + char *o = out; + mfs_t i = 0; - n_pgs = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); - tmp = buf; + o = mfs_ser_mfs(x->depth, o); + o = mfs_ser_mfs(x->sz_new, o); + o = mfs_ser_ctz(&x->loc_new, o); + o = mfs_ser_timespec(&x->st_mtim_new, o); + o = mfs_ser_timespec(&x->st_atim_new, o); + o = mfs_ser_timespec(&x->st_ctim_new, o); - for (i = 0; i < n_pgs; i++) + for (i = 0; i < x->depth; i++) { - rem_sz = MIN(MFS_PGSZ(sb), buf + sz - tmp); - ret = mfs_read_page(sb, tmp, rem_sz, pg, 0); - if (predict_false(ret < 0)) - { - goto errout_with_log; - } + o = mfs_ser_path(&x->path[i], o); + } - pg++; + o = mfs_ser_16(mfs_hash(out, o - out), o); + return o; +} - if (pg - MFS_BLK2PG(sb, blk) >= MFS_PGINBLK(sb)) - { - idx++; - if (idx >= MFS_JRNL(sb).n_blks) - { - /* TODO: Time for journal flushing and moving. */ - } +/**************************************************************************** + * Name: deser_log + * + * Description: + * Deserialize a log. + * + * Input Parameters: + * in - Input array from where to deserialize. + * n - Log to deserialize + * + * Returned Value: + * NULL - Error. + * Pointer to byte after the end of serialized value. + * + * Assumptions/Limitations: + * This allocates space for the path, and the log should freed after use. + * + ****************************************************************************/ - blk = mfs_jrnl_blkidx2blk(sb, idx); - pg = MFS_BLK2PG(sb, blk); - } +FAR static const char *deser_log(FAR const char * const in, + FAR struct jrnl_log_s * const x) +{ + mfs_t k = 0; + const char *i = in; - tmp += rem_sz; - } + i = mfs_deser_mfs(i, &x->depth); + i = mfs_deser_mfs(i, &x->sz_new); + i = mfs_deser_ctz(i, &x->loc_new); + i = mfs_deser_timespec(i, &x->st_mtim_new); + i = mfs_deser_timespec(i, &x->st_atim_new); + i = mfs_deser_timespec(i, &x->st_ctim_new); - /* Deserialize */ + /* Allocates path. Deallocate using mfs_jrnl_log_free. */ - tmp2 = buf; - tmp2 = mfs_deser_ctz(tmp2, &(*log)->new); - for (i = 0; i < depth; i++) + x->path = kmm_zalloc(sizeof(struct jrnl_log_s) * x->depth); + if (predict_false(x->path == NULL)) { - tmp2 = mfs_deser_ctz(tmp2, &(*log)->path[i]); + return NULL; } - tmp2 = mfs_deser_8(tmp2, &hash); - - if (hash != mfs_arrhash(buf, sz - 1)) + for (k = 0; k < x->depth; k++) { - ret = -EINVAL; - goto errout_with_log; + i = mfs_deser_path(i, &x->path[k]); } - *new_pg = pg; - *new_idx = idx; - - kmm_free(buf); - return ret; - -errout_with_log: - kmm_free(*log); - *log = NULL; - -errout_with_buf: - kmm_free(buf); - -errout: - return ret; + i = mfs_deser_16(i, &x->hash); + return i; } /**************************************************************************** * Name: jrnl_log_free * * Description: - * Free a log. + * Free the log. * * Input Parameters: - * log - Journal log. + * log - Log + * + * Assumptions/Limitations: + * This allocates space for the path, and the log should freed after use. * ****************************************************************************/ -static void jrnl_log_free(FAR struct jrnl_log_s *log) +static void jrnl_log_free(FAR const struct jrnl_log_s * const log) { - kmm_free(log); + free(log->path); } /**************************************************************************** * Public Functions ****************************************************************************/ -int mfs_jrnl_newlog(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, const struct mfs_ctz_s new_ctz) -{ - return jrnl_wrlog(sb, path, depth, new_ctz); -} - -int mfs_jrnl_updatepath(FAR const struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth) -{ - int ret = OK; - mfs_t k; - mfs_t pg; - mfs_t idx; - struct jrnl_log_s *log; - - idx = MFS_JRNL(sb).log_sblkidx; - pg = MFS_JRNL(sb).log_spg; - - for (k = 0; k < MFS_JRNL(sb).n_logs; k++) - { - ret = jrnl_rdlog(sb, pg, idx, &pg, &idx, &log); - if (predict_false(ret < 0)) - { - return ret; - } - - if (log->depth > depth) - { - continue; - } - - if (depth == 0 || - (log->path[log->depth - 1].pg_e == path[log->depth - 1].ctz.pg_e && - log->path[log->depth - 1].idx_e == path[log->depth - 1].ctz.idx_e)) - { - path[log->depth].ctz = log->new; - } - - jrnl_log_free(log); - } - - /* TODO: Create an update offset function in ctz.c to update the offsets - * of path. - */ - - return ret; -} - int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk) { - mfs_t pg; - FAR char *buf = NULL; - char buftmp[2]; - int ret = OK; - mfs_t sz; - mfs_t idx; - FAR struct jrnl_log_s *log = NULL; + char buftmp[2]; + int ret = OK; + mfs_t sz; + mfs_t blkidx; + mfs_t pg_in_blk; + FAR char *buf = NULL; + FAR struct jrnl_log_s *log = NULL; /* Magic sequence is already used to find the block, so not required. */ @@ -459,28 +425,44 @@ int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk) goto errout; } - sz = 8 + 2 + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); - pg = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); + sz = MFS_JRNL_SUFFIXSZ + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); - MFS_JRNL(sb).log_cpg = pg; - MFS_JRNL(sb).log_cblkidx = 0; + MFS_JRNL(sb).log_cpg = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); MFS_JRNL(sb).log_spg = MFS_JRNL(sb).log_cpg; + MFS_JRNL(sb).log_cblkidx = 0; MFS_JRNL(sb).log_sblkidx = MFS_JRNL(sb).log_cblkidx; MFS_JRNL(sb).jrnlarr_pg = 0; - MFS_JRNL(sb).jrnlarr_pgoff = 8 + 2; + MFS_JRNL(sb).jrnlarr_pgoff = MFS_JRNL_SUFFIXSZ; /* Number of logs */ - idx = 0; MFS_JRNL(sb).n_logs = 0; - while (idx < MFS_JRNL(sb).n_logs) + blkidx = MFS_JRNL(sb).log_sblkidx; + pg_in_blk = MFS_JRNL(sb).log_spg % MFS_PGINBLK(sb); + + while (true) { - jrnl_rdlog(sb, pg, idx, &pg, &idx, &log); + /* TODO: Update this to new read log. */ + + ret = jrnl_rdlog(sb, &blkidx, &pg_in_blk, log); + if (predict_false(ret < 0 && ret != -ENOSPC)) + { + goto errout; + } + else if (ret == -ENOSPC) + { + ret = OK; + break; + } - /* Assumes checking the depth is enough to check if it's empty. */ + /* Assumes checking the depth is enough to check if it's empty, as + * theoretically there are no blocks with depth 0, as root has a + * depth of 1. + */ - if (log->depth == 0) + if (!log || log->depth == 0) { + DEBUGASSERT(!log || log->path == NULL); break; } @@ -501,13 +483,6 @@ int mfs_jrnl_init(FAR struct mfs_sb_s * const sb, mfs_t blk) return ret; } -void mfs_jrnl_free(FAR struct mfs_sb_s * const sb) -{ - /* TODO: Flush entire journal here. */ - - finfo("Journal Freed."); -} - int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) { int i; @@ -524,7 +499,7 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) /* Write magic sequence, size of jrnlarr, and then the jrnlarr. */ - sz = 8 + 2 + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); + sz = MFS_JRNL_SUFFIXSZ + ((CONFIG_MNEMOFS_JOURNAL_NBLKS + 2) * 4); n_pgs = (sz + (MFS_PGSZ(sb) - 1)) / MFS_PGSZ(sb); buf = kmm_zalloc(sz); @@ -606,7 +581,7 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) MFS_JRNL(sb).log_spg = MFS_JRNL(sb).log_cpg; MFS_JRNL(sb).log_sblkidx = MFS_JRNL(sb).log_cblkidx; MFS_JRNL(sb).jrnlarr_pg = MFS_BLK2PG(sb, blk); - MFS_JRNL(sb).jrnlarr_pgoff = 8 + 2; + MFS_JRNL(sb).jrnlarr_pgoff = MFS_JRNL_SUFFIXSZ; MFS_JRNL(sb).n_blks = CONFIG_MNEMOFS_JOURNAL_NBLKS; MFS_JRNL(sb).mblk1 = blk1; MFS_JRNL(sb).mblk2 = blk2; @@ -629,14 +604,20 @@ int mfs_jrnl_fmt(FAR struct mfs_sb_s * const sb, mfs_t blk1, mfs_t blk2) return ret; } +void mfs_jrnl_free(FAR struct mfs_sb_s * const sb) +{ + mfs_jrnl_flush(sb); + finfo("Journal Freed."); +} + mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, const mfs_t blk_idx) { - int ret = OK; + int ret = OK; mfs_t pg; - mfs_t pgoff; - mfs_t blk; mfs_t idx; + mfs_t blk; + mfs_t pgoff; char buf[4]; pg = MFS_JRNL(sb).jrnlarr_pg; @@ -669,3 +650,177 @@ mfs_t mfs_jrnl_blkidx2blk(FAR const struct mfs_sb_s * const sb, return idx; } + +int mfs_jrnl_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth) +{ + int ret = OK; + mfs_t blkidx; + mfs_t counter = 0; + mfs_t pg_in_block; + struct jrnl_log_s tmplog; + + /* TODO: Allow optional filling of updated timestamps, etc. */ + + DEBUGASSERT(depth > 0); + + blkidx = MFS_JRNL(sb).log_sblkidx; + pg_in_block = MFS_JRNL(sb).log_spg % MFS_PGINBLK(sb); + + while (blkidx < MFS_JRNL(sb).n_blks && counter < MFS_JRNL(sb).n_logs) + { + ret = jrnl_rdlog(sb, &blkidx, &pg_in_block, &tmplog); + if (predict_false(ret < 0 && ret != -ENOSPC)) + { + goto errout; + } + else if (ret == -ENOSPC) + { + break; + } + + DEBUGASSERT(tmplog.depth > 0); + + if (tmplog.depth > depth) + { + /* Not suitable. */ + } + else + { + DEBUGASSERT(tmplog.depth > 0); + + if (mfs_path_eq(&tmplog.path[tmplog.depth - 1], + &path[tmplog.depth - 1])) + { + path[tmplog.depth - 1].ctz = tmplog.loc_new; + path[tmplog.depth - 1].sz = tmplog.sz_new; + } + } + + jrnl_log_free(&tmplog); + counter++; + } + +errout: + return ret; +} + +int mfs_jrnl_wrlog(FAR struct mfs_sb_s * const sb, + const struct mfs_node_s node, + const struct mfs_ctz_s loc_new, const mfs_t sz_new) +{ + int ret = OK; + mfs_t i; + mfs_t n_pgs; + mfs_t wr_sz; + mfs_t jrnl_pg; + mfs_t jrnl_blk; + FAR char *buf = NULL; + FAR char *tmp = NULL; + const mfs_t log_sz = sizeof(mfs_t) + MFS_LOGSZ(node.depth); + struct jrnl_log_s log; + + buf = kmm_zalloc(log_sz); /* For size before log. */ + if (predict_false(buf == NULL)) + { + ret = -ENOMEM; + goto errout; + } + + /* Serialize */ + + log.depth = node.depth; + log.sz_new = node.depth; + log.loc_new = loc_new; + log.st_mtim_new = node.st_mtim; + log.st_atim_new = node.st_atim; + log.st_ctim_new = node.st_ctim; + log.path = node.path; /* Fine as temporarily usage. */ + + tmp = buf; + tmp = mfs_ser_mfs(log_sz - sizeof(mfs_t), tmp); + tmp = ser_log(&log, tmp); + + /* Store */ + + n_pgs = MFS_CEILDIVIDE(log_sz, MFS_PGSZ(sb)); + jrnl_blk = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).log_cblkidx); + jrnl_pg = MFS_JRNL(sb).log_cpg; + tmp = buf; + wr_sz = 0; + for (i = 0; i < n_pgs && wr_sz < log_sz; i++) + { + /* This if-statement exists to remove calculation behind + * MIN(MFS_PGSZ(sb), log_sz - wr_sz) + */ + + if (i == 0 && i == n_pgs - 1) + { + ret = mfs_write_page(sb, tmp, log_sz, jrnl_pg, 0); + wr_sz += log_sz; + tmp += log_sz; + } + else if (i == 0) + { + ret = mfs_write_page(sb, tmp, MFS_PGSZ(sb), jrnl_pg, 0); + wr_sz += MFS_PGSZ(sb); + tmp += MFS_PGSZ(sb); + } + else if (i == n_pgs - 1) + { + ret = mfs_write_page(sb, tmp, log_sz - wr_sz, jrnl_pg, 0); + wr_sz += MFS_PGSZ(sb); + tmp += MFS_PGSZ(sb); + } + else + { + ret = mfs_write_page(sb, tmp, MFS_PGSZ(sb), jrnl_pg, 0); + wr_sz += MFS_PGSZ(sb); + tmp += MFS_PGSZ(sb); + } + + if (predict_false(ret == 0)) + { + ret = -EINVAL; + goto errout_with_buf; + } + + /* Move to next block if needed. */ + + jrnl_pg++; + if (jrnl_pg - MFS_BLK2PG(sb, jrnl_blk) == MFS_PGINBLK(sb)) + { + MFS_JRNL(sb).log_cblkidx++; + + if (MFS_JRNL(sb).log_cblkidx == MFS_JRNL(sb).n_blks) + { + /* Not finished reading log yet, and the journal is over. */ + + ret = -ENOSPC; + goto errout_with_buf; + } + + jrnl_blk = mfs_jrnl_blkidx2blk(sb, MFS_JRNL(sb).log_cblkidx); + jrnl_pg = MFS_BLK2PG(sb, jrnl_blk); + } + } + + /* MFS_JRNL(sb).log_cblkidx is up to date */ + + MFS_JRNL(sb).log_cpg = jrnl_pg; + MFS_JRNL(sb).n_logs++; + +errout_with_buf: + kmm_free(buf); + +errout: + return ret; +} + +int mfs_jrnl_flush(FAR struct mfs_sb_s * const sb) +{ + /* TODO */ + + return OK; +} diff --git a/fs/mnemofs/mnemofs_lru.c b/fs/mnemofs/mnemofs_lru.c index a1b032e44dd54..a0965e439c301 100644 --- a/fs/mnemofs/mnemofs_lru.c +++ b/fs/mnemofs/mnemofs_lru.c @@ -93,15 +93,22 @@ enum * Private Function Prototypes ****************************************************************************/ -static void lru_nodesearch(FAR struct mfs_sb_s * const sb, +static void lru_nodesearch(FAR const struct mfs_sb_s * const sb, FAR const struct mfs_path_s * const path, const mfs_t depth, FAR struct mfs_node_s **node); static bool lru_islrufull(FAR struct mfs_sb_s * const sb); static bool lru_isnodefull(FAR struct mfs_node_s *node); -static int lru_nodeflush(FAR struct mfs_sb_s * const sb, +static int lru_nodeflush(FAR struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR struct mfs_node_s *node, + bool clean_node); +static int lru_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, + mfs_t bytes, int op, + FAR struct mfs_path_s * const path, + const mfs_t depth, FAR const char *buf); +static int lru_updatesz(FAR struct mfs_sb_s * sb, FAR struct mfs_path_s * const path, - const mfs_t depth, const mfs_t ctz_sz, - FAR struct mfs_node_s *node, bool clean_node); + const mfs_t depth, const mfs_t new_sz); /**************************************************************************** * Private Data @@ -129,58 +136,69 @@ static int lru_nodeflush(FAR struct mfs_sb_s * const sb, * ****************************************************************************/ -static void lru_nodesearch(FAR struct mfs_sb_s * const sb, +static void lru_nodesearch(FAR const struct mfs_sb_s * const sb, FAR const struct mfs_path_s * const path, const mfs_t depth, FAR struct mfs_node_s **node) { - bool found; - mfs_t i; + bool found = false; + mfs_t i; FAR struct mfs_node_s *n; *node = NULL; + list_for_every_entry(&MFS_LRU(sb), n, struct mfs_node_s, list) { - if (n == NULL) - { - break; - } + /* We need this loop to specifically check the parents in case these + * entries are all new, and have not been allocated any pages for + * being stored in the flash. Also we know that the root (depth 1) will + * be at least common in their paths. + */ + + DEBUGASSERT(depth > 0); - found = true; if (n->depth != depth) { continue; } - if (depth != 0) + found = true; + for (i = n->depth; i >= 1 && found; i--) { - for (i = depth - 1; i + 1 > 0; i--) /* i + 1 prevents underflow. */ + if (path[i - 1].ctz.idx_e == 0 && path[i - 1].ctz.pg_e == 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz) && + n->path[i - 1].off == path[i - 1].off) { - if (n->path[i].off == path[i].off && - n->path[i].ctz.idx_e == path[i].ctz.idx_e && - n->path[i].ctz.pg_e == path[i].ctz.pg_e) - { - /* OK */ - } - else - { - found = false; - break; - } + /* OK */ + } + else if (path[i - 1].ctz.pg_e != 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz)) + { + /* OK */ + } + else + { + found = false; } } if (found) { - finfo("Node search ended with match of node %p at depth %u" - " for CTZ of %u original size with range [%u, %u).", n, - n->depth, n->sz, n->range_min, n->range_max); *node = n; - return; + break; } } - *node = NULL; - finfo("Node search ended without match."); + if (found) + { + finfo("Node search ended with match of node %p at depth %u" + " for CTZ of %u size with range [%u, %u).", n, n->depth, n->sz, + n->range_min, n->range_max); + } + else + { + finfo("Node search ended without match."); + *node = NULL; + } } /**************************************************************************** @@ -190,7 +208,7 @@ static void lru_nodesearch(FAR struct mfs_sb_s * const sb, * Check whether the number of nodes in the LRU has reaches its limit. * * Input Parameters: - * sb - Superblock instance of the device. + * sb - Superblock instance of the device. * * Returned Value: * true - LRU is full @@ -223,6 +241,17 @@ static bool lru_isnodefull(FAR struct mfs_node_s *node) return node->n_list == CONFIG_MNEMOFS_NLRUDELTA; } +/**************************************************************************** + * Name: lru_free_delta + * + * Description: + * Free a node's delta. + * + * Input Parameters: + * delta - LRU delta. + * + ****************************************************************************/ + static void lru_free_delta(FAR struct mfs_delta_s *delta) { kmm_free(delta->upd); @@ -252,10 +281,10 @@ static void lru_free_delta(FAR struct mfs_delta_s *delta) static int lru_nodeflush(FAR struct mfs_sb_s * const sb, FAR struct mfs_path_s * const path, - const mfs_t depth, const mfs_t ctz_sz, - FAR struct mfs_node_s *node, bool clean_node) + const mfs_t depth, FAR struct mfs_node_s *node, + bool clean_node) { - int ret = OK; + int ret = OK; FAR struct mfs_delta_s *delta = NULL; FAR struct mfs_delta_s *tmp = NULL; @@ -264,8 +293,9 @@ static int lru_nodeflush(FAR struct mfs_sb_s * const sb, return -ENOMEM; } - ret = mfs_ctz_nwrtooff(sb, node, path, depth, ctz_sz, - &path[depth - 1].ctz); + /* TODO: Implement effct of clean_node. */ + + ret = mfs_ctz_wrtnode(sb, node); if (predict_false(ret < 0)) { goto errout; @@ -289,13 +319,36 @@ static int lru_nodeflush(FAR struct mfs_sb_s * const sb, return ret; } -static int lru_wrtooff(FAR struct mfs_sb_s * const sb, - const mfs_t data_off, mfs_t bytes, mfs_t ctz_sz, - int op, FAR struct mfs_path_s * const path, - const mfs_t depth, FAR const char *buf) +/**************************************************************************** + * Name: lru_wrtooff + * + * Description: + * Write to offset in LRU. + * + * Input Parameters: + * sb - Superblock instance of the device. + * data_off - Offset into the data in the CTZ skip list. + * bytes - Number of bytes to write. + * ctz_sz - Size of the CTZ skip list. + * op - Operation (MFS_LRU_UPD or MFS_LRU_DEL). + * path - CTZ representation of the path. + * depth - Depth of path. + * buf - Buffer containing data. + * + * Returned Value: + * 0 - OK + * < 0 - Error + * + ****************************************************************************/ + +static int lru_wrtooff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, + mfs_t bytes, int op, + FAR struct mfs_path_s * const path, const mfs_t depth, + FAR const char *buf) { - int ret = OK; - bool found = true; + int ret = OK; + bool found = true; + mfs_t old_sz; FAR struct mfs_node_s *node = NULL; FAR struct mfs_node_s *last_node = NULL; FAR struct mfs_delta_s *delta = NULL; @@ -304,14 +357,23 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, if (node == NULL) { - node = kmm_zalloc(sizeof(*node) + (depth * sizeof(struct mfs_path_s))); + node = kmm_zalloc(sizeof(*node)); if (predict_false(node == NULL)) { + found = false; ret = -ENOMEM; goto errout; } - node->sz = ctz_sz; + node->path = kmm_zalloc(depth * sizeof(struct mfs_path_s)); + if (predict_false(node->path == NULL)) + { + found = false; + ret = -ENOMEM; + goto errout_with_node; + } + + node->sz = path[depth - 1].sz; node->depth = depth; node->n_list = 0; node->range_max = 0; @@ -320,7 +382,7 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, memcpy(node->path, path, depth * sizeof(struct mfs_path_s)); found = false; - finfo("Node not found, allocated, ready to be inserted into LRU."); + finfo("Node not found. Allocated at %p.", node); } if (!found) @@ -345,7 +407,7 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, { /* Node flush writes to the flash and journal. */ - ret = lru_nodeflush(sb, path, depth, ctz_sz, node, false); + ret = lru_nodeflush(sb, path, depth, node, false); if (predict_false(ret < 0)) { goto errout_with_node; @@ -373,7 +435,8 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, goto errout_with_delta; } - finfo("Delta is of the update type, has %u bytes of updates." , bytes); + finfo("Delta is of the update type, has %u bytes at offset %u.", + bytes, data_off); } delta->n_b = bytes; @@ -385,21 +448,37 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, } node->n_list++; - node->range_min = MIN(node->range_min, data_off); - node->range_max = MAX(node->range_max, data_off + bytes); + node->range_min = MIN(node->range_min, data_off); + node->range_max = MAX(node->range_max, data_off + bytes); + + old_sz = node->sz; + node->sz = MAX(node->range_max, path[depth - 1].sz); + node->path[node->depth - 1].sz = node->sz; + + if (old_sz != node->sz) + { + ret = lru_updatesz(sb, node->path, node->depth, node->sz); + if (predict_false(ret < 0)) + { + goto errout_with_delta; + } + } - finfo("Delta attached to node. Now there are %lu nodes and the node has" - " %lu deltas. Node with range [%u, %u).", list_length(&MFS_LRU(sb)), - list_length(&node->delta), node->range_min, node->range_max); + finfo("Delta attached to node %p. Now there are %lu nodes and the node has" + " %lu deltas. Node with range [%u, %u).", node, + list_length(&MFS_LRU(sb)), list_length(&node->delta), + node->range_min, node->range_max); return ret; errout_with_delta: + list_delete(&delta->list); kmm_free(delta); errout_with_node: if (!found && node != NULL) { + list_delete(&node->list); kmm_free(node); } @@ -407,13 +486,106 @@ static int lru_wrtooff(FAR struct mfs_sb_s * const sb, return ret; } +/**************************************************************************** + * Name: lru_updatesz + * + * Description: + * Updates size of an fs object in its parent. + * + * Input Parameters: + * sb - Superblock instance of the device. + * path - CTZ representation of the path. + * depth - Depth of path. + * new_sz - New size + * + * Returned Value: + * 0 - OK + * < 0 - Error + * + * Assumptions/Limitations: + * Adds an entry for the target's parent to update the child's size, and + * updates the size in path of everyone that has this child. + * + ****************************************************************************/ + +static int lru_updatesz(FAR struct mfs_sb_s * sb, + FAR struct mfs_path_s * const path, + const mfs_t depth, const mfs_t new_sz) +{ + int ret = OK; + struct mfs_node_s *n = NULL; + mfs_t i; + bool found; + char buf[sizeof(mfs_t)]; + + DEBUGASSERT(depth > 0); + + list_for_every_entry(&MFS_LRU(sb), n, struct mfs_node_s, list) + { + if (n->depth < depth) + { + continue; + } + + found = false; + for (i = depth; i >= 1; i--) + { + if (path[i - 1].ctz.idx_e == 0 && path[i - 1].ctz.pg_e == 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz) && + n->path[i - 1].off == path[i - 1].off) + { + found = true; + } + else if (path[i - 1].ctz.pg_e != 0 && + mfs_ctz_eq(&n->path[i - 1].ctz, &path[i - 1].ctz)) + { + found = true; + } + else + { + break; + } + } + + if (found) + { + n->path[depth - 1].sz = new_sz; + } + } + + if (depth == 1) + { + MFS_MN(sb).root_sz = new_sz; + goto errout; + } + + memset(buf, 0, sizeof(mfs_t)); + mfs_ser_mfs(new_sz, buf); + + /* This function will be used by mfs_lru_wr itself, but given that if + * there is no change in size, this won't cause an infinite loop, this + * should be fine. + */ + + ret = mfs_lru_wr(sb, path[depth - 2].off + offsetof(struct mfs_dirent_s, + sz), sizeof(mfs_t), path, depth, buf); + if (predict_false(ret < 0)) + { + goto errout; + } + + path[depth - 1].sz = new_sz; + +errout: + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, const mfs_t depth, - const mfs_t ctz_sz) + FAR struct mfs_path_s * const path, const mfs_t depth) { struct mfs_node_s *node = NULL; @@ -423,168 +595,212 @@ int mfs_lru_ctzflush(FAR struct mfs_sb_s * const sb, return OK; } - return lru_nodeflush(sb, path, depth, ctz_sz, node, true); + return lru_nodeflush(sb, path, depth, node, true); } int mfs_lru_del(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t bytes, mfs_t ctz_sz, - FAR struct mfs_path_s * const path, const mfs_t depth) + mfs_t bytes, FAR struct mfs_path_s * const path, + const mfs_t depth) { - return lru_wrtooff(sb, data_off, bytes, ctz_sz, MFS_LRU_DEL, path, depth, - NULL); + return lru_wrtooff(sb, data_off, bytes, MFS_LRU_DEL, path, depth, NULL); } int mfs_lru_wr(FAR struct mfs_sb_s * const sb, const mfs_t data_off, - mfs_t bytes, mfs_t ctz_sz, FAR struct mfs_path_s * const path, + mfs_t bytes, FAR struct mfs_path_s * const path, const mfs_t depth, FAR const char *buf) { - return lru_wrtooff(sb, data_off, bytes, ctz_sz, MFS_LRU_UPD, path, depth, - buf); + return lru_wrtooff(sb, data_off, bytes, MFS_LRU_UPD, path, depth, buf); +} + +void mfs_lru_init(FAR struct mfs_sb_s * const sb) +{ + list_initialize(&MFS_LRU(sb)); + sb->n_lru = 0; + + finfo("LRU Initialized\n"); } -int mfs_lru_rdfromoff(FAR struct mfs_sb_s * const sb, const mfs_t data_off, +int mfs_lru_rdfromoff(FAR const struct mfs_sb_s * const sb, + const mfs_t data_off, FAR struct mfs_path_s * const path, const mfs_t depth, FAR char *buf, const mfs_t buflen) { - int ret = OK; - mfs_t s; - mfs_t e; - mfs_t end; - mfs_t start; - mfs_t del_b; + /* Requires updated path from the journal. */ + + int ret = OK; + mfs_t upper; + mfs_t lower; + mfs_t rem_sz; + mfs_t upper_og; + mfs_t upper_upd; + mfs_t lower_upd; + FAR char *tmp; + struct mfs_ctz_s ctz; FAR struct mfs_node_s *node = NULL; FAR struct mfs_delta_s *delta = NULL; - finfo("Reading from offset %u, %u bytes", data_off, buflen); - - ret = mfs_ctz_rdfromoff(sb, data_off, path, depth, buf, buflen); - if (predict_false(ret < 0)) - { - goto errout; - } - lru_nodesearch(sb, path, depth, &node); if (node == NULL) { goto errout; } - start = data_off; - end = data_off + buflen; - del_b = 0; + /* Node is NOT supposed to be freed by the caller, it's a reference to + * the actual node in the LRU and freeing it could break the entire LRU. + */ + + tmp = buf; + ctz = node->path[node->depth - 1].ctz; + lower = data_off; + upper_og = lower + buflen; + upper = upper_og; + rem_sz = buflen; - do + while (rem_sz > 0) { + mfs_ctz_rdfromoff(sb, ctz, lower, rem_sz, tmp); + list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) { - if (delta->upd) + if (delta->upd == NULL) { - s = MAX(delta->off, start); - e = MIN(delta->off + delta->n_b, end); + /* Delete */ - if (s >= e) + lower_upd = MAX(lower, delta->off); + upper_upd = MIN(upper, delta->off + delta->n_b); + + if (lower_upd >= upper_upd) { - continue; + /* Outside range */ } + else + { + memmove(tmp + (lower - lower_upd), + tmp + (upper_upd - lower), upper - upper_upd); - memcpy(buf + (s - data_off), delta->upd + (s - delta->off), - e - s); + upper -= (upper_upd - lower_upd); + } } else { - s = MAX(delta->off, start); - e = MIN(delta->off + delta->n_b, end); + /* Update */ - if (s >= end) - { - continue; - } + lower_upd = MAX(lower, delta->off); + upper_upd = MIN(upper, delta->off + delta->n_b); - if (e <= start) + if (lower_upd >= upper_upd) { - del_b += delta->n_b; - s = data_off + delta->n_b; - e = end; - memmove(buf, buf + delta->n_b, - buflen - delta->n_b); - e = data_off + buflen - delta->n_b; + /* Outside range */ } else { - del_b += e - s; - memmove(buf + s, buf + e, buflen - (e - s)); - e = data_off + buflen - (e - s); + memcpy(tmp + (lower_upd - lower), + delta->upd + (lower_upd - delta->off), + upper_upd - lower_upd); } } - - start = s; - end = e; } - start = end; - end = data_off + buflen; + tmp += upper - lower; + rem_sz -= upper - lower; + lower = upper; + upper = upper_og; } - while (start != end); errout: return ret; } -void mfs_lru_init(FAR struct mfs_sb_s * const sb) +int mfs_lru_updatedinfo(FAR const struct mfs_sb_s * const sb, + FAR struct mfs_path_s * const path, + const mfs_t depth) { - list_initialize(&MFS_LRU(sb)); - sb->n_lru = 0; + int ret = OK; + bool found; + mfs_t i; + FAR struct mfs_node_s *node = NULL; - finfo("LRU Initialized\n"); -} + DEBUGASSERT(depth > 0); -void mfs_lru_updatedsz(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, mfs_t *n_sz) -{ - mfs_t o_sz; - FAR struct mfs_node_s *node = NULL; - FAR struct mfs_delta_s *delta = NULL; - - if (depth == 0) + list_for_every_entry(&MFS_LRU(sb), node, struct mfs_node_s, list) { - /* Master node */ + /* TODO: When a directory is newly created, and still in the LRU, its + * CTZ is (0, 0), and this can match others as well if at same depth, + * so, in these cases, match the parents, and so on up. + */ - o_sz = 0; - } + DEBUGASSERT(node->depth > 0); - if (depth == 1) - { - /* Root node. */ + if (node->depth > depth) + { + continue; + } - o_sz = MFS_MN(sb).root_sz; - } - else - { - o_sz = path[depth - 1].sz; - } + /* We need this loop to specifically check the parents in case these + * entries are all new, and have not been allocated any pages for + * being stored in the flash. Also we know that the root (depth 1) will + * be at least common in their paths. + */ - *n_sz = o_sz; + found = true; + for (i = node->depth; i >= 1 && found; i--) + { + if (path[i - 1].ctz.idx_e == 0 && path[i - 1].ctz.pg_e == 0 && + mfs_ctz_eq(&node->path[i - 1].ctz, &path[i - 1].ctz) && + node->path[i - 1].off == path[i - 1].off) + { + /* OK */ + } + else if (path[i - 1].ctz.pg_e != 0 && + mfs_ctz_eq(&node->path[i - 1].ctz, &path[i - 1].ctz)) + { + /* OK */ + } + else + { + found = false; + } + } - lru_nodesearch(sb, path, depth, &node); - if (node == NULL) - { - finfo("No updates for file size, with depth %u.", depth); - return; + if (found) + { + path[node->depth - 1].sz = node->path[node->depth - 1].sz; + } } - list_for_every_entry(&node->delta, delta, struct mfs_delta_s, list) + return ret; +} + +int mfs_lru_updatectz(FAR struct mfs_sb_s * sb, + FAR struct mfs_path_s * const path, const mfs_t depth, + const struct mfs_ctz_s new_ctz) +{ + int ret = OK; + char buf[sizeof(struct mfs_ctz_s)]; + FAR struct mfs_node_s *node = NULL; + + list_for_every_entry(&MFS_LRU(sb), node, struct mfs_node_s, list) { - finfo("depth %u %u %u %p", depth, delta->n_b, delta->off, delta->upd); - if (delta->upd == NULL) + if (node->depth >= depth && + mfs_ctz_eq(&node->path[depth - 1].ctz, &path[depth - 1].ctz) && + node->path[depth - 1].sz == path[depth - 1].sz) { - *n_sz -= MIN((*n_sz) - delta->off, delta->n_b); - } - else - { - *n_sz = MAX(*n_sz, delta->off + delta->n_b); + node->path[depth - 1].ctz = new_ctz; } } - finfo("Updated file size is %u with depth %u.", *n_sz, depth); + memset(buf, 0, sizeof(struct mfs_ctz_s)); + mfs_ser_ctz(&new_ctz, buf); + + ret = mfs_lru_wr(sb, path[depth - 1].off + offsetof(struct mfs_dirent_s, + ctz), sizeof(struct mfs_ctz_s), path, depth, buf); + if (predict_false(ret < 0)) + { + goto errout; + } + + path[depth - 1].ctz = new_ctz; + +errout: + return ret; } diff --git a/fs/mnemofs/mnemofs_master.c b/fs/mnemofs/mnemofs_master.c index 3f94720aa83aa..7f5b0ebacad5e 100644 --- a/fs/mnemofs/mnemofs_master.c +++ b/fs/mnemofs/mnemofs_master.c @@ -186,15 +186,15 @@ static FAR const char *deser_mn(FAR const char * const in, int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk) { - int ret = OK; - mfs_t i = 0; + int ret = OK; + mfs_t i = 0; mfs_t mblk1; mfs_t mblk2; mfs_t jrnl_blk_tmp; - bool found = false; + bool found = false; uint8_t hash; struct mfs_mn_s mn; - const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); + const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); char buftmp[4]; char buf[sz + 1]; @@ -265,14 +265,14 @@ int mfs_mn_init(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk) int mfs_mn_fmt(FAR struct mfs_sb_s * const sb, const mfs_t jrnl_blk) { - int ret = OK; + int ret = OK; mfs_t pg; mfs_t mblk1; mfs_t mblk2; struct mfs_mn_s mn; - const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); - char buf[sz + 1]; struct timespec ts; + const mfs_t sz = sizeof(struct mfs_mn_s) - sizeof(mn.pg); + char buf[sz + 1]; clock_gettime(CLOCK_REALTIME, &ts); diff --git a/fs/mnemofs/mnemofs_rw.c b/fs/mnemofs/mnemofs_rw.c index 4a01e8aec9976..20ef4331ce8d7 100644 --- a/fs/mnemofs/mnemofs_rw.c +++ b/fs/mnemofs/mnemofs_rw.c @@ -85,12 +85,22 @@ int mfs_isbadblk(FAR const struct mfs_sb_s * const sb, mfs_t blk) { + if (predict_false(blk > MFS_NBLKS(sb))) + { + return -EINVAL; + } + return MTD_ISBAD(MFS_MTD(sb), blk); } int mfs_markbadblk(FAR const struct mfs_sb_s * const sb, mfs_t blk) { - return MTD_ISBAD(MFS_MTD(sb), blk); + if (predict_false(blk > MFS_NBLKS(sb))) + { + return -EINVAL; + } + + return MTD_MARKBAD(MFS_MTD(sb), blk); } /* NOTE: These functions do not update the block allocator's state nor do @@ -103,6 +113,11 @@ ssize_t mfs_write_page(FAR const struct mfs_sb_s * const sb, { int ret = OK; + if (predict_false(page > MFS_NPGS(sb) || pgoff >= MFS_PGSZ(sb))) + { + return -EINVAL; + } + mempcpy(MFS_RWBUF(sb) + pgoff, data, datalen); ret = MTD_BWRITE(MFS_MTD(sb), page, 1, MFS_RWBUF(sb)); @@ -123,6 +138,11 @@ ssize_t mfs_read_page(FAR const struct mfs_sb_s * const sb, { int ret = OK; + if (predict_false(page > MFS_NPGS(sb) || pgoff >= MFS_PGSZ(sb))) + { + return -EINVAL; + } + ret = MTD_BREAD(MFS_MTD(sb), page, 1, MFS_RWBUF(sb)); if (ret < 0) { @@ -139,11 +159,21 @@ ssize_t mfs_read_page(FAR const struct mfs_sb_s * const sb, int mfs_erase_blk(FAR const struct mfs_sb_s * const sb, const off_t blk) { + if (predict_false(blk > MFS_NBLKS(sb))) + { + return -EINVAL; + } + return MTD_ERASE(MFS_MTD(sb), blk, 1); } int mfs_erase_nblks(FAR const struct mfs_sb_s * const sb, const off_t blk, const size_t n) { + if (predict_false(blk + n > MFS_NBLKS(sb))) + { + return -EINVAL; + } + return MTD_ERASE(MFS_MTD(sb), blk, n); } diff --git a/fs/mnemofs/mnemofs_util.c b/fs/mnemofs/mnemofs_util.c index 0815bd352e7af..a9b1efe032ad4 100644 --- a/fs/mnemofs/mnemofs_util.c +++ b/fs/mnemofs/mnemofs_util.c @@ -92,6 +92,8 @@ uint8_t mfs_arrhash(FAR const char *arr, ssize_t len) ssize_t r = len - 1; uint16_t hash = 0; + /* TODO: Change the array checksum to be 16 bit long. */ + while (l <= r) { hash += arr[l] * arr[r] * (l + 1) * (r + 1); @@ -105,6 +107,27 @@ uint8_t mfs_arrhash(FAR const char *arr, ssize_t len) return hash % (1 << 8); } +uint16_t mfs_hash(FAR const char *arr, ssize_t len) +{ + ssize_t l = 0; + ssize_t r = len - 1; + uint32_t hash = 0; + + /* TODO: Change the array checksum to be 16 bit long. */ + + while (l <= r) + { + hash += arr[l] * arr[r] * (l + 1) * (r + 1); + l++; + r--; + hash %= (1 << MFS_HASHSZ); + } + + finfo("Hash calculated for size %ld to be %u.", len, hash); + + return hash; +} + FAR char *mfs_ser_8(const uint8_t n, FAR char * const out) { *out = n; @@ -189,6 +212,28 @@ FAR const char *mfs_deser_ctz(FAR const char * const in, return i; } +FAR char *mfs_ser_path(FAR const struct mfs_path_s * const x, + FAR char * const out) +{ + char *o = out; + + o = mfs_ser_ctz(&x->ctz, o); + o = mfs_ser_mfs(x->off, o); + o = mfs_ser_mfs(x->sz, o); + return o; +} + +FAR const char *mfs_deser_path(FAR const char * const in, + FAR struct mfs_path_s * const x) +{ + const char *i = in; + + i = mfs_deser_ctz(i, &x->ctz); + i = mfs_deser_mfs(i, &x->off); + i = mfs_deser_mfs(i, &x->sz); + return i; +} + FAR char *mfs_ser_timespec(FAR const struct timespec * const x, FAR char * const out) { @@ -225,3 +270,16 @@ mfs_t mfs_set_msb(mfs_t n) { return 31 - mfs_clz(n); } + +bool mfs_ctz_eq(FAR const struct mfs_ctz_s * const a, + FAR const struct mfs_ctz_s * const b) +{ + return a->idx_e == b->idx_e && a->pg_e == b->pg_e; +} + +bool mfs_path_eq(FAR const struct mfs_path_s * const a, + FAR const struct mfs_path_s * const b) +{ + return mfs_ctz_eq(&a->ctz, &b->ctz) && (a->off == b->off) + && (a->sz == b->sz); +} diff --git a/include/nuttx/mtd/nand_ram.h b/include/nuttx/mtd/nand_ram.h index 5229882e42b83..c3483ed06ac5c 100644 --- a/include/nuttx/mtd/nand_ram.h +++ b/include/nuttx/mtd/nand_ram.h @@ -43,14 +43,14 @@ #define NAND_RAM_SIZE NAND_RAM_MB(CONFIG_MTD_NAND_RAM_SIZE) -#define NAND_RAM_LOG_PAGES_PER_BLOCK ((uint32_t) 7) -#define NAND_RAM_PAGE_SIZE ((uint32_t) (1 << 9)) /* 512 B */ -#define NAND_RAM_SPARE_SIZE ((uint32_t) (1 << 4)) /* 16 B */ +#define NAND_RAM_LOG_PAGES_PER_BLOCK ((uint32_t) 4) +#define NAND_RAM_PAGE_SIZE ((uint32_t) (1 << 7)) +#define NAND_RAM_SPARE_SIZE ((uint32_t) (1 << 3)) +#define NAND_RAM_BLOCK_SIZE ((uint32_t) ((1 << NAND_RAM_LOG_PAGES_PER_BLOCK) * NAND_RAM_PAGE_SIZE)) #define NAND_RAM_N_PAGES ((uint32_t) NAND_RAM_SIZE / NAND_RAM_PAGE_SIZE) #define NAND_RAM_TOTAL_PAGE_SIZE ((uint32_t) (NAND_RAM_PAGE_SIZE + NAND_RAM_SPARE_SIZE)) -#define NAND_RAM_PAGES_PER_BLOCK ((uint32_t) (NAND_RAM_BLOCK_SIZE / NAND_RAM_PAGE_SIZE)) -#define NAND_RAM_N_BLOCKS ((uint32_t) (NAND_RAM_N_PAGES / NAND_RAM_PAGES_PER_BLOCK)) -#define NAND_RAM_BLOCK_SIZE ((uint32_t) ((1 << NAND_RAM_LOG_PAGES_PER_BLOCK) * NAND_RAM_PAGE_SIZE)) +#define NAND_RAM_PAGES_PER_BLOCK ((uint32_t) (1 << (NAND_RAM_LOG_PAGES_PER_BLOCK))) +#define NAND_RAM_N_BLOCKS ((uint32_t) (NAND_RAM_SIZE / (NAND_RAM_PAGES_PER_BLOCK * NAND_RAM_PAGE_SIZE))) #define NAND_RAM_PAGE_WRITTEN 0 #define NAND_RAM_PAGE_FREE 1 From 6c97a8f4681fc79182bb624f062318ffb5096b54 Mon Sep 17 00:00:00 2001 From: chao an Date: Fri, 9 Aug 2024 15:20:48 +0800 Subject: [PATCH 29/81] sim/login: remove login restrictions to improve the experience for green hands Most developers start learning Nuttx from sim/nsh, but the login experience is very bad, they don't know where to get the username and password, this commit will remove the limitation of sim/nsh login, and add sim/login configuration to ensure the feature of NSH_CONSOLE_LOGIN is verified. Signed-off-by: chao an --- .../platforms/sim/sim/boards/sim/index.rst | 26 ++++--- boards/sim/sim/sim/configs/login/defconfig | 67 +++++++++++++++++++ boards/sim/sim/sim/configs/nsh/defconfig | 5 -- 3 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 boards/sim/sim/sim/configs/login/defconfig diff --git a/Documentation/platforms/sim/sim/boards/sim/index.rst b/Documentation/platforms/sim/sim/boards/sim/index.rst index 472bfdabfd186..2026534ffcc91 100644 --- a/Documentation/platforms/sim/sim/boards/sim/index.rst +++ b/Documentation/platforms/sim/sim/boards/sim/index.rst @@ -849,16 +849,7 @@ NOTES: apps/examples/hello. - 2. This version has password protection enabled. Here is the login info:: - - USERNAME: admin - PASSWORD: Administrator - - The encrypted password is retained in /etc/passwd. I am sure that - you will find this annoying. You can disable the password protection - by de-selecting CONFIG_NSH_CONSOLE_LOGIN=y. - - 3. This configuration has BINFS enabled so that the builtin applications can + 2. This configuration has BINFS enabled so that the builtin applications can be made visible in the file system. Because of that, the builtin applications do not work as other examples. @@ -1807,6 +1798,21 @@ This is a configuration with sim usbhost support. Run sim usbhost with root mode, run sim usbdev or plug-in cdcacm usb device. Then you can use /dev/ttyACM to transfer data. +login +----- + +This is a configuration with login password protection for nuttx shell. + +NOTES: + + This config has password protection enabled. Here is the login info:: + + USERNAME: admin + PASSWORD: Administrator + + The encrypted password is retained in /etc/passwd. I am sure that + you will find this annoying. You can disable the password protection + by de-selecting CONFIG_NSH_CONSOLE_LOGIN=y. README.txt ========== diff --git a/boards/sim/sim/sim/configs/login/defconfig b/boards/sim/sim/sim/configs/login/defconfig new file mode 100644 index 0000000000000..fbb4f2874e791 --- /dev/null +++ b/boards/sim/sim/sim/configs/login/defconfig @@ -0,0 +1,67 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="sim" +CONFIG_ARCH_BOARD="sim" +CONFIG_ARCH_BOARD_SIM=y +CONFIG_ARCH_CHIP="sim" +CONFIG_ARCH_SIM=y +CONFIG_BOARDCTL_APP_SYMTAB=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LOOPSPERMSEC=0 +CONFIG_BOOT_RUNFROMEXTSRAM=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_GPIO=y +CONFIG_DEV_LOOP=y +CONFIG_DEV_ZERO=y +CONFIG_ETC_FATDEVNO=2 +CONFIG_ETC_ROMFS=y +CONFIG_ETC_ROMFSDEVNO=1 +CONFIG_EXAMPLES_GPIO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FSUTILS_PASSWD=y +CONFIG_FSUTILS_PASSWD_READONLY=y +CONFIG_FS_BINFS=y +CONFIG_FS_FAT=y +CONFIG_FS_PROCFS=y +CONFIG_FS_RAMMAP=y +CONFIG_FS_ROMFS=y +CONFIG_GPIO_LOWER_HALF=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_IOEXPANDER=y +CONFIG_IOEXPANDER_DUMMY=y +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_LOCALE=y +CONFIG_LIBC_LOCALE_CATALOG=y +CONFIG_LIBC_LOCALE_GETTEXT=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_LIBC_NUMBERED_ARGS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_CONSOLE_LOGIN=y +CONFIG_NSH_FILE_APPS=y +CONFIG_NSH_MOTD=y +CONFIG_NSH_MOTD_STRING="MOTD: username=admin password=Administrator" +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/bin" +CONFIG_PSEUDOFS_ATTRIBUTES=y +CONFIG_PSEUDOFS_SOFTLINKS=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_WAITPID=y +CONFIG_SIM_WALLTIME_SIGNAL=y +CONFIG_START_MONTH=6 +CONFIG_START_YEAR=2008 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y diff --git a/boards/sim/sim/sim/configs/nsh/defconfig b/boards/sim/sim/sim/configs/nsh/defconfig index fbb4f2874e791..094b594c88194 100644 --- a/boards/sim/sim/sim/configs/nsh/defconfig +++ b/boards/sim/sim/sim/configs/nsh/defconfig @@ -27,8 +27,6 @@ CONFIG_EXAMPLES_GPIO=y CONFIG_EXAMPLES_HELLO=y CONFIG_FAT_LCNAMES=y CONFIG_FAT_LFN=y -CONFIG_FSUTILS_PASSWD=y -CONFIG_FSUTILS_PASSWD_READONLY=y CONFIG_FS_BINFS=y CONFIG_FS_FAT=y CONFIG_FS_PROCFS=y @@ -48,10 +46,7 @@ CONFIG_LIBC_MAX_EXITFUNS=1 CONFIG_LIBC_NUMBERED_ARGS=y CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y -CONFIG_NSH_CONSOLE_LOGIN=y CONFIG_NSH_FILE_APPS=y -CONFIG_NSH_MOTD=y -CONFIG_NSH_MOTD_STRING="MOTD: username=admin password=Administrator" CONFIG_NSH_READLINE=y CONFIG_PATH_INITIAL="/bin" CONFIG_PSEUDOFS_ATTRIBUTES=y From 34a30e577e9aa27b3a8b0a67c7784121add201a5 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Wed, 10 Jul 2024 18:25:12 +0800 Subject: [PATCH 30/81] riscv/qemu: add CMake for NuttSBI This allows building NuttSBI based kernel image with CMake so that to support out-of-tree building. Signed-off-by: Yanfeng Liu --- boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt index e5f78691fd703..58e2e5568775c 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt +++ b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt @@ -31,9 +31,11 @@ endif() target_sources(board PRIVATE ${SRCS}) if(CONFIG_ARCH_CHIP_QEMU_RV) - if(CONFIG_BUILD_KERNEL) set(LDFILE ld-kernel.script) + if(CONFIG_NUTTSBI) + set(LDFILE ld-nuttsbi.script) + endif() else() set(LDFILE ld.script) endif() From 46f4a24d59d1ad443d242104dfa375369b8d65e5 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Sun, 14 Jul 2024 08:48:37 +0800 Subject: [PATCH 31/81] riscv/qemu: add CMake for PROTECTED This adds CMake support for PROTECTED build mode on rv-virt target. Signed-off-by: Yanfeng Liu --- arch/risc-v/src/qemu-rv/CMakeLists.txt | 4 ++++ boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt | 7 +++++++ .../qemu-rv/rv-virt/kernel/CMakeLists.txt | 21 +++++++++++++++++++ .../risc-v/qemu-rv/rv-virt/src/CMakeLists.txt | 9 ++++---- 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt diff --git a/arch/risc-v/src/qemu-rv/CMakeLists.txt b/arch/risc-v/src/qemu-rv/CMakeLists.txt index 397069bae8c31..a666c4ad0dbfd 100644 --- a/arch/risc-v/src/qemu-rv/CMakeLists.txt +++ b/arch/risc-v/src/qemu-rv/CMakeLists.txt @@ -39,4 +39,8 @@ if(CONFIG_MM_PGALLOC) list(APPEND SRCS qemu_rv_pgalloc.c) endif() +if(CONFIG_BUILD_PROTECTED) + list(APPEND SRCS qemu_rv_userspace.c) +endif() + target_sources(arch PRIVATE ${SRCS}) diff --git a/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt index 6f5e40d723db9..a7c54dabdbbfd 100644 --- a/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt +++ b/boards/risc-v/qemu-rv/rv-virt/CMakeLists.txt @@ -19,3 +19,10 @@ # ############################################################################## add_subdirectory(src) + +if(CONFIG_BUILD_PROTECTED) + add_subdirectory(kernel) + set_property( + GLOBAL PROPERTY LD_SCRIPT_USER + ${CMAKE_CURRENT_LIST_DIR}/scripts/ld-userland.script) +endif() diff --git a/boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt new file mode 100644 index 0000000000000..82638d9cc026f --- /dev/null +++ b/boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt @@ -0,0 +1,21 @@ +# ############################################################################## +# boards/risc-v/qemu-rv/rv-virt/kernel/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you 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. +# +# ############################################################################## + +target_sources(nuttx_user PRIVATE rv_virt_userspace.c) diff --git a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt index 58e2e5568775c..46e760f6ccefd 100644 --- a/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt +++ b/boards/risc-v/qemu-rv/rv-virt/src/CMakeLists.txt @@ -31,11 +31,12 @@ endif() target_sources(board PRIVATE ${SRCS}) if(CONFIG_ARCH_CHIP_QEMU_RV) - if(CONFIG_BUILD_KERNEL) + if(CONFIG_NUTTSBI) + set(LDFILE ld-nuttsbi.script) + elseif(CONFIG_BUILD_KERNEL) set(LDFILE ld-kernel.script) - if(CONFIG_NUTTSBI) - set(LDFILE ld-nuttsbi.script) - endif() + elseif(CONFIG_BUILD_PROTECTED) + set(LDFILE ld-protected.script) else() set(LDFILE ld.script) endif() From 2afdcfb6a67d3fec4c2acfba6961b7cfc187de7c Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Fri, 9 Aug 2024 09:08:18 +0800 Subject: [PATCH 32/81] boards/lm3s6965-ek: adjust memory.ld to unblock CI This adjusts memory.ld to unblock CI issue: `nuttx_user.elf section '.text' will not fit in region 'uflash'` Signed-off-by: Yanfeng Liu --- boards/arm/tiva/lm3s6965-ek/scripts/memory.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld b/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld index acc84a83d6f65..771fabbef8bbf 100644 --- a/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld +++ b/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld @@ -26,8 +26,8 @@ MEMORY { /* 256Kb FLASH */ - kflash (rx) : ORIGIN = 0x00000000, LENGTH = 128K - uflash (rx) : ORIGIN = 0x00020000, LENGTH = 128K + kflash (rx) : ORIGIN = 0x00000000, LENGTH = 124K + uflash (rx) : ORIGIN = 0x00020000, LENGTH = 132K xflash (rx) : ORIGIN = 0x00040000, LENGTH = 0K /* 64Kb of contiguous SRAM */ From 83932d115b156f60930345fc643f58e0589c7d68 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Fri, 9 Aug 2024 09:53:47 +0800 Subject: [PATCH 33/81] boards/rv-virt: unify rv32 config names This renames a few RV32 configs to follow the convention that names w/o numbers are for RV32, so that to be in line with majority RV32 configs. As a result, we have: `nsh` vs `nsh64`, `knsh` vs `knsh64`, `pnsh` vs `pnsh64`,`flats` vs `flats64`, `nsbi` vs `nsbi64`, `libcxx` vs `libcxx64` etc. This helps us pick the right config name w/o checking file contents. Signed-off-by: Yanfeng Liu --- Documentation/components/paging.rst | 2 +- .../risc-v/qemu-rv/boards/rv-virt/index.rst | 18 +++++++++--------- .../rv-virt/configs/{knsh32 => knsh}/defconfig | 0 .../{knsh32_paging => knsh_paging}/defconfig | 0 .../{knsh32_romfs => knsh_romfs}/defconfig | 0 .../configs/{libcxx32 => libcxx}/defconfig | 0 6 files changed, 10 insertions(+), 10 deletions(-) rename boards/risc-v/qemu-rv/rv-virt/configs/{knsh32 => knsh}/defconfig (100%) rename boards/risc-v/qemu-rv/rv-virt/configs/{knsh32_paging => knsh_paging}/defconfig (100%) rename boards/risc-v/qemu-rv/rv-virt/configs/{knsh32_romfs => knsh_romfs}/defconfig (100%) rename boards/risc-v/qemu-rv/rv-virt/configs/{libcxx32 => libcxx}/defconfig (100%) diff --git a/Documentation/components/paging.rst b/Documentation/components/paging.rst index 7adf8b2235cad..787fa57f161d1 100644 --- a/Documentation/components/paging.rst +++ b/Documentation/components/paging.rst @@ -65,7 +65,7 @@ allocates a physical page and maps it to the virtual memory space that triggered the page fault exception and then resumes execution from the same point where the page fault first occurred. -:ref:`knsh32_paging` simulates a device with 4MiB physical memory with 8MiB +:ref:`knsh_paging` simulates a device with 4MiB physical memory with 8MiB of virtual heap memory allocated for each process. This is possible by enabling on-demand paging. diff --git a/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst index 16a186960043b..34f137e6fd2e6 100644 --- a/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst +++ b/Documentation/platforms/risc-v/qemu-rv/boards/rv-virt/index.rst @@ -59,7 +59,7 @@ All of the configurations presented below can be tested by running the following $ ./tools/configure.sh rv-virt: -Where is the name of the configuration you want to use, i.e.: nsh, knsh32, knsh64... +Where is the name of the configuration you want to use, i.e.: nsh, knsh, knsh64... To build it, run the following command:: @@ -146,7 +146,7 @@ To run it with QEMU, use the following command:: knetnsh64 --------- -Similar to the `knsh32`_ configuration, but with networking support and 64-bit RISC-V. +Similar to the `knsh`_ configuration, but with networking support and 64-bit RISC-V. To run it with QEMU, use the following command:: @@ -169,7 +169,7 @@ knetnsh64_smp Similar to the `knetnsh64`_ configuration, but with SMP support for 64-bit RISC-V. -knsh32 +knsh ------ This is similar to the `nsh`_ configuration except that NuttX @@ -192,12 +192,12 @@ In `nsh`, applications can be run from the `/system/bin` directory:: nsh> /system/bin/hello -.. _knsh32_paging: +.. _knsh_paging: -knsh32_paging +knsh_paging ------------- -Similar to ``knsh32_romfs``, but enabling on-demand paging: this +Similar to ``knsh_romfs``, but enabling on-demand paging: this configuration simulates a 4MiB device (using QEMU), but sets the number of heap pages equal to ``CONFIG_ARCH_HEAP_NPAGES=2048``. This means that each process's heap is 8MiB, whereas ``CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE`` is @@ -208,10 +208,10 @@ to have their own address space larger than the available physical memory. This is particularly useful for implementing a set of programming language interpreters. -knsh32_romfs +knsh_romfs ------------ -Similar to the `knsh32`_ configuration, but uses ROMFS instead of `hostfs`. +Similar to the `knsh`_ configuration, but uses ROMFS instead of `hostfs`. A ROMFS image is generated and linked to the kernel. This requires re-running ``make``:: $ make V=1 -j$(nproc) @@ -234,7 +234,7 @@ In `nsh`, applications can be run from the `/system/bin` directory:: knsh64 ------ -Similar to the `knsh32`_ configuration, but for 64-bit RISC-V. +Similar to the `knsh`_ configuration, but for 64-bit RISC-V. Run it with QEMU using the default command for 64-bit RISC-V. diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh32/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/knsh32/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/knsh/defconfig diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh32_paging/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/knsh32_paging/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh32_romfs/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/knsh_romfs/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/knsh32_romfs/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/knsh_romfs/defconfig diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/libcxx32/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/libcxx/defconfig similarity index 100% rename from boards/risc-v/qemu-rv/rv-virt/configs/libcxx32/defconfig rename to boards/risc-v/qemu-rv/rv-virt/configs/libcxx/defconfig From cde0de00fe40484ed75cb80e3050b511a8b5c41a Mon Sep 17 00:00:00 2001 From: "chenwen@espressif.com" Date: Wed, 24 Jul 2024 18:31:30 +0800 Subject: [PATCH 34/81] xtensa/esp32s3: Update the rtc code to fix system blocking issue 1. For some reasons, the bootloader will set CPU source to BBPLL and enable it, but there are calibration issues, so we need turn off the BBPLL and do calibration again to fix the issue. 2. Corresponding issue link: https://github.com/espressif/esp-idf/commit/89cc9084ab5d889761cb5eff7560a2661236842a Signed-off-by: chenwen@espressif.com --- arch/xtensa/src/esp32s3/esp32s3_rtc.c | 350 ++++++++++-------- arch/xtensa/src/esp32s3/esp32s3_rtc.h | 32 -- .../src/esp32s3/hardware/esp32s3_rtccntl.h | 7 + 3 files changed, 198 insertions(+), 191 deletions(-) diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.c b/arch/xtensa/src/esp32s3/esp32s3_rtc.c index dd68de426344d..c01623612bcb8 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.c +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.c @@ -100,6 +100,10 @@ #define RETRY_CAL_EXT 1 +#define CLK_LL_PLL_80M_FREQ_MHZ (80) +#define CLK_LL_PLL_160M_FREQ_MHZ (160) +#define CLK_LL_PLL_240M_FREQ_MHZ (240) + /* Lower threshold for a reasonably-looking calibration value for a 32k XTAL. * The ideal value (assuming 32768 Hz frequency) * is 1000000/32768*(2**19) = 16*10^6. @@ -138,6 +142,10 @@ #define RTC_CNTL_PD_CUR_MONITOR_DEFAULT (1) #define RTC_CNTL_PD_CUR_MONITOR_ON (0) +/* Set LDO slave during CPU switch */ + +#define DEFAULT_LDO_SLAVE 0x7 + /* Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP, * RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values. * Valid if RTC_CNTL_DBG_ATTEN is 0. @@ -353,6 +361,8 @@ static RTC_DATA_ATTR struct esp32s3_rtc_backup_s rtc_saved_data; static struct esp32s3_rtc_backup_s *g_rtc_save; static bool g_rt_timer_enabled = false; +static uint32_t g_dig_dbias_pvt_240m = 28; +static uint32_t g_rtc_dbias_pvt_240m = 28; static uint32_t g_dig_dbias_pvt_non_240m = 27; static uint32_t g_rtc_dbias_pvt_non_240m = 27; @@ -377,17 +387,15 @@ static void esp32s3_rtc_clk_32k_enable(bool enable); static void IRAM_ATTR esp32s3_rtc_clk_8m_enable(bool clk_8m_en, bool d256_en); static void esp32s3_rtc_calibrate_ocode(void); -static void IRAM_ATTR esp32s3_rtc_clk_bbpll_disable(void); +static void IRAM_ATTR esp32s3_rtc_bbpll_disable(void); +static void IRAM_ATTR esp32s3_rtc_bbpll_enable(void); static void IRAM_ATTR esp32s3_rtc_bbpll_configure( enum esp32s3_rtc_xtal_freq_e xtal_freq, int pll_freq); static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_8m(void); static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_pll_mhz( int cpu_freq_mhz); - -void IRAM_ATTR esp32s3_rtc_bbpll_disable(void); void esp32s3_rtc_clk_apb_freq_update(uint32_t apb_freq); void IRAM_ATTR esp32s3_rtc_update_to_xtal(int freq, int div); -static void esp32s3_wait_dig_dbias_valid(uint64_t rtc_cycles); uint32_t esp32s3_rtc_clk_apb_freq_get(void); #ifdef CONFIG_RTC_ALARM @@ -650,23 +658,6 @@ static uint32_t IRAM_ATTR esp32s3_rtc_clk_cal_internal( return cal_val; } -static void esp32s3_wait_dig_dbias_valid(uint64_t rtc_cycles) -{ - int slow_clk_freq = esp32s3_rtc_clk_slow_freq_get(); - int cal_clk = RTC_CAL_RTC_MUX; - - if (slow_clk_freq == RTC_SLOW_FREQ_32K_XTAL) - { - cal_clk = RTC_CAL_32K_XTAL; - } - else if (slow_clk_freq == RTC_SLOW_FREQ_8MD256) - { - cal_clk = RTC_CAL_8MD256; - } - - esp32s3_rtc_clk_cal(cal_clk, rtc_cycles); -} - /**************************************************************************** * Name: esp32s3_rtc_update_to_xtal * @@ -684,21 +675,13 @@ static void esp32s3_wait_dig_dbias_valid(uint64_t rtc_cycles) void IRAM_ATTR esp32s3_rtc_update_to_xtal(int freq, int div) { - ets_update_cpu_frequency(freq); - - /* Set digital voltage for different cpu freq from xtal */ - - if (freq <= 2) - { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, DIG_DBIAS_2M); - } - else + struct esp32s3_cpu_freq_config_s cur_config = { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, - DIG_DBIAS_XTAL); - } + 0 + }; - esp32s3_wait_dig_dbias_valid(2); + esp32s3_rtc_clk_cpu_freq_get_config(&cur_config); + ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. * Need to set divider to 1 (reg. value 0) first. @@ -715,6 +698,17 @@ void IRAM_ATTR esp32s3_rtc_update_to_xtal(int freq, int div) SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); esp32s3_rtc_clk_apb_freq_update(freq * MHZ); + + if (cur_config.freq_mhz == 240) + { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_non_240m); + esp_rom_delay_us(40); + } + + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE); } /**************************************************************************** @@ -932,26 +926,16 @@ static void esp32s3_select_rtc_slow_clk(enum esp32s3_slow_clk_sel_e slow_clk) static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_8m(void) { - int origin_soc_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, - SYSTEM_SOC_CLK_SEL); - int origin_div_cnt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, - SYSTEM_PRE_DIV_CNT); - ets_update_cpu_frequency(8); - - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, - DIG_DBIAS_XTAL); - esp32s3_wait_dig_dbias_valid(2); - - if ((DPORT_SOC_CLK_SEL_XTAL == origin_soc_clk) - && (origin_div_cnt > 4)) - { - esp32s3_wait_dig_dbias_valid(2); - } - + ets_update_cpu_frequency(20); REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, - DPORT_SOC_CLK_SEL_8M); + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, 2); esp32s3_rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_APPROX); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_non_240m); + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, + DEFAULT_LDO_SLAVE); } /**************************************************************************** @@ -971,46 +955,85 @@ static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_8m(void) static void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_to_pll_mhz( int cpu_freq_mhz) { - int origin_soc_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, - SYSTEM_SOC_CLK_SEL); - int origin_cpuperiod_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG, - SYSTEM_CPUPERIOD_SEL); - int dbias = DIG_DBIAS_80M_160M; - int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) - { - /* Nothing to do */ - } - else if (cpu_freq_mhz == 160) - { - dbias = DIG_DBIAS_80M_160M; - per_conf = DPORT_CPUPERIOD_SEL_160; - } - else if (cpu_freq_mhz == 240) + /* There are totally 6 LDO slaves(all on by default). At the moment of + * swithing LDO slave, LDO voltage will also change instantaneously. + * LDO slave can reduce the voltage change caused by switching frequency. + * CPU frequency <= 40M : just open 3 LDO slaves; CPU frequency = 80M : + * open 4 LDO slaves; CPU frequency = 160M : open 5 LDO slaves; + * CPU frequency = 240M : open 6 LDO slaves; LDO voltage will decrease + * at the moment of switching from low frequency to high frequency; + * otherwise, LDO voltage will increase.In order to reduce LDO voltage + * drop, LDO voltage should rise first then fall. + */ + + int pd_slave = cpu_freq_mhz / 80; + struct esp32s3_cpu_freq_config_s cur_config = { - dbias = DIG_DBIAS_240M; - per_conf = DPORT_CPUPERIOD_SEL_240; - } - else + 0 + }; + + esp32s3_rtc_clk_cpu_freq_get_config(&cur_config); + + /* cpu_frequency < 240M: dbias = pvt-dig + 2; + * cpu_frequency = 240M: dbias = pvt-dig + 3; + */ + + if (cpu_freq_mhz > cur_config.freq_mhz) { - rtcerr("Invalid frequency\n"); + if (cpu_freq_mhz == 240) + { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_240m); + esp_rom_delay_us(40); + } + + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, + DEFAULT_LDO_SLAVE >> pd_slave); } - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, dbias); - if ((origin_soc_clk == DPORT_SOC_CLK_SEL_XTAL) - || (origin_soc_clk == DPORT_SOC_CLK_SEL_8M) - || (((origin_soc_clk == DPORT_SOC_CLK_SEL_PLL) - && (0 == origin_cpuperiod_sel)))) + switch (cpu_freq_mhz) { - esp32s3_wait_dig_dbias_valid(2); + case CLK_LL_PLL_80M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 0); + break; + + case CLK_LL_PLL_160M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 1); + break; + + case CLK_LL_PLL_240M_FREQ_MHZ: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, 2); + break; + + default: + DEBUGASSERT(0); } - REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); + + /* switch clock source */ + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); esp32s3_rtc_clk_apb_freq_update(80 * MHZ); ets_update_cpu_frequency(cpu_freq_mhz); + + if (cpu_freq_mhz < cur_config.freq_mhz) + { + if (cur_config.freq_mhz == 240) + { + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_non_240m); + esp_rom_delay_us(40); + } + + REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, + DEFAULT_LDO_SLAVE >> pd_slave); + } } #ifdef CONFIG_RTC_ALARM @@ -1080,7 +1103,10 @@ static void esp32s3_rtc_calibrate_ocode(void) bool bg_odone_flag = 0; uint64_t cycle1 = 0; uint64_t max_delay_time_us = 10000; - struct esp32s3_cpu_freq_config_s freq_config; + struct esp32s3_cpu_freq_config_s freq_config = + { + 0 + }; /* Bandgap output voltage is not precise when calibrate o-code by hardware * sometimes, so need software o-code calibration (must turn off PLL). @@ -1292,10 +1318,10 @@ enum esp32s3_rtc_xtal_freq_e IRAM_ATTR esp32s3_rtc_clk_xtal_freq_get(void) } /**************************************************************************** - * Name: esp32s3_rtc_clk_bbpll_disable + * Name: esp32_rtc_bbpll_disable * * Description: - * Disable BBPLL. + * Power down BBPLL circuit. * * Input Parameters: * None @@ -1305,12 +1331,32 @@ enum esp32s3_rtc_xtal_freq_e IRAM_ATTR esp32s3_rtc_clk_xtal_freq_get(void) * ****************************************************************************/ -static void IRAM_ATTR esp32s3_rtc_clk_bbpll_disable(void) +static void IRAM_ATTR esp32s3_rtc_bbpll_disable(void) { modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, 0, RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); } +/**************************************************************************** + * Name: esp32s3_rtc_bbpll_enable + * + * Description: + * Power up BBPLL circuit. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32s3_rtc_bbpll_enable(void) +{ + modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); +} + /**************************************************************************** * Name: esp32s3_rtc_bbpll_configure * @@ -1329,26 +1375,36 @@ static void IRAM_ATTR esp32s3_rtc_clk_bbpll_disable(void) static void IRAM_ATTR esp32s3_rtc_bbpll_configure( enum esp32s3_rtc_xtal_freq_e xtal_freq, int pll_freq) { - static uint8_t div_ref = 0; - static uint8_t div7_0 = 0; - static uint8_t dr1 = 0 ; - static uint8_t dr3 = 0 ; - static uint8_t dchgp = 0; - static uint8_t dcur = 0; - static uint8_t dbias = 0; - uint8_t i2c_bbpll_lref = 0; + uint8_t div_ref = 0; + uint8_t div7_0 = 0; + uint8_t dr1 = 0; + uint8_t dr3 = 0; + uint8_t dchgp = 0; + uint8_t dcur = 0; + uint8_t dbias = 3; + uint8_t i2c_bbpll_lref = 0; uint8_t i2c_bbpll_div_7_0 = 0; uint8_t i2c_bbpll_dcur = 0; + switch (pll_freq) + { + case RTC_PLL_FREQ_320M: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 0); + break; + + case RTC_PLL_FREQ_480M: + REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 1); + break; + + default: + DEBUGASSERT(0); + } + modifyreg32(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, 0); modifyreg32(I2C_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW); if (pll_freq == RTC_PLL_FREQ_480M) { - /* Set this register to let the digital part know 480M PLL is used */ - - modifyreg32(SYSTEM_CPU_PER_CONF_REG, 0, SYSTEM_PLL_FREQ_SEL); - /* Configure 480M PLL */ switch (xtal_freq) @@ -1361,7 +1417,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; @@ -1373,7 +1428,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 1; dchgp = 4; dcur = 0; - dbias = 2; } break; @@ -1385,7 +1439,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; } @@ -1394,11 +1447,7 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( } else { - /* Clear this register to let the digital part know 320M PLL is used */ - - modifyreg32(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL, 0); - - /* Configure 480M PLL */ + /* Configure 320M PLL */ switch (xtal_freq) { @@ -1410,7 +1459,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; @@ -1422,7 +1470,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; @@ -1434,7 +1481,6 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( dr3 = 0; dchgp = 5; dcur = 3; - dbias = 2; } break; } @@ -1445,7 +1491,7 @@ static void IRAM_ATTR esp32s3_rtc_bbpll_configure( i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref); i2c_bbpll_div_7_0 = div7_0; i2c_bbpll_dcur = (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | - (2 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; + (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); @@ -1530,6 +1576,18 @@ void IRAM_ATTR esp32s3_rtc_init(void) cfg.cali_ocode = 1; } + /* When run rtc_init, it maybe deep sleep reset. Since we power down modem + * in deep sleep, after wakeup from deep sleep, these fields are changed + * and not reset. We will access two BB regs(BBPD_CTRL and NRXPD_CTRL) in + * rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these + * two BB regs and finally triggle RTC WDT. So need to clear modem Force + * PD. No worry about the power consumption, Because modem Force PD will + * be set at the end of this function. + */ + + modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO, 0); + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD, 0); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); @@ -1941,9 +1999,8 @@ uint32_t esp32s3_rtc_clk_apb_freq_get(void) void IRAM_ATTR esp32s3_rtc_cpu_freq_set_xtal(void) { - int freq_mhz = (int) esp32s3_rtc_clk_xtal_freq_get(); + int freq_mhz = (int)esp32s3_rtc_clk_xtal_freq_get(); esp32s3_rtc_update_to_xtal(freq_mhz, 1); - esp32s3_rtc_wait_for_slow_cycle(); esp32s3_rtc_bbpll_disable(); } @@ -2383,15 +2440,16 @@ void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_set_config( esp32s3_rtc_update_to_xtal(config->freq_mhz, config->div); if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - esp32s3_rtc_clk_bbpll_disable(); + esp32s3_rtc_bbpll_disable(); } } else if (config->source == RTC_CPU_FREQ_SRC_PLL) { if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) { + esp32s3_rtc_bbpll_enable(); modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); esp32s3_rtc_bbpll_configure(esp32s3_rtc_clk_xtal_freq_get(), config->source_freq_mhz); } @@ -2403,7 +2461,7 @@ void IRAM_ATTR esp32s3_rtc_clk_cpu_freq_set_config( esp32s3_rtc_clk_cpu_freq_to_8m(); if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - esp32s3_rtc_clk_bbpll_disable(); + esp32s3_rtc_bbpll_disable(); } } } @@ -2535,46 +2593,6 @@ uint64_t esp32s3_rtc_get_time_us(void) return delta_time_us; } -/**************************************************************************** - * Name: esp32s3_rtc_bbpll_enable - * - * Description: - * Power up BBPLL circuit. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void IRAM_ATTR esp32s3_rtc_bbpll_enable(void) -{ - modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); -} - -/**************************************************************************** - * Name: esp32_rtc_bbpll_disable - * - * Description: - * Power down BBPLL circuit. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void IRAM_ATTR esp32s3_rtc_bbpll_disable(void) -{ - modifyreg32(RTC_CNTL_RTC_OPTIONS0_REG, 0, RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); -} - /**************************************************************************** * Name: esp32c3_rtc_sleep_low_init * @@ -2661,13 +2679,27 @@ uint64_t IRAM_ATTR esp32s3_rtc_get_boot_time(void) #ifdef CONFIG_ESP32S3_SYSTEM_BBPLL_RECALIB void IRAM_ATTR esp32s3_rtc_recalib_bbpll(void) { - struct esp32s3_cpu_freq_config_s freq_config; + struct esp32s3_cpu_freq_config_s freq_config = + { + 0 + }; + esp32s3_rtc_clk_cpu_freq_get_config(&freq_config); - esp32s3_rtc_cpu_freq_set_xtal(); - esp32s3_rtc_bbpll_disable(); - esp32s3_rtc_bbpll_enable(); - esp32s3_rtc_bbpll_configure(esp32s3_rtc_clk_xtal_freq_get(), 480); - esp32s3_rtc_clk_cpu_freq_set_config(&freq_config); + + /* There are two paths we arrive here: 1.CPU reset. 2.Other reset reasons. + * - For other reasons, the bootloader will set CPU source to BBPLL and + * enable it. But there are calibration issues. Turn off the BBPLL and + * do calibration again to fix the issue. + * - For CPU reset, the CPU source will be set to XTAL, while the BBPLL + * is kept to meet USB Serial JTAG's requirements. In this case, we + * don't touch BBPLL to avoid USJ disconnection. + */ + + if (freq_config.source == RTC_CPU_FREQ_SRC_PLL) + { + esp32s3_rtc_cpu_freq_set_xtal(); + esp32s3_rtc_clk_cpu_freq_set_config(&freq_config); + } } #endif diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.h b/arch/xtensa/src/esp32s3/esp32s3_rtc.h index 7ad11eec4dc90..9b4f4464daecd 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.h +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.h @@ -301,22 +301,6 @@ enum esp32s3_rtc_xtal_freq_e esp32s3_rtc_clk_xtal_freq_get(void); void esp32s3_rtc_update_to_xtal(int freq, int div); -/**************************************************************************** - * Name: esp32s3_rtc_bbpll_enable - * - * Description: - * Reset BBPLL configuration. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void esp32s3_rtc_bbpll_enable(void); - /**************************************************************************** * Name: esp32s3_rtc_clk_set * @@ -434,22 +418,6 @@ uint64_t esp32s3_rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t esp32s3_clk_slowclk_cal_get(void); -/**************************************************************************** - * Name: esp32s3_rtc_bbpll_disable - * - * Description: - * disable BBPLL. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -void esp32s3_rtc_bbpll_disable(void); - /**************************************************************************** * Name: esp32s3_rtc_sleep_set_wakeup_time * diff --git a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h index 3a8ab206f0c1a..8b26a01a815a5 100644 --- a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h +++ b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h @@ -5843,6 +5843,13 @@ #define RTC_CNTL_DATE_V 0x0fffffff #define RTC_CNTL_DATE_S 0 +/* LDO SLAVE : R/W ;bitpos:[18:13] ; default: 6'd0 ; */ + +#define RTC_CNTL_SLAVE_PD 0x0000003F +#define RTC_CNTL_SLAVE_PD_M ((RTC_CNTL_SLAVE_PD_V)<<(RTC_CNTL_SLAVE_PD_S)) +#define RTC_CNTL_SLAVE_PD_V 0x3f +#define RTC_CNTL_SLAVE_PD_S 13 + /* Deep sleep (power down digital domain) */ #define RTC_SLEEP_PD_DIG BIT(0) From 0a0af89de9dfbfd1621548e9ea5cd63fac856cd4 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Sat, 10 Aug 2024 10:50:41 +0800 Subject: [PATCH 35/81] board/lm3s6965-ek: fix memory.ld for PROTECTED The uflash origin should equal to kflash size, this completes the fix to unblock CI. Signed-off-by: Yanfeng Liu --- boards/arm/tiva/lm3s6965-ek/scripts/memory.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld b/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld index 771fabbef8bbf..9bb7703419956 100644 --- a/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld +++ b/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld @@ -27,7 +27,7 @@ MEMORY /* 256Kb FLASH */ kflash (rx) : ORIGIN = 0x00000000, LENGTH = 124K - uflash (rx) : ORIGIN = 0x00020000, LENGTH = 132K + uflash (rx) : ORIGIN = 0x0001f000, LENGTH = 132K xflash (rx) : ORIGIN = 0x00040000, LENGTH = 0K /* 64Kb of contiguous SRAM */ From 7e0db9406360e01fd9cdcae74611adcc0588f433 Mon Sep 17 00:00:00 2001 From: "Alan C. Assis" Date: Fri, 9 Aug 2024 08:59:59 -0700 Subject: [PATCH 36/81] arm/lm3s6965-ek: Disable NTPC for lm3s6965 to fix maximum flash space reached --- boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig b/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig index ba029f9a37bea..3b157590f2770 100644 --- a/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig +++ b/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig @@ -91,7 +91,6 @@ CONFIG_SYSLOG_CONSOLE=y CONFIG_SYSTEM_DHCPC_RENEW=y CONFIG_SYSTEM_NETDB=y CONFIG_SYSTEM_NSH=y -CONFIG_SYSTEM_NTPC=y CONFIG_SYSTEM_PING=y CONFIG_TASK_NAME_SIZE=24 CONFIG_TESTING_OSTEST=y From d77ef098c6498a237c9b39bb5bf625e93c4a59b1 Mon Sep 17 00:00:00 2001 From: Daniel Jasinski Date: Sat, 10 Aug 2024 12:28:54 -0400 Subject: [PATCH 37/81] build: set CMake policy to allow FetchContent_Populate FetchContent_Populate is depracated starting from CMake 3.30. Setting this policy to OLD allows clean CMake builds for configurations that rely on CMake fetch content feature. Signed-off-by: Daniel Jasinski --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cb7714a2e434..b2effa4c918a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,11 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) endif() +if(POLICY CMP0169) + # allow to call FetchContent_Populate directly + cmake_policy(SET CMP0169 OLD) +endif() + # Basic CMake configuration ################################################## set(CMAKE_CXX_EXTENSIONS OFF) From 208b8e084f0071506491922a944934516e92c8a8 Mon Sep 17 00:00:00 2001 From: Rodrigo Sim Date: Sat, 10 Aug 2024 13:17:06 -0300 Subject: [PATCH 38/81] arm/stm32f401rc-rs485: Add support to BMP280 sensor Signed-off-by: Rodrigo Sim --- .../boards/stm32f401rc-rs485/index.rst | 19 ++++ .../arm/stm32/common/include/stm32_bmp280.h | 84 ++++++++++++++ boards/arm/stm32/common/src/CMakeLists.txt | 4 + boards/arm/stm32/common/src/Make.defs | 4 + boards/arm/stm32/common/src/stm32_bmp280.c | 106 ++++++++++++++++++ .../configs/bmp280/defconfig | 69 ++++++++++++ .../stm32f401rc-rs485/src/stm32_bringup.c | 15 +++ drivers/sensors/Kconfig | 17 +++ drivers/sensors/bmp280_uorb.c | 4 + 9 files changed, 322 insertions(+) create mode 100644 boards/arm/stm32/common/include/stm32_bmp280.h create mode 100644 boards/arm/stm32/common/src/stm32_bmp280.c create mode 100644 boards/arm/stm32/stm32f401rc-rs485/configs/bmp280/defconfig diff --git a/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst b/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst index 339f5064e7c3a..20d067d01bc5d 100644 --- a/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst +++ b/Documentation/platforms/arm/stm32f4/boards/stm32f401rc-rs485/index.rst @@ -691,3 +691,22 @@ at 13.56 MHz and ISO/IEC 14443 A/MIFARE and NTAG. .. figure:: mfrc522_image.jpg :align: center + +bmp280 +------ + +Configures the NuttShell (nsh) over USB Serial (check usbserial configuration) and enables BMP280 Digital Pressure Sensor. +BMP280 has an I2C address that can be configure by SDO. Connecting SDO to GND results in slave +address 0x76, connection it to VDD results in slave address 0x77. This can be configured by enabling BMP280_I2C_ADDR_76 or BMP280_I2C_ADDR_77. This configuration uses I2C1 and slave address 0x77. + +NSH commands:: + + NuttShell (NSH) NuttX-12.6.0-RC1 + nsh> bmp280 + Absolute pressure [hPa] = 911.400024 + Temperature [C] = 26.110001 + nsh> bmp280 + Absolute pressure [hPa] = 932.650024 + Temperature [C] = 24.490000 + +There is a known issue where every time the sensor is initialized, the first measurement is wrong, please check https://github.com/apache/nuttx/issues/12421 for the latest updates on this issue. \ No newline at end of file diff --git a/boards/arm/stm32/common/include/stm32_bmp280.h b/boards/arm/stm32/common/include/stm32_bmp280.h new file mode 100644 index 0000000000000..9c15ff6f610d1 --- /dev/null +++ b/boards/arm/stm32/common/include/stm32_bmp280.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * boards/arm/stm32/common/include/stm32_bmp280.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_STM32_COMMON_INCLUDE_STM32_BMP280_H +#define __BOARDS_ARM_STM32_COMMON_INCLUDE_STM32_BMP280_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_bmp280_initialize + * + * Description: + * Initialize and register the BMP280 Pressure Sensor driver. + * + * Input Parameters: + * devno - The device number, used to build the device path as /dev/pressN + * busno - The I2C bus number + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_bmp280_initialize(int devno, int busno); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __BOARDS_ARM_STM32_COMMON_INCLUDE_STM32_BMP280_H */ diff --git a/boards/arm/stm32/common/src/CMakeLists.txt b/boards/arm/stm32/common/src/CMakeLists.txt index 4c6c4df796d34..668cb257f669d 100644 --- a/boards/arm/stm32/common/src/CMakeLists.txt +++ b/boards/arm/stm32/common/src/CMakeLists.txt @@ -24,6 +24,10 @@ if(CONFIG_SENSORS_BMP180) list(APPEND SRCS stm32_bmp180.c) endif() +if(CONFIG_SENSORS_BMP280) + list(APPEND SRCS stm32_bmp280.c) +endif() + if(CONFIG_LEDS_APA102) list(APPEND SRCS stm32_apa102.c) endif() diff --git a/boards/arm/stm32/common/src/Make.defs b/boards/arm/stm32/common/src/Make.defs index ddb698c13b3f6..fc75a96098b97 100644 --- a/boards/arm/stm32/common/src/Make.defs +++ b/boards/arm/stm32/common/src/Make.defs @@ -24,6 +24,10 @@ ifeq ($(CONFIG_SENSORS_BMP180),y) CSRCS += stm32_bmp180.c endif +ifeq ($(CONFIG_SENSORS_BMP280),y) + CSRCS += stm32_bmp280.c +endif + ifeq ($(CONFIG_SENSORS_MS56XX),y) CSRCS += stm32_ms5611.c endif diff --git a/boards/arm/stm32/common/src/stm32_bmp280.c b/boards/arm/stm32/common/src/stm32_bmp280.c new file mode 100644 index 0000000000000..b8b0f70ebfa91 --- /dev/null +++ b/boards/arm/stm32/common/src/stm32_bmp280.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * boards/arm/stm32/common/src/stm32_bmp280.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "stm32_i2c.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_bmp280_initialize + * + * Description: + * Initialize and register the BMP280 Pressure Sensor driver. + * + * Input Parameters: + * devno - The device number, used to build the device path as /dev/pressN + * busno - The I2C bus number + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_bmp280_initialize(int devno, int busno) +{ + struct i2c_master_s *i2c; + int ret; + + sninfo("Initializing BMP280!\n"); + + /* Initialize BMP280 */ + + i2c = stm32_i2cbus_initialize(busno); + if (i2c) + { + /* Then try to register the barometer sensor in I2C0 */ + + ret = bmp280_register(devno, i2c); + if (ret < 0) + { + snerr("ERROR: Error registering BMP280 in I2C%d\n", busno); + } + } + else + { + ret = -ENODEV; + } + + return ret; +} + diff --git a/boards/arm/stm32/stm32f401rc-rs485/configs/bmp280/defconfig b/boards/arm/stm32/stm32f401rc-rs485/configs/bmp280/defconfig new file mode 100644 index 0000000000000..20d75c29f72dc --- /dev/null +++ b/boards/arm/stm32/stm32f401rc-rs485/configs/bmp280/defconfig @@ -0,0 +1,69 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_DISABLE_IFCONFIG is not set +# CONFIG_NSH_DISABLE_PS is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32f401rc-rs485" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_STM32F401RC_RS485=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="stm32" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32F401RC=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_IRQBUTTONS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BMP280_I2C_ADDR_77=y +CONFIG_BOARDCTL_USBDEVCTRL=y +CONFIG_BOARD_LOOPSPERMSEC=8499 +CONFIG_BUILTIN=y +CONFIG_CDCACM=y +CONFIG_CDCACM_CONSOLE=y +CONFIG_EXAMPLES_BMP280=y +CONFIG_EXAMPLES_BUTTONS=y +CONFIG_EXAMPLES_BUTTONS_NAME0="SW3" +CONFIG_EXAMPLES_BUTTONS_NAME1="SW4" +CONFIG_EXAMPLES_BUTTONS_NAME2="SW5" +CONFIG_EXAMPLES_BUTTONS_NAMES=y +CONFIG_EXAMPLES_BUTTONS_QTD=3 +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INPUT=y +CONFIG_INPUT_BUTTONS=y +CONFIG_INPUT_BUTTONS_LOWER=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=98304 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SENSORS=y +CONFIG_SENSORS_BMP280=y +CONFIG_SPI=y +CONFIG_START_DAY=5 +CONFIG_START_MONTH=5 +CONFIG_START_YEAR=2014 +CONFIG_STM32_I2C1=y +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_OTGFS=y +CONFIG_STM32_PWR=y +CONFIG_STM32_USART6=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=0 +CONFIG_USBDEV=y diff --git a/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c index cd8f236be0426..b513580b4f739 100644 --- a/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c +++ b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c @@ -75,6 +75,10 @@ #include "stm32_drv8266.h" #endif +#ifdef CONFIG_SENSORS_BMP280 +#include "stm32_bmp280.h" +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -298,5 +302,16 @@ int stm32_bringup(void) } #endif +#ifdef CONFIG_SENSORS_BMP280 + /* Initialize the BMP280 pressure sensor. */ + + ret = board_bmp280_initialize(0, 1); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize BMP280, error %d\n", ret); + return ret; + } +#endif + return ret; } diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 6c78c06bc28d5..6abab708aa08e 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -379,6 +379,23 @@ config SENSORS_BMP280 if SENSORS_BMP280 +choice + prompt "I2C Address" + default BMP280_I2C_ADDR_76 + +config BMP280_I2C_ADDR_76 + bool "0x76" + ---help--- + Default address. + If SDO pin is pulled to GND, use 0x76 + +config BMP280_I2C_ADDR_77 + bool "0x77" + ---help--- + If SDO pin is pulled to VDDIO, use 0x77 + +endchoice # I2C Address + config BMP280_I2C_FREQUENCY int "BMP280 I2C frequency" default 400000 diff --git a/drivers/sensors/bmp280_uorb.c b/drivers/sensors/bmp280_uorb.c index 7acdb664d9362..ecf5289d86472 100644 --- a/drivers/sensors/bmp280_uorb.c +++ b/drivers/sensors/bmp280_uorb.c @@ -42,7 +42,11 @@ * Pre-processor Definitions ****************************************************************************/ +#ifdef CONFIG_BMP280_I2C_ADDR_76 #define BMP280_ADDR 0x76 +#else +#define BMP280_ADDR 0x77 +#endif #define BMP280_FREQ CONFIG_BMP280_I2C_FREQUENCY #define DEVID 0x58 From fe10abe4a0d953e0f1853189bae425a61dcb1cc9 Mon Sep 17 00:00:00 2001 From: "Alan C. Assis" Date: Sat, 10 Aug 2024 08:51:14 -0700 Subject: [PATCH 39/81] arm/stm32f103-minimum: Use common board MFRC522 --- .../configs/rfid-rc522/defconfig | 1 + .../stm32f103-minimum/src/CMakeLists.txt | 4 - .../arm/stm32/stm32f103-minimum/src/Make.defs | 4 - .../stm32f103-minimum/src/stm32_bringup.c | 4 + .../stm32f103-minimum/src/stm32_mfrc522.c | 86 ------------------- .../stm32f103-minimum/src/stm32f103_minimum.h | 12 --- 6 files changed, 5 insertions(+), 106 deletions(-) delete mode 100644 boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c diff --git a/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig b/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig index 5bb78a6b9431f..e36cee0693e38 100644 --- a/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig +++ b/boards/arm/stm32/stm32f103-minimum/configs/rfid-rc522/defconfig @@ -19,6 +19,7 @@ # CONFIG_NSH_DISABLE_XD is not set CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="stm32f103-minimum" +CONFIG_ARCH_BOARD_COMMON=y CONFIG_ARCH_BOARD_STM32F103_MINIMUM=y CONFIG_ARCH_CHIP="stm32" CONFIG_ARCH_CHIP_STM32=y diff --git a/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt b/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt index fa92900f2d3f2..0fc22fd9dc5d8 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt +++ b/boards/arm/stm32/stm32f103-minimum/src/CMakeLists.txt @@ -79,10 +79,6 @@ if(CONFIG_CAN_MCP2515) list(APPEND SRCS stm32_mcp2515.c) endif() -if(CONFIG_CL_MFRC522) - list(APPEND SRCS stm32_mfrc522.c) -endif() - if(CONFIG_LCD_MAX7219) list(APPEND SRCS stm32_max7219.c) endif() diff --git a/boards/arm/stm32/stm32f103-minimum/src/Make.defs b/boards/arm/stm32/stm32f103-minimum/src/Make.defs index 651c06d46b134..10c18a339cbb9 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/Make.defs +++ b/boards/arm/stm32/stm32f103-minimum/src/Make.defs @@ -81,10 +81,6 @@ ifeq ($(CONFIG_CAN_MCP2515),y) CSRCS += stm32_mcp2515.c endif -ifeq ($(CONFIG_CL_MFRC522),y) - CSRCS += stm32_mfrc522.c -endif - ifeq ($(CONFIG_LCD_MAX7219),y) CSRCS += stm32_max7219.c endif diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c b/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c index d228b1bc9c61e..16d4a8c9fc610 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c +++ b/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c @@ -56,6 +56,10 @@ # include #endif +#ifdef CONFIG_CL_MFRC522 +#include "stm32_mfrc522.h" +#endif + #include "stm32f103_minimum.h" /* Conditional logic in stm32f103_minimum.h will determine if certain diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c b/boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c deleted file mode 100644 index cb20cf6155a79..0000000000000 --- a/boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** - * boards/arm/stm32/stm32f103-minimum/src/stm32_mfrc522.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you 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. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include - -#include -#include - -#include "stm32.h" -#include "stm32_spi.h" -#include "stm32f103_minimum.h" - -#if defined(CONFIG_SPI) && defined(CONFIG_STM32_SPI1) && defined(CONFIG_CL_MFRC522) - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define MFRC522_SPI_PORTNO 1 /* On SPI1 */ - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: stm32_mfrc522initialize - * - * Description: - * Initialize and register the MFRC522 RFID driver. - * - * Input Parameters: - * devpath - The full path to the driver to register. E.g., "/dev/rfid0" - * - * Returned Value: - * Zero (OK) on success; a negated errno value on failure. - * - ****************************************************************************/ - -int stm32_mfrc522initialize(const char *devpath) -{ - struct spi_dev_s *spi; - int ret; - - spi = stm32_spibus_initialize(MFRC522_SPI_PORTNO); - - if (!spi) - { - return -ENODEV; - } - - /* Then register the MFRC522 */ - - ret = mfrc522_register(devpath, spi); - if (ret < 0) - { - snerr("ERROR: Error registering MFRC522\n"); - } - - return ret; -} - -#endif /* CONFIG_SPI && CONFIG_MFRC522 */ diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h b/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h index 44929f9453b4a..fbdcf126516d0 100644 --- a/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h +++ b/boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h @@ -372,17 +372,5 @@ int stm32_hyt271initialize(int devno); int stm32_ds18b20initialize(int devno); #endif -/**************************************************************************** - * Name: stm32_mfrc522initialize - * - * Description: - * Function used to initialize the MFRC522 RFID Transceiver - * - ****************************************************************************/ - -#ifdef CONFIG_CL_MFRC522 -int stm32_mfrc522initialize(const char *devpath); -#endif - #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_STM32_STM32F103_MINIMUM_SRC_STM32F103_MINIMUM_H */ From af78534df9a1c1b9a0a5c8519d90856c975560f5 Mon Sep 17 00:00:00 2001 From: Nicolas Gariepy Date: Fri, 9 Aug 2024 21:16:02 -0400 Subject: [PATCH 40/81] fix stm32wl5_rcc.h: Add the missing argument to RCC_PLLCFG_PLLP define. --- arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h index c730a3d4c0743..df9c46636fd94 100644 --- a/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h @@ -276,7 +276,7 @@ #define RCC_PLLCFG_PLLP_SHIFT (17) /* Bit 17-21: Main PLL div factor for PLLPCLK */ #define RCC_PLLCFG_PLLP_MASK (0x1f << RCC_PLLCFG_PLLP_SHIFT) -# define RCC_PLLCFG_PLLP (((n)-1) << RCC_PLLCFG_PLLP_SHIFT) /* 2..32 */ +#define RCC_PLLCFG_PLLP(n) (((n)-1) << RCC_PLLCFG_PLLP_SHIFT) /* 2..32 */ #define RCC_PLLCFG_PLLQEN (1 << 24) /* Bit 24: Main PLL PLLQCLK output enable */ From 76b58e4af06234ebd969251c6191e75b4c869aee Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Sun, 11 Aug 2024 10:15:52 +0800 Subject: [PATCH 41/81] board/lm3s6965-ek: restore 128K kflash This reverts both 2afdcfb6a6 and 0a0af89de9 to restore the 128K kflash design as the implementation depends on that to work, checked with: ``` $ qemu-system-arm -M lm3s6965evb -nographic -device \ loader,file=nuttx.bin,addr=0x0 -device \ loader,file=nuttx_user.bin,addr=0x2000 ``` Signed-off-by: Yanfeng Liu --- boards/arm/tiva/lm3s6965-ek/scripts/memory.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld b/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld index 9bb7703419956..acc84a83d6f65 100644 --- a/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld +++ b/boards/arm/tiva/lm3s6965-ek/scripts/memory.ld @@ -26,8 +26,8 @@ MEMORY { /* 256Kb FLASH */ - kflash (rx) : ORIGIN = 0x00000000, LENGTH = 124K - uflash (rx) : ORIGIN = 0x0001f000, LENGTH = 132K + kflash (rx) : ORIGIN = 0x00000000, LENGTH = 128K + uflash (rx) : ORIGIN = 0x00020000, LENGTH = 128K xflash (rx) : ORIGIN = 0x00040000, LENGTH = 0K /* 64Kb of contiguous SRAM */ From 029411f00cc89c24f0be26756bb6a251207dc9ce Mon Sep 17 00:00:00 2001 From: anjiahao Date: Mon, 18 Dec 2023 20:50:37 +0800 Subject: [PATCH 42/81] arm:Select ram vector on armv6m Signed-off-by: anjiahao --- arch/arm/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fab5dd53ffb85..2d174dccfea5b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -797,6 +797,7 @@ config ARCH_CORTEXM0 select ARM_THUMB select ARCH_ARMV6M select ARCH_HAVE_IRQPRIO + select ARCH_HAVE_RAMVECTORS select ARCH_HAVE_RESET select ARCH_HAVE_HARDFAULT_DEBUG From 47b0414eabce3adf8a2c0c158caedb6eea20f62b Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Mon, 29 Jul 2024 16:01:54 +0800 Subject: [PATCH 43/81] arch/riscv: add cluster local hartid Some multicore RV chips (mpfs, jh7110 etc) have hart clusters and globally numbered mhartids. Clusters with single hart or SMP support can be managed by one NuttX instance. Currently NuttX expects to use cluster-local ids. This allows us to get local ids by offsetting mhartids with a base value. Note that there are chips (e.g. k230) that use cluster-local ids directly, so this is not needed for them. Signed-off-by: Yanfeng Liu --- arch/risc-v/Kconfig | 14 ++++++++++++++ arch/risc-v/src/common/riscv_macros.S | 3 +++ 2 files changed, 17 insertions(+) diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 3f04a4738ae89..2da3665d0cc03 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -451,6 +451,20 @@ config ARCH_RV_MMIO_BITS default 32 if ARCH_RV32 default 64 if ARCH_RV64 +config ARCH_RV_HARTID_BASE + int "Base hartid of this cluster" + default 0 + ---help--- + Some RV chips have multiple cluster of harts with + globally numbered mhartids, like qemu-rv, mpfs and + jh7110 etc. Clusters with SMP ability can be managed + by NuttX. As NuttX expects cluster-local hart ids, + we can shift mhartid by this value to derive such + local ids. The SMP_NCPUS still defines number of + harts in the cluster. Note that we assume that global + ids for each cluster are continuous. Note that there + are chips like k230 which don't have global mhartid. + config ARCH_FAMILY string default "rv32" if ARCH_RV32 diff --git a/arch/risc-v/src/common/riscv_macros.S b/arch/risc-v/src/common/riscv_macros.S index 0ab8358d507d9..03ddfe872d8ed 100644 --- a/arch/risc-v/src/common/riscv_macros.S +++ b/arch/risc-v/src/common/riscv_macros.S @@ -362,6 +362,9 @@ REGLOAD \out, RISCV_PERCPU_HARTID(\out) #else csrr \out, CSR_MHARTID +# if CONFIG_ARCH_RV_HARTID_BASE > 0 + add \out, \out, - CONFIG_ARCH_RV_HARTID_BASE +# endif #endif .endm From 3e171489bd26fb6547cb687a2883fd292dc574f7 Mon Sep 17 00:00:00 2001 From: yanghuatao Date: Wed, 24 Apr 2024 01:06:17 +0800 Subject: [PATCH 44/81] toolchain/ghs: Fix green hills toolchain build Vela link error [elxr] (error #412) unresolved symbols: __builtin_frame_address from libarch.a(arm_checkstack.o) Signed-off-by: yanghuatao --- arch/arm/include/armv6-m/irq.h | 13 +++++++++++++ arch/arm/include/armv7-a/irq.h | 13 +++++++++++++ arch/arm/include/armv7-m/irq.h | 13 +++++++++++++ arch/arm/include/armv7-r/irq.h | 13 +++++++++++++ arch/arm/include/armv8-m/irq.h | 13 +++++++++++++ arch/arm/include/armv8-r/irq.h | 13 +++++++++++++ arch/arm/include/irq.h | 2 -- arch/arm/include/tlsr82/irq.h | 13 +++++++++++++ 8 files changed, 91 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/armv6-m/irq.h b/arch/arm/include/armv6-m/irq.h index e900b6b1c5adb..335e81c2bd04e 100644 --- a/arch/arm/include/armv6-m/irq.h +++ b/arch/arm/include/armv6-m/irq.h @@ -330,6 +330,19 @@ static inline void setcontrol(uint32_t control) : "memory"); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv7-a/irq.h b/arch/arm/include/armv7-a/irq.h index 1bc4ce0ce5c1a..61437233f770c 100644 --- a/arch/arm/include/armv7-a/irq.h +++ b/arch/arm/include/armv7-a/irq.h @@ -406,6 +406,19 @@ noinstrument_function static inline void up_irq_restore(irqstate_t flags) ); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv7-m/irq.h b/arch/arm/include/armv7-m/irq.h index cfa94f44e504f..8a9e1f801ffdf 100644 --- a/arch/arm/include/armv7-m/irq.h +++ b/arch/arm/include/armv7-m/irq.h @@ -535,6 +535,19 @@ static inline void setcontrol(uint32_t control) : "memory"); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv7-r/irq.h b/arch/arm/include/armv7-r/irq.h index 09a107a3171da..a31c90ebbb93e 100644 --- a/arch/arm/include/armv7-r/irq.h +++ b/arch/arm/include/armv7-r/irq.h @@ -402,6 +402,19 @@ static inline void up_irq_restore(irqstate_t flags) ); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv8-m/irq.h b/arch/arm/include/armv8-m/irq.h index a440a4da9895b..4e3f3b9b0cd3c 100644 --- a/arch/arm/include/armv8-m/irq.h +++ b/arch/arm/include/armv8-m/irq.h @@ -508,6 +508,19 @@ static inline void setcontrol(uint32_t control) : "memory"); } +static inline_function uint32_t up_getsp(void) +{ + uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/armv8-r/irq.h b/arch/arm/include/armv8-r/irq.h index e094657485a7c..b0e1a9ff8d767 100644 --- a/arch/arm/include/armv8-r/irq.h +++ b/arch/arm/include/armv8-r/irq.h @@ -402,6 +402,19 @@ static inline void up_irq_restore(irqstate_t flags) ); } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "mov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** diff --git a/arch/arm/include/irq.h b/arch/arm/include/irq.h index 21e221816bd55..137592728c371 100644 --- a/arch/arm/include/irq.h +++ b/arch/arm/include/irq.h @@ -66,8 +66,6 @@ * Pre-processor Prototypes ****************************************************************************/ -#define up_getsp() (uintptr_t)__builtin_frame_address(0) - #ifndef __ASSEMBLY__ #ifdef __cplusplus diff --git a/arch/arm/include/tlsr82/irq.h b/arch/arm/include/tlsr82/irq.h index d7032bfbb17ac..edb15a170273c 100644 --- a/arch/arm/include/tlsr82/irq.h +++ b/arch/arm/include/tlsr82/irq.h @@ -236,6 +236,19 @@ static inline uint32_t getcontrol(void) return 0; } +static inline_function uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__ + ( + "tmov %0, sp\n" + : "=r" (sp) + ); + + return sp; +} + #endif /* __ASSEMBLY__ */ /**************************************************************************** From 5bb805b22992a36bafdc16b113085bcfe208d26c Mon Sep 17 00:00:00 2001 From: yanghuatao Date: Wed, 24 Apr 2024 00:13:06 +0800 Subject: [PATCH 45/81] toolchain/ghs: Fix green hills toolchain build Vela asarm errors common/gnu/fork.S 29: unknown instruction .syntax unified --^ [asarm] (error #2230) common/gnu/fork.S 81: bad directive .type up_fork , function ------------------^ [asarm] (error #2067) armv7-m/arm_saveusercontext.S 31: unknown instruction .syntax unified --^ [asarm] (error #2230) armv7-m/arm_saveusercontext.S 55: bad directive .type up_saveusercontext , % function --^ [asarm] (error #2004) armv7-m/arm_saveusercontext.S 65: not within valid register range str r12 , [ r0 , ( 4 * ( ( ( 12 ) + ( 16 ) ) + 4 ) ) ] ------^ [asarm] (error #2004) armv7-m/arm_saveusercontext.S 66: not within valid register range str r14 , [ r0 , ( 4 * ( ( ( 12 ) + ( 16 ) ) + 5 ) ) ] ------^ [asarm] (error #2004) armv7-m/arm_saveusercontext.S 67: not within valid register range str r14 , [ r0 , ( 4 * ( ( ( 12 ) + ( 16 ) ) + 6 ) ) ] ------^ [asarm] (error #2014) armv7-m/arm_saveusercontext.S 72: expected a register str r1 , [ r0 , ( 4 * ( ( ( 12 ) + ( 16 ) ) + 7 ) ) ] ------------------^ [asarm] (error #2004) armv7-m/arm_saveusercontext.S 75: not within valid register range add r1 , r0 , ( 4 * ( ( ( 12 ) + ( 16 ) ) + 8 ) ) -----------^ [asarm] (error #2071) armv7-m/arm_saveusercontext.S 89: bad parameter stmia r0 ! , { r2 - r11 } --------^ [asarm] (error #2014) armv7-m/arm_saveusercontext.S 93: expected a register mov r1 , - 1 -----------^ Signed-off-by: yanghuatao --- arch/arm/src/armv7-m/arm_exception.S | 9 ++++++++- arch/arm/src/armv7-m/arm_saveusercontext.S | 8 ++++++++ arch/arm/src/common/gnu/fork.S | 5 ++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/armv7-m/arm_exception.S b/arch/arm/src/armv7-m/arm_exception.S index d2478aadd2b15..4f057ae113ac1 100644 --- a/arch/arm/src/armv7-m/arm_exception.S +++ b/arch/arm/src/armv7-m/arm_exception.S @@ -87,9 +87,12 @@ ****************************************************************************/ .globl exception_common - +#ifdef __ghs__ + .thumb2 +#else .syntax unified .thumb +#endif .file "arm_exception.S" /**************************************************************************** @@ -119,8 +122,12 @@ .text .section .text.exception_common +#ifdef __ghs__ + .type exception_common, $function +#else .thumb_func .type exception_common, function +#endif exception_common: mrs r0, ipsr /* R0=exception number */ diff --git a/arch/arm/src/armv7-m/arm_saveusercontext.S b/arch/arm/src/armv7-m/arm_saveusercontext.S index 58d02f575f9da..5e67be0e6c51b 100644 --- a/arch/arm/src/armv7-m/arm_saveusercontext.S +++ b/arch/arm/src/armv7-m/arm_saveusercontext.S @@ -28,8 +28,12 @@ .file "arm_saveusercontext.S" .text +#ifdef __ghs__ + .thumb2 +#else .syntax unified .thumb +#endif /**************************************************************************** * Public Functions @@ -52,7 +56,11 @@ .globl up_saveusercontext .globl up_saveusercontext +#ifdef __ghs__ + .type up_saveusercontext, $function +#else .type up_saveusercontext, %function +#endif up_saveusercontext: diff --git a/arch/arm/src/common/gnu/fork.S b/arch/arm/src/common/gnu/fork.S index 7697561a2750a..d98003d4dab1e 100644 --- a/arch/arm/src/common/gnu/fork.S +++ b/arch/arm/src/common/gnu/fork.S @@ -26,7 +26,6 @@ #include "arm_fork.h" - .syntax unified .file "fork.S" /**************************************************************************** @@ -78,7 +77,11 @@ ****************************************************************************/ .globl up_fork +#ifdef __ghs__ + .type up_fork, $function +#else .type up_fork, function +#endif up_fork: /* Create a stack frame */ From 6da525704d04255e245af9e559641c036808c662 Mon Sep 17 00:00:00 2001 From: fangxinyong Date: Sun, 28 Apr 2024 22:04:50 +0800 Subject: [PATCH 46/81] toolchain/ghs: fix the inline assembly code register alloc compile error The following are the compile error that reported by GreenHills compiler: "/mnt/yang/qixinwei_commit/nuttx/include/arch/syscall.h", line 156 (col. 17): error #2036-D: cannot allocate "reg0" to specified caller-saved register "/mnt/yang/qixinwei_commit/nuttx/include/arch/syscall.h", line 157 (col. 17): error #2036-D: cannot allocate "reg1" to specified caller-saved register Then we fix this greenhills compilation error by explicitly specifying the registers in the clobber list in the inline assembly code. This fix is successful in compiling on the nuttx/boards/arm/mps/mps2-an500/configs/nsh platform and passes the ostest test. However, if we keep the implementation the same for both the default and Greenhills compilers, the default compiler will report the following two issues: 1. the "sys_call6" function will report compile error when compiling on "./vendor/qemu/boards/smartspeaker/configs/smartspeaker-knsh" platform, the detailed error info: CC: proxies/PROXY_mq_getattr.c In file included from /home/guoshichao/work_profile/vela_os/vela_qemu_1/nuttx/include/sys/syscall.h:35, from /home/guoshichao/work_profile/vela_os/vela_qemu_1/nuttx/include/syscall.h:30, from proxies/PROXY_mmap.c:5: In function 'sys_call6', inlined from 'mmap' at proxies/PROXY_mmap.c:9:22: /home/guoshichao/work_profile/vela_os/vela_qemu_1/nuttx/include/arch/syscall.h:297:3: error: 'asm' operand has impossible constraints 297 | __asm__ __volatile__ | ^~~~~~~ 2. when running on qemu-armv7-a platform, the modification to "smh_call()" function will make the system fail to boot up, so we need to keep the default compiler implementation and greenhills compiler implementation separate Signed-off-by: fangxinyong (cherry picked from commit cb48b749b1c9cad8cfb96bff7c5e9b6ebf20fc8a) --- arch/arm/include/syscall.h | 157 +++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/arch/arm/include/syscall.h b/arch/arm/include/syscall.h index 3b424bbb08a6e..ae59f8be75ae1 100644 --- a/arch/arm/include/syscall.h +++ b/arch/arm/include/syscall.h @@ -136,6 +136,18 @@ static inline uintptr_t sys_call0(unsigned int nbr) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0) + : "memory", "r14", "r0" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); __asm__ __volatile__ @@ -145,6 +157,7 @@ static inline uintptr_t sys_call0(unsigned int nbr) : "i"(SYS_syscall), "r"(reg0) : "memory", "r14" ); +#endif return reg0; } @@ -153,6 +166,20 @@ static inline uintptr_t sys_call0(unsigned int nbr) static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1) + : "memory", "r14", "r0", "r1" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg1 __asm__("r1") = (long)(parm1); @@ -163,6 +190,7 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) : "i"(SYS_syscall), "r"(reg0), "r"(reg1) : "memory", "r14" ); +#endif return reg0; } @@ -172,6 +200,22 @@ static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2) { +#ifdef __ghs__ + register long reg0 = (long)nbr; + register long reg2 = (long)parm2; + register long reg1 = (long)parm1; + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2) + : "memory", "r14", "r0", "r1", "r2" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg2 __asm__("r2") = (long)(parm2); register long reg1 __asm__("r1") = (long)(parm1); @@ -183,6 +227,7 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2) : "memory", "r14" ); +#endif return reg0; } @@ -192,6 +237,24 @@ static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3) + : "memory", "r14", "r0", "r1", "r2", "r3" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg3 __asm__("r3") = (long)(parm3); register long reg2 __asm__("r2") = (long)(parm2); @@ -204,6 +267,7 @@ static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3) : "memory", "r14" ); +#endif return reg0; } @@ -214,6 +278,27 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg4 = (long)(parm4); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "mov r4, %6\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4) + : "memory", "r14", "r0", "r1", "r2", "r3", "r4" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg4 __asm__("r4") = (long)(parm4); register long reg3 __asm__("r3") = (long)(parm3); @@ -228,6 +313,7 @@ static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, "r"(reg3), "r"(reg4) : "memory", "r14" ); +#endif return reg0; } @@ -238,6 +324,29 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg5 = (long)(parm5); + register long reg4 = (long)(parm4); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "mov r4, %6\n\t" + "mov r5, %7\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5) + : "memory", "r14", "r0", "r1", "r2", "r3", "r4", "r5" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg5 __asm__("r5") = (long)(parm5); register long reg4 __asm__("r4") = (long)(parm4); @@ -253,6 +362,7 @@ static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, "r"(reg3), "r"(reg4), "r"(reg5) : "memory", "r14" ); +#endif return reg0; } @@ -264,6 +374,31 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg6 = (long)(parm6); + register long reg5 = (long)(parm5); + register long reg4 = (long)(parm4); + register long reg3 = (long)(parm3); + register long reg2 = (long)(parm2); + register long reg1 = (long)(parm1); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" + "mov r2, %4\n\t" + "mov r3, %5\n\t" + "mov r4, %6\n\t" + "mov r5, %7\n\t" + "mov r6, %8\n\t" + "svc %1" + : "=r"(reg0) + : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6) + : "memory", "r14", "r0", "r1", "r2", "r3", "r4", "r5", "r6" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg6 __asm__("r6") = (long)(parm6); register long reg5 __asm__("r5") = (long)(parm5); @@ -280,6 +415,7 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6) : "memory", "r14" ); +#endif return reg0; } @@ -288,6 +424,26 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, static inline long smh_call(unsigned int nbr, void *parm) { +#ifdef __ghs__ + register long reg0 = (long)(nbr); + register long reg1 = (long)(parm); + + __asm__ __volatile__ + ( + "mov r0, %2\n\t" + "mov r1, %3\n\t" +#if defined(CONFIG_ARCH_ARMV6M) || \ + defined(CONFIG_ARCH_ARMV7M) || \ + defined(CONFIG_ARCH_ARMV8M) + "bkpt %1" +#else + "svc %1" +#endif + : "=r"(reg0) + : "i"(SYS_smhcall), "r"(reg0), "r"(reg1) + : "memory", "r14", "r0", "r1" + ); +#else register long reg0 __asm__("r0") = (long)(nbr); register long reg1 __asm__("r1") = (long)(parm); @@ -304,6 +460,7 @@ static inline long smh_call(unsigned int nbr, void *parm) : "i"(SYS_smhcall), "r"(reg0), "r"(reg1) : "memory", "r14" ); +#endif return reg0; } From 693e869404d157a725e67dc032cc23f6de3c3892 Mon Sep 17 00:00:00 2001 From: guoshichao Date: Wed, 19 Jun 2024 15:20:30 +0800 Subject: [PATCH 47/81] arm-m/barrier: fix green hills build ARM_ISB error according to armv6-m/armv7-m arch reference manual: the three ISB {}, DSB {}, DMB {} instructions field are defined as: Specifies an optional limitation on the ISB/DSB/DMB operation. Allowered values are: Full system ISB/DSB/DMB operation, encoded as option=='1111'. Can be omitted. All other encodings of the options are RESERVED. the "#opt" field of "isb #opt" So we could remove the options field in Armv7-m platform. The following are the build error with greenhills compiler: CC: common/arm_exit.c [asarm] (error #2071) /tmp/gh_001h70j1.si 92: bad parameter isb 15 ------^ [asarm] (error #2071) /tmp/gh_001h70j1.si 112: bad parameter isb 15 ------^ [asarm] (error) errors during processing According to armv8-m arch reference manual: the ISB/DMB instruction's "opt" encoding rule is same as armv6-m/armv7-m, but the "DSB" instruction is different, in armv8-m, the "DSB {}" field has two valid encoding options: 0b0000, 0b0100. and all other encoding options are reserved. In Armv7-a/Armv8-a, the dsb/dmb option field has 8 valid state value. Signed-off-by: guoshichao --- arch/arm/src/armv6-m/barriers.h | 12 ++++++------ arch/arm/src/armv7-a/barriers.h | 4 ++-- arch/arm/src/armv7-m/barriers.h | 12 ++++++------ arch/arm/src/armv7-r/barriers.h | 4 ++-- arch/arm/src/armv8-m/barriers.h | 8 ++++---- arch/arm/src/armv8-r/barriers.h | 4 ++-- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm/src/armv6-m/barriers.h b/arch/arm/src/armv6-m/barriers.h index 20c1a089dbe46..e0b661bc94787 100644 --- a/arch/arm/src/armv6-m/barriers.h +++ b/arch/arm/src/armv6-m/barriers.h @@ -31,12 +31,12 @@ /* ARMv6-M memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") -#define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") -#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_dsb() __asm__ __volatile__ ("dsb " : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") +#define arm_dmb() __asm__ __volatile__ ("dmb " : : : "memory") -#define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) -#define ARM_DMB() arm_dmb(15) +#define ARM_DSB() arm_dsb() +#define ARM_ISB() arm_isb() +#define ARM_DMB() arm_dmb() #endif /* __ARCH_ARM_SRC_ARMV6_M_BARRIERS_H */ diff --git a/arch/arm/src/armv7-a/barriers.h b/arch/arm/src/armv7-a/barriers.h index e8b5d94f93ac2..2258e4110f57d 100644 --- a/arch/arm/src/armv7-a/barriers.h +++ b/arch/arm/src/armv7-a/barriers.h @@ -31,15 +31,15 @@ /* ARMv7-A memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") #define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") #define arm_nop() __asm__ __volatile__ ("nop\n") #define arm_sev() __asm__ __volatile__ ("sev\n") #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) #define ARM_DMB() arm_dmb(15) +#define ARM_ISB() arm_isb() #define ARM_NOP() arm_nop() #define ARM_SEV() arm_sev() diff --git a/arch/arm/src/armv7-m/barriers.h b/arch/arm/src/armv7-m/barriers.h index b8d91fddacbd4..b020427a620e4 100644 --- a/arch/arm/src/armv7-m/barriers.h +++ b/arch/arm/src/armv7-m/barriers.h @@ -31,12 +31,12 @@ /* ARMv7-M memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") -#define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") -#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_dsb() __asm__ __volatile__ ("dsb " : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") +#define arm_dmb() __asm__ __volatile__ ("dmb " : : : "memory") -#define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) -#define ARM_DMB() arm_dmb(15) +#define ARM_DSB() arm_dsb() +#define ARM_ISB() arm_isb() +#define ARM_DMB() arm_dmb() #endif /* __ARCH_ARM_SRC_ARMV7_M_BARRIERS_H */ diff --git a/arch/arm/src/armv7-r/barriers.h b/arch/arm/src/armv7-r/barriers.h index fe17d57db36fb..71005f4a4dff9 100644 --- a/arch/arm/src/armv7-r/barriers.h +++ b/arch/arm/src/armv7-r/barriers.h @@ -31,15 +31,15 @@ /* ARMv7-R memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") #define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") #define arm_nop() __asm__ __volatile__ ("nop\n") #define arm_sev() __asm__ __volatile__ ("sev\n") #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) #define ARM_DMB() arm_dmb(15) +#define ARM_ISB() arm_isb() #define ARM_NOP() arm_nop() #define ARM_SEV() arm_sev() diff --git a/arch/arm/src/armv8-m/barriers.h b/arch/arm/src/armv8-m/barriers.h index 789268e567cea..22d896989b789 100644 --- a/arch/arm/src/armv8-m/barriers.h +++ b/arch/arm/src/armv8-m/barriers.h @@ -31,12 +31,12 @@ /* ARMv8-M memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") +#define arm_dmb() __asm__ __volatile__ ("dmb " : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") -#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define ARM_ISB() arm_isb() +#define ARM_DMB() arm_dmb() #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) -#define ARM_DMB() arm_dmb(15) #endif /* __ARCH_ARM_SRC_ARMV8_M_BARRIERS_H */ diff --git a/arch/arm/src/armv8-r/barriers.h b/arch/arm/src/armv8-r/barriers.h index 0fd9f5790ba78..7e542eb99d7a4 100644 --- a/arch/arm/src/armv8-r/barriers.h +++ b/arch/arm/src/armv8-r/barriers.h @@ -31,15 +31,15 @@ /* ARMv8-R memory barriers */ -#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory") #define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory") #define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory") +#define arm_isb() __asm__ __volatile__ ("isb " : : : "memory") #define arm_nop() __asm__ __volatile__ ("nop\n") #define arm_sev() __asm__ __volatile__ ("sev\n") #define ARM_DSB() arm_dsb(15) -#define ARM_ISB() arm_isb(15) #define ARM_DMB() arm_dmb(15) +#define ARM_ISB() arm_isb() #define ARM_NOP() arm_nop() #define ARM_SEV() arm_sev() From ed9d57b5012a1c1c26138a6783730526b3b7bf32 Mon Sep 17 00:00:00 2001 From: guoshichao Date: Mon, 22 Jul 2024 14:42:30 +0800 Subject: [PATCH 48/81] greenhills: fix the arch_setjmp.S build error CC: bch/bchlib_read.c [asarm] (error #2067) machine/arm/gnu/arch_setjmp.S 34: unknown instruction .syntax unified --^ [asarm] (error #2230) machine/arm/gnu/arch_setjmp.S 62: bad directive .type setjmp , function -----------------^ [asarm] (error) errors during processing Signed-off-by: guoshichao --- libs/libc/machine/arm/gnu/arch_setjmp.S | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/libc/machine/arm/gnu/arch_setjmp.S b/libs/libc/machine/arm/gnu/arch_setjmp.S index cae0f259fe6b0..77a26adfdd8fa 100644 --- a/libs/libc/machine/arm/gnu/arch_setjmp.S +++ b/libs/libc/machine/arm/gnu/arch_setjmp.S @@ -31,7 +31,9 @@ .globl setjmp .globl longjmp +#ifndef __ghs__ .syntax unified +#endif .file "setjmp.S" /**************************************************************************** @@ -59,7 +61,12 @@ * ****************************************************************************/ +#ifndef __ghs__ .type setjmp, function +#else + .type setjmp, $function +#endif + setjmp: /* Store callee-saved Core registers */ @@ -121,7 +128,11 @@ setjmp: * ****************************************************************************/ +#ifndef __ghs__ .type longjmp, function +#else + .type longjmp, $function +#endif longjmp: /* Load callee-saved Core registers */ From d76218e817a13f17763ffe03cdc349cae01c3124 Mon Sep 17 00:00:00 2001 From: guoshichao Date: Thu, 1 Aug 2024 21:36:03 +0800 Subject: [PATCH 49/81] greenhills: fix the moblib asm compile error CC: assert/lib_assert.c [asarm] (error #2179) modlib/modlib_globals.S 61: unexpected token type (char) encountered; expected type (identifier) .size \ globalNames , . - \ globalNames --------^ [asarm] (error #2179) modlib/modlib_globals.S 67: unexpected token type (char) encountered; expected type (identifier) .size \ nglobals , . - \ nglobals --------^ [asarm] (error #2179) modlib/modlib_globals.S 72: unexpected token type (char) encountered; expected type (identifier) .size \ global_table , . - \ global_table --------^ Signed-off-by: guoshichao --- libs/libc/modlib/modlib_globals.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/libc/modlib/modlib_globals.S b/libs/libc/modlib/modlib_globals.S index bdc8912271448..b65edfb51a461 100644 --- a/libs/libc/modlib/modlib_globals.S +++ b/libs/libc/modlib/modlib_globals.S @@ -16,7 +16,11 @@ .type SYMBOL(\ep), "object" .endm .macro SIZE ep +# if defined(__ghs__) + .size SYMBOL(ep), . - SYMBOL(ep) +# else .size SYMBOL(\ep), . - SYMBOL(\ep) +# endif .endm #else # define SYMBOL(s) _##s From fecc5091af8a6d2e48840c7b361ffbc2e1487314 Mon Sep 17 00:00:00 2001 From: yanghuatao Date: Tue, 23 Apr 2024 17:25:32 +0800 Subject: [PATCH 50/81] toolchain/ghs: Fix SP_DSB warnings "/mnt/yang/qixinwei_vela_warnings/nuttx/include/nuttx/spinlock.h", line 252: warning #76-D: argument to macro is empty SP_DSB(); ^ "/mnt/yang/qixinwei_vela_warnings/nuttx/include/nuttx/spinlock.h", line 261: warning #76-D: argument to macro is empty SP_DMB(); ^ "/mnt/yang/qixinwei_vela_warnings/nuttx/include/nuttx/spinlock.h", line 252: warning #76-D: argument to macro is empty SP_DSB(); ^ "/mnt/yang/qixinwei_vela_warnings/nuttx/include/nuttx/spinlock.h", line 261: warning #76-D: argument to macro is empty SP_DMB(); ^ "/mnt/yang/qixinwei_vela_warnings/nuttx/include/nuttx/spinlock.h", line 296: warning #76-D: argument to macro is empty SP_DSB(); ^ Signed-off-by: yanghuatao --- arch/arm/include/spinlock.h | 4 ++-- arch/arm64/include/spinlock.h | 4 ++-- arch/ceva/include/spinlock.h | 4 ++-- arch/risc-v/include/spinlock.h | 4 ++-- arch/x86_64/include/spinlock.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/include/spinlock.h b/arch/arm/include/spinlock.h index b9c53d94185f9..519cbae8f9be4 100644 --- a/arch/arm/include/spinlock.h +++ b/arch/arm/include/spinlock.h @@ -59,8 +59,8 @@ * all memory accesses are complete */ -#define SP_DSB(n) __asm__ __volatile__ ("dsb sy" : : : "memory") -#define SP_DMB(n) __asm__ __volatile__ ("dmb st" : : : "memory") +#define SP_DSB() __asm__ __volatile__ ("dsb sy" : : : "memory") +#define SP_DMB() __asm__ __volatile__ ("dmb st" : : : "memory") #ifdef CONFIG_ARM_HAVE_WFE_SEV #define SP_WFE() __asm__ __volatile__ ("wfe" : : : "memory") diff --git a/arch/arm64/include/spinlock.h b/arch/arm64/include/spinlock.h index 5eee94bb55c39..ced899e13b559 100644 --- a/arch/arm64/include/spinlock.h +++ b/arch/arm64/include/spinlock.h @@ -59,8 +59,8 @@ * all memory accesses are complete */ -#define SP_DSB(n) __asm__ __volatile__ ("dsb sy" : : : "memory") -#define SP_DMB(n) __asm__ __volatile__ ("dmb st" : : : "memory") +#define SP_DSB() __asm__ __volatile__ ("dsb sy" : : : "memory") +#define SP_DMB() __asm__ __volatile__ ("dmb st" : : : "memory") #define SP_WFE() __asm__ __volatile__ ("wfe" : : : "memory") #define SP_SEV() __asm__ __volatile__ ("sev" : : : "memory") diff --git a/arch/ceva/include/spinlock.h b/arch/ceva/include/spinlock.h index 13cc8fb1b29ff..de125f07bd53d 100644 --- a/arch/ceva/include/spinlock.h +++ b/arch/ceva/include/spinlock.h @@ -61,8 +61,8 @@ * */ -#define SP_DSB(n) up_dsb() -#define SP_DMB(n) up_dmb() +#define SP_DSB() up_dsb() +#define SP_DMB() up_dmb() /**************************************************************************** * Public Types diff --git a/arch/risc-v/include/spinlock.h b/arch/risc-v/include/spinlock.h index 427e1ef51fdeb..3bfe430338fcf 100644 --- a/arch/risc-v/include/spinlock.h +++ b/arch/risc-v/include/spinlock.h @@ -59,8 +59,8 @@ * */ -#define SP_DSB(n) __asm__ __volatile__ ("fence") -#define SP_DMB(n) __asm__ __volatile__ ("fence") +#define SP_DSB() __asm__ __volatile__ ("fence") +#define SP_DMB() __asm__ __volatile__ ("fence") /**************************************************************************** * Public Types diff --git a/arch/x86_64/include/spinlock.h b/arch/x86_64/include/spinlock.h index ac5b7d8b4f500..d315a32daf9b5 100644 --- a/arch/x86_64/include/spinlock.h +++ b/arch/x86_64/include/spinlock.h @@ -55,8 +55,8 @@ * */ -#define SP_DSB(n) __asm__ __volatile__ ("mfence") -#define SP_DMB(n) __asm__ __volatile__ ("mfence") +#define SP_DSB() __asm__ __volatile__ ("mfence") +#define SP_DMB() __asm__ __volatile__ ("mfence") /**************************************************************************** * Public Types From ce6d308cefdef44468e29145e8d529b78cc9297b Mon Sep 17 00:00:00 2001 From: anjiahao Date: Tue, 19 Dec 2023 20:00:28 +0800 Subject: [PATCH 51/81] armv8-m:fix log warnning armv8-m/arm_securefault.c:72:11: warning: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t' {aka 'long unsigned int'} [-Wformat=] 72 | sfalert("\tCFSR: %08x HFSR: %08x DFSR: %08x\n", getreg32(NVIC_CFAULTS), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: anjiahao --- arch/arm/src/armv8-m/arm_hardfault.c | 2 +- arch/arm/src/armv8-m/arm_memfault.c | 4 ++-- arch/arm/src/armv8-m/arm_securefault.c | 9 +++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/arm/src/armv8-m/arm_hardfault.c b/arch/arm/src/armv8-m/arm_hardfault.c index 83c9e3d5ed1e5..d69c4f599c1f9 100644 --- a/arch/arm/src/armv8-m/arm_hardfault.c +++ b/arch/arm/src/armv8-m/arm_hardfault.c @@ -162,7 +162,7 @@ int arm_hardfault(int irq, void *context, void *arg) hfalert("PANIC!!! Hard Fault!:"); hfalert("\tIRQ: %d regs: %p\n", irq, context); - hfalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08" + hfalert("\tBASEPRI: %08" PRIx8 " PRIMASK: %08" PRIx8 " IPSR: %08" PRIx32 " CONTROL: %08" PRIx32 "\n", getbasepri(), getprimask(), getipsr(), getcontrol()); hfalert("\tCFSR: %08" PRIx32 " HFSR: %08" PRIx32 " DFSR: %08" diff --git a/arch/arm/src/armv8-m/arm_memfault.c b/arch/arm/src/armv8-m/arm_memfault.c index e9bdbc580eb49..685e2657bd845 100644 --- a/arch/arm/src/armv8-m/arm_memfault.c +++ b/arch/arm/src/armv8-m/arm_memfault.c @@ -66,9 +66,9 @@ int arm_memfault(int irq, void *context, void *arg) mfalert("PANIC!!! Memory Management Fault:\n"); mfalert("\tIRQ: %d context: %p\n", irq, context); - mfalert("\tCFSR: %08x MMFAR: %08x\n", + mfalert("\tCFSR: %08" PRIx32 " MMFAR: %08" PRIx32 "\n", getreg32(NVIC_CFAULTS), getreg32(NVIC_MEMMANAGE_ADDR)); - mfalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08" + mfalert("\tBASEPRI: %08" PRIx32 " PRIMASK: %08" PRIx32 " IPSR: %08" PRIx32 " CONTROL: %08" PRIx32 "\n", getbasepri(), getprimask(), getipsr(), getcontrol()); diff --git a/arch/arm/src/armv8-m/arm_securefault.c b/arch/arm/src/armv8-m/arm_securefault.c index fb0f2a4736453..82285196eb0af 100644 --- a/arch/arm/src/armv8-m/arm_securefault.c +++ b/arch/arm/src/armv8-m/arm_securefault.c @@ -66,12 +66,13 @@ int arm_securefault(int irq, void *context, void *arg) sfalert("PANIC!!! Secure Fault:\n"); sfalert("\tIRQ: %d regs: %p\n", irq, context); - sfalert("\tBASEPRI: %08x PRIMASK: %08x IPSR: %08" + sfalert("\tBASEPRI: %08" PRIx8 " PRIMASK: %08" PRIx8 " IPSR: %08" PRIx32 " CONTROL: %08" PRIx32 "\n", getbasepri(), getprimask(), getipsr(), getcontrol()); - sfalert("\tCFSR: %08x HFSR: %08x DFSR: %08x\n", getreg32(NVIC_CFAULTS), - getreg32(NVIC_HFAULTS), getreg32(NVIC_DFAULTS)); - sfalert("\tBFAR: %08x AFSR: %08x SFAR: %08x\n", + sfalert("\tCFSR: %08" PRIx32 " HFSR: %08" PRIx32 " DFSR: %08" PRIx32 "\n", + getreg32(NVIC_CFAULTS), getreg32(NVIC_HFAULTS), + getreg32(NVIC_DFAULTS)); + sfalert("\tBFAR: %08" PRIx32 " AFSR: %08" PRIx32 " SFAR: %08" PRIx32 "\n", getreg32(NVIC_BFAULT_ADDR), getreg32(NVIC_AFAULTS), getreg32(SAU_SFAR)); From 8c8ccbf039df330181751096c081d30378b1b01c Mon Sep 17 00:00:00 2001 From: anjiahao Date: Tue, 9 Jan 2024 17:20:03 +0800 Subject: [PATCH 52/81] mps3-an547:support mps3-an547 reset Signed-off-by: anjiahao --- .../arm/mps/mps3-an547/configs/nsh/defconfig | 4 +- boards/arm/mps/mps3-an547/src/Makefile | 2 +- boards/arm/mps/mps3-an547/src/mps3_reset.c | 62 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 boards/arm/mps/mps3-an547/src/mps3_reset.c diff --git a/boards/arm/mps/mps3-an547/configs/nsh/defconfig b/boards/arm/mps/mps3-an547/configs/nsh/defconfig index 63f915480bdad..a98c6e92a2772 100644 --- a/boards/arm/mps/mps3-an547/configs/nsh/defconfig +++ b/boards/arm/mps/mps3-an547/configs/nsh/defconfig @@ -5,6 +5,7 @@ # You can then do "make savedefconfig" to generate a new defconfig file that includes your # modifications. # +# CONFIG_DEBUG_WARN is not set CONFIG_ARCH="arm" CONFIG_ARCH_BOARD="mps3-an547" CONFIG_ARCH_BOARD_MPS3_AN547=y @@ -12,6 +13,7 @@ CONFIG_ARCH_CHIP="mps" CONFIG_ARCH_CHIP_MPS3_AN547=y CONFIG_ARCH_CHIP_MPS=y CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y CONFIG_ARMV8M_SYSTICK=y CONFIG_BUILTIN=y CONFIG_CMSDK_UART0=y @@ -26,8 +28,6 @@ CONFIG_DEBUG_ASSERTIONS=y CONFIG_DEBUG_FEATURES=y CONFIG_DEBUG_SCHED=y CONFIG_DEBUG_SCHED_ERROR=y -CONFIG_DEBUG_SCHED_INFO=y -CONFIG_DEBUG_SCHED_WARN=y CONFIG_DEBUG_SYMBOLS=y CONFIG_DEFAULT_TASK_STACKSIZE=4096 CONFIG_DEV_ZERO=y diff --git a/boards/arm/mps/mps3-an547/src/Makefile b/boards/arm/mps/mps3-an547/src/Makefile index 59ae8876b5dfb..c137aed2dda5b 100644 --- a/boards/arm/mps/mps3-an547/src/Makefile +++ b/boards/arm/mps/mps3-an547/src/Makefile @@ -20,6 +20,6 @@ include $(TOPDIR)/Make.defs -CSRCS = mps3_bringup.c +CSRCS = mps3_bringup.c mps3_reset.c include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/mps/mps3-an547/src/mps3_reset.c b/boards/arm/mps/mps3-an547/src/mps3_reset.c new file mode 100644 index 0000000000000..5b6bb37118d95 --- /dev/null +++ b/boards/arm/mps/mps3-an547/src/mps3_reset.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * boards/arm/mps/mps3-an547/src/mps3_reset.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_BOARDCTL_RESET + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_reset + * + * Description: + * Reset board. Support for this function is required by board-level + * logic if CONFIG_BOARDCTL_RESET is selected. + * + * Input Parameters: + * status - Status information provided with the reset event. This + * meaning of this status information is board-specific. If not + * used by a board, the value zero may be provided in calls to + * board_reset(). + * + * Returned Value: + * If this function returns, then it was not possible to power-off the + * board due to some constraints. The return value int this case is a + * board-specific reason for the failure to shutdown. + * + ****************************************************************************/ + +int board_reset(int status) +{ + up_systemreset(); + return 0; +} + +#endif /* CONFIG_BOARDCTL_RESET */ From aee17d6cc2cf19876a1917c049f47cf1dae3a393 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Fri, 5 Jan 2024 15:51:06 +0800 Subject: [PATCH 53/81] kasan:fix bug write error is recognized as read error Signed-off-by: anjiahao --- mm/kasan/kasan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c index b8a4843abd724..8e0aebc10eb80 100644 --- a/mm/kasan/kasan.c +++ b/mm/kasan/kasan.c @@ -221,7 +221,7 @@ static inline void kasan_check_report(FAR const void *addr, size_t size, { if (kasan_is_poisoned(addr, size)) { - kasan_report(addr, size, false, return_address); + kasan_report(addr, size, is_write, return_address); } } From 5f4c1721ff4d2685d2a4251f48b6687ba15bd153 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Wed, 31 Jan 2024 21:45:26 +0800 Subject: [PATCH 54/81] coredump:support coredump aligned access registers Signed-off-by: anjiahao --- binfmt/libelf/libelf_coredump.c | 31 ++++++++++++++++++++++++++++--- include/elf.h | 6 ++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/binfmt/libelf/libelf_coredump.c b/binfmt/libelf/libelf_coredump.c index 725992a9ae15a..f5f5ccd2c452e 100644 --- a/binfmt/libelf/libelf_coredump.c +++ b/binfmt/libelf/libelf_coredump.c @@ -423,9 +423,34 @@ static void elf_emit_memory(FAR struct elf_dumpinfo_s *cinfo, int memsegs) for (i = 0; i < memsegs; i++) { - elf_emit(cinfo, (FAR void *)cinfo->regions[i].start, - cinfo->regions[i].end - - cinfo->regions[i].start); + if (cinfo->regions[i].flags & PF_REGISTER) + { + FAR uintptr_t *start = (FAR uintptr_t *)cinfo->regions[i].start; + FAR uintptr_t *end = (FAR uintptr_t *)cinfo->regions[i].end; + uintptr_t buf[64]; + size_t offset = 0; + + while (start < end) + { + buf[offset++] = *start++; + + if (offset % (sizeof(buf) / sizeof(uintptr_t)) == 0) + { + elf_emit(cinfo, buf, sizeof(buf)); + offset = 0; + } + } + + if (offset != 0) + { + elf_emit(cinfo, buf, offset * sizeof(uintptr_t)); + } + } + else + { + elf_emit(cinfo, (FAR void *)cinfo->regions[i].start, + cinfo->regions[i].end - cinfo->regions[i].start); + } /* Align to page */ diff --git a/include/elf.h b/include/elf.h index fbd8e5391a385..5de67bf2f2210 100644 --- a/include/elf.h +++ b/include/elf.h @@ -233,6 +233,12 @@ #define PF_X 1 /* Execute */ #define PF_W 2 /* Write */ #define PF_R 4 /* Read */ +#define PF_MASKOS 0x0ff00000 /* All bits included in the PF_MASKOS + * mask are reserved for operating system-specific + * semantics. + */ +#define PF_REGISTER 0x00100000 /* Register, need pointer aligned access */ + #define PF_MASKPROC 0xf0000000 /* Unspecified */ /* Figure 5-10: Dynamic Array Tags, d_tag */ From 8d0d1f7571487585b554facda2f414da48decf3c Mon Sep 17 00:00:00 2001 From: anjiahao Date: Fri, 2 Feb 2024 11:20:52 +0800 Subject: [PATCH 55/81] coredump:Add coredump success log printing to remind you to use coreudmp Signed-off-by: anjiahao --- sched/misc/coredump.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index fcf1a8ca16c87..74c25fa9a31a9 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -115,7 +115,7 @@ static void coredump_dump_blkdev(pid_t pid) if (g_blockstream.inode == NULL) { - _alert("Coredump Device Not Found\n"); + _alert("Coredump device not found\n"); return; } @@ -123,14 +123,15 @@ static void coredump_dump_blkdev(pid_t pid) g_blockinfo, g_blockstream.geo.geo_nsectors - 1, 1); if (ret < 0) { - _alert("Coredump Device Read Fail\n"); + _alert("Coredump information read fail\n"); return; } info = (FAR struct coredump_info_s *)g_blockinfo; if (info->magic == COREDUMP_MAGIC) { - _alert("Coredump Device Already Used\n"); + _alert("Coredump exists in %s, skip\n", + CONFIG_BOARD_COREDUMP_BLKDEV_PATH); return; } @@ -143,7 +144,7 @@ static void coredump_dump_blkdev(pid_t pid) ret = core_dump(g_regions, stream, pid); if (ret < 0) { - _alert("Coredump Fail\n"); + _alert("Coredump fail\n"); return; } @@ -151,8 +152,16 @@ static void coredump_dump_blkdev(pid_t pid) info->size = g_blockstream.common.nput; info->time = time(NULL); uname(&info->name); - g_blockstream.inode->u.i_bops->write(g_blockstream.inode, + ret = g_blockstream.inode->u.i_bops->write(g_blockstream.inode, (FAR void *)info, g_blockstream.geo.geo_nsectors - 1, 1); + if (ret < 0) + { + _alert("Coredump information write fail\n"); + return; + } + + _alert("Finish coredump, write %d bytes to %s\n", + info->size, CONFIG_BOARD_COREDUMP_BLKDEV_PATH); } #endif @@ -174,7 +183,7 @@ int coredump_initialize(void) g_regions = alloc_memory_region(CONFIG_BOARD_MEMORY_RANGE); if (g_regions == NULL) { - _alert("Memory Region Alloc Fail\n"); + _alert("Coredump memory region alloc fail\n"); return -ENOMEM; } } @@ -184,7 +193,7 @@ int coredump_initialize(void) CONFIG_BOARD_COREDUMP_BLKDEV_PATH); if (ret < 0) { - _alert("%s Coredump Device Not Found\n", + _alert("%s Coredump device not found\n", CONFIG_BOARD_COREDUMP_BLKDEV_PATH); free_memory_region(g_regions); g_regions = NULL; @@ -194,7 +203,7 @@ int coredump_initialize(void) g_blockinfo = kmm_malloc(g_blockstream.geo.geo_sectorsize); if (g_blockinfo == NULL) { - _alert("Coredump Device Memory Alloc Fail\n"); + _alert("Coredump device memory alloc fail\n"); free_memory_region(g_regions); g_regions = NULL; lib_blkoutstream_close(&g_blockstream); From 2ff2b8243773df3a56d535635b898a06f3f8c0f6 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Tue, 30 Jan 2024 16:08:04 +0800 Subject: [PATCH 56/81] coredump:coredump_set_memory_region to set memory region Signed-off-by: anjiahao --- {sched/misc => include/nuttx}/coredump.h | 19 +++++++++++++++---- sched/init/nx_bringup.c | 2 +- sched/misc/assert.c | 2 +- sched/misc/coredump.c | 22 +++++++++++++++++++--- 4 files changed, 36 insertions(+), 9 deletions(-) rename {sched/misc => include/nuttx}/coredump.h (80%) diff --git a/sched/misc/coredump.h b/include/nuttx/coredump.h similarity index 80% rename from sched/misc/coredump.h rename to include/nuttx/coredump.h index 32dc3a6c2c674..8d2cf207a39e9 100644 --- a/sched/misc/coredump.h +++ b/include/nuttx/coredump.h @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/misc/coredump.h + * include/nuttx/coredump.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,19 +18,30 @@ * ****************************************************************************/ -#ifndef __SCHED_MISC_COREDUMP_H -#define __SCHED_MISC_COREDUMP_H +#ifndef __INCLUDE_NUTTX_COREDUMP_H +#define __INCLUDE_NUTTX_COREDUMP_H /**************************************************************************** * Included Files ****************************************************************************/ +#include #include /**************************************************************************** * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: coredump_set_memory_region + * + * Description: + * Set do coredump memory region. + * + ****************************************************************************/ + +int coredump_set_memory_region(FAR struct memory_region_s *region); + /**************************************************************************** * Name: coredump_initialize * @@ -55,4 +66,4 @@ int coredump_initialize(void); void coredump_dump(pid_t pid); -#endif /* __SCHED_MISC_COREDUMP_H */ +#endif /* __INCLUDE_NUTTX_COREDUMP_H */ diff --git a/sched/init/nx_bringup.c b/sched/init/nx_bringup.c index 152dcc8ab236e..1affea836e693 100644 --- a/sched/init/nx_bringup.c +++ b/sched/init/nx_bringup.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,6 @@ #include "sched/sched.h" #include "wqueue/wqueue.h" #include "init/init.h" -#include "misc/coredump.h" #ifdef CONFIG_ETC_ROMFS # include diff --git a/sched/misc/assert.c b/sched/misc/assert.c index fa9b8c8916577..2500b0c2bb4b8 100644 --- a/sched/misc/assert.c +++ b/sched/misc/assert.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,6 @@ #include "irq/irq.h" #include "sched/sched.h" #include "group/group.h" -#include "misc/coredump.h" /**************************************************************************** * Pre-processor Definitions diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index 74c25fa9a31a9..c8c4f920db871 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -23,11 +23,10 @@ ****************************************************************************/ #include +#include #include #include -#include "misc/coredump.h" - /**************************************************************************** * Private Data ****************************************************************************/ @@ -165,6 +164,22 @@ static void coredump_dump_blkdev(pid_t pid) } #endif +/**************************************************************************** + * Name: coredump_set_memory_region + * + * Description: + * Set do coredump memory region. + * + ****************************************************************************/ + +int coredump_set_memory_region(FAR struct memory_region_s *region) +{ + /* Not free g_regions, because allow call this fun when crash */ + + g_regions = region; + return 0; +} + /**************************************************************************** * Name: coredump_initialize * @@ -180,7 +195,8 @@ int coredump_initialize(void) if (CONFIG_BOARD_MEMORY_RANGE[0] != '\0') { - g_regions = alloc_memory_region(CONFIG_BOARD_MEMORY_RANGE); + coredump_set_memory_region( + alloc_memory_region(CONFIG_BOARD_MEMORY_RANGE)); if (g_regions == NULL) { _alert("Coredump memory region alloc fail\n"); From 6db85498a2eb4731c3b28c25873df7b10d2febd5 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Mon, 29 Jul 2024 16:10:53 +0800 Subject: [PATCH 57/81] riscv/qemu-rv: add cluster PLIC/CLINT configs This adds cluster specific configs for PLIC, CLINT and ACLINT devices. Signed-off-by: Yanfeng Liu --- arch/risc-v/src/qemu-rv/Kconfig | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/qemu-rv/Kconfig b/arch/risc-v/src/qemu-rv/Kconfig index 5d5b8b2dd41ec..550b854c57953 100644 --- a/arch/risc-v/src/qemu-rv/Kconfig +++ b/arch/risc-v/src/qemu-rv/Kconfig @@ -40,4 +40,24 @@ config ARCH_CHIP_QEMU_RV_ISA_V default n select ARCH_RV_ISA_V -endif +config ARCH_CHIP_QEMU_RV_CLUSTER + bool "Enable cluster support" + default n + +if ARCH_CHIP_QEMU_RV_CLUSTER + +config ARCH_CHIP_QEMU_RV_PLIC + hex "Base address of PLIC device" + default 0xc000000 + +config ARCH_CHIP_QEMU_RV_CLINT + hex "Base address of CLINT device" + default 0x2000000 + +config ARCH_CHIP_QEMU_RV_ACLINT + hex "Base address of ACLINT device" + default 0x2f00000 + +endif # ARCH_CHIP_QEMU_RV_CLUSTER + +endif # ARCH_CHIP_QEMU_RV From f5b2fc371e87a0c41b1429e2c0370b44e347d1ba Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Mon, 29 Jul 2024 15:13:56 +0800 Subject: [PATCH 58/81] riscv/qemu-rv: use cluster PLIC/CLINT configs This uses cluster speficic PLIC, CLINT and ACLINT devices in NuttX. Signed-off-by: Yanfeng Liu --- .../src/qemu-rv/hardware/qemu_rv_memorymap.h | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h b/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h index 420cefefe9f54..a2c372f08fbcd 100644 --- a/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h +++ b/arch/risc-v/src/qemu-rv/hardware/qemu_rv_memorymap.h @@ -27,11 +27,25 @@ /* Register Base Address ****************************************************/ -#define QEMU_RV_CLINT_BASE 0x02000000 -#define QEMU_RV_ACLINT_BASE 0x02f00000 -#define QEMU_RV_PLIC_BASE 0x0c000000 +#ifdef CONFIG_ARCH_CHIP_QEMU_RV_PLIC +# define QEMU_RV_PLIC_BASE CONFIG_ARCH_CHIP_QEMU_RV_PLIC +#else +# define QEMU_RV_PLIC_BASE 0xc000000 +#endif + +#ifdef CONFIG_ARCH_CHIP_QEMU_RV_CLINT +# define QEMU_RV_CLINT_BASE CONFIG_ARCH_CHIP_QEMU_RV_CLINT +#else +# define QEMU_RV_CLINT_BASE 0x2000000 +#endif + +#ifdef CONFIG_ARCH_CHIP_QEMU_RV_ACLINT +# define QEMU_RV_ACLINT_BASE CONFIG_ARCH_CHIP_QEMU_RV_ACLINT +#else +# define QEMU_RV_ACLINT_BASE 0x2f00000 +#endif -#define QEMU_RV_RESET_BASE 0x100000 +#define QEMU_RV_RESET_BASE 0x100000 #ifdef CONFIG_ARCH_USE_S_MODE # define QEMU_RV_APLIC_BASE 0x0d000000 From 155517b5fc8c69da94767ed62b686a46edc19817 Mon Sep 17 00:00:00 2001 From: simbit18 <101105604+simbit18@users.noreply.github.com> Date: Mon, 12 Aug 2024 13:39:50 +0200 Subject: [PATCH 59/81] arch/sim/src/cmake/Toolchain.cmake: macOS fix unknown options: --gc-sections fix ld: unknown options: --gc-sections added -> add_link_options(-Wl,-dead_strip) --- arch/sim/src/cmake/Toolchain.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/sim/src/cmake/Toolchain.cmake b/arch/sim/src/cmake/Toolchain.cmake index c1caedd3c6e39..7fb1989fcf4c2 100644 --- a/arch/sim/src/cmake/Toolchain.cmake +++ b/arch/sim/src/cmake/Toolchain.cmake @@ -97,7 +97,11 @@ else() endif() if(CONFIG_DEBUG_OPT_UNUSED_SECTIONS) - add_link_options(-Wl,--gc-sections) + if(APPLE) + add_link_options(-Wl,-dead_strip) + else() + add_link_options(-Wl,--gc-sections) + endif() add_compile_options(-ffunction-sections -fdata-sections) endif() From a1f9a6624e865aee7100b368f1b127f17d934e36 Mon Sep 17 00:00:00 2001 From: zhangshuai39 Date: Fri, 26 Jul 2024 18:13:34 +0800 Subject: [PATCH 60/81] net/tun:Remove unused variables in read & write Signed-off-by: zhangshuai39 --- drivers/net/tun.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9a81cd7e10609..9d84b959daee5 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -969,9 +969,8 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) { FAR struct tun_device_s *priv = filep->f_priv; - ssize_t nwritten = 0; uint8_t llhdrlen; - int ret; + ssize_t ret; if (priv == NULL || buflen > CONFIG_NET_TUN_PKTSIZE) { @@ -989,7 +988,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, ret = nxmutex_lock(&priv->lock); if (ret < 0) { - return nwritten == 0 ? (ssize_t)ret : nwritten; + return ret; } /* Check if there are free space to write */ @@ -1002,7 +1001,6 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, priv->dev.d_buf = NULL; if (ret < 0) { - nwritten = (nwritten == 0) ? ret : nwritten; net_unlock(); break; } @@ -1011,7 +1009,6 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, buflen, -llhdrlen, false); if (ret < 0) { - nwritten = (nwritten == 0) ? ret : nwritten; net_unlock(); break; } @@ -1021,7 +1018,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, tun_net_receive(priv); net_unlock(); - nwritten = buflen; + ret = buflen; break; } @@ -1029,7 +1026,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, if ((filep->f_oflags & O_NONBLOCK) != 0) { - nwritten = -EAGAIN; + ret = -EAGAIN; break; } @@ -1039,7 +1036,7 @@ static ssize_t tun_write(FAR struct file *filep, FAR const char *buffer, } nxmutex_unlock(&priv->lock); - return nwritten; + return ret; } /**************************************************************************** @@ -1050,9 +1047,8 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { FAR struct tun_device_s *priv = filep->f_priv; - ssize_t nread = 0; uint8_t llhdrlen; - int ret; + ssize_t ret; if (priv == NULL) { @@ -1070,7 +1066,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, ret = nxmutex_lock(&priv->lock); if (ret < 0) { - return nread == 0 ? (ssize_t)ret : nread; + return ret; } /* Check if there are data to read in write buffer */ @@ -1079,13 +1075,13 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, { if (buflen < priv->write_d_len) { - nread = -EINVAL; + ret = -EINVAL; break; } iob_copyout((FAR uint8_t *)buffer, priv->write_buf, priv->write_d_len, -llhdrlen); - nread = priv->write_d_len; + ret = priv->write_d_len; iob_free_chain(priv->write_buf); priv->write_buf = NULL; @@ -1102,13 +1098,13 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, { if (buflen < priv->read_d_len) { - nread = -EINVAL; + ret = -EINVAL; break; } iob_copyout((FAR uint8_t *)buffer, priv->read_buf, priv->read_d_len, -llhdrlen); - nread = priv->read_d_len; + ret = priv->read_d_len; iob_free_chain(priv->read_buf); priv->read_buf = NULL; @@ -1124,7 +1120,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, if ((filep->f_oflags & O_NONBLOCK) != 0) { - nread = -EAGAIN; + ret = -EAGAIN; break; } @@ -1134,7 +1130,7 @@ static ssize_t tun_read(FAR struct file *filep, FAR char *buffer, } nxmutex_unlock(&priv->lock); - return nread; + return ret; } /**************************************************************************** From af10e1b470571e16807f00b0702119e36b109410 Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Tue, 21 May 2024 21:37:28 +0800 Subject: [PATCH 61/81] lib_ustname:keep the incrementally compiled version time updated fix phoney target mismatch issue, always rebuild ustname Signed-off-by: xuxin19 --- libs/libc/misc/CMakeLists.txt | 8 ++++++++ libs/libc/misc/Make.defs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libs/libc/misc/CMakeLists.txt b/libs/libc/misc/CMakeLists.txt index d9ae54b35f37f..3beabec7f1ddc 100644 --- a/libs/libc/misc/CMakeLists.txt +++ b/libs/libc/misc/CMakeLists.txt @@ -112,4 +112,12 @@ if(CONFIG_FDCHECK) list(APPEND SRCS lib_fdcheck.c) endif() +if(NOT CONFIG_LIBC_UNAME_DISABLE_TIMESTAMP) + add_custom_target( + always_rebuild_lib_utsname + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_SOURCE_DIR}/lib_utsname.c) + + add_dependencies(c always_rebuild_lib_utsname) +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs index c3d19570f7f38..c5a1bda0087b3 100644 --- a/libs/libc/misc/Make.defs +++ b/libs/libc/misc/Make.defs @@ -80,7 +80,7 @@ endif # add lib_utsname.o to phony target for force rebuild #if !defined(CONFIG_LIBC_UNAME_DISABLE_TIMESTAMP) -.PHONY: lib_utsname$(OBJEXT) +.PHONY: bin$(DELIM)lib_utsname$(OBJEXT) kbin$(DELIM)lib_utsname$(OBJEXT) #endif # Add the misc directory to the build From cd46d274898377befb0fb0a48433b38969f91ce1 Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Mon, 17 Jun 2024 16:46:37 +0800 Subject: [PATCH 62/81] cmake:Remove Unix-specific code and replace it with cmake script to support cross-platform the Unix-specific commands used in the CMake implementation of savedefconfig are not supported on the Windows platform, which will cause compatibility issues. replace it with CMake implementation, which can be cross-platform and has been verified on Windows. Signed-off-by: xuxin19 --- cmake/menuconfig.cmake | 35 ++----------------- cmake/savedefconfig.cmake | 72 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 33 deletions(-) create mode 100644 cmake/savedefconfig.cmake diff --git a/cmake/menuconfig.cmake b/cmake/menuconfig.cmake index 66d45bad95919..97e130712b4ba 100644 --- a/cmake/menuconfig.cmake +++ b/cmake/menuconfig.cmake @@ -68,41 +68,10 @@ add_custom_target( savedefconfig COMMAND ${CMAKE_COMMAND} -E env ${KCONFIG_ENV} savedefconfig --out ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND grep "CONFIG_ARCH=" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND grep "^CONFIG_ARCH_CHIP_" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "CONFIG_ARCH_CHIP=" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "CONFIG_ARCH_BOARD=" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "^CONFIG_ARCH_CUSTOM" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND grep "^CONFIG_ARCH_BOARD_CUSTOM" ${CMAKE_BINARY_DIR}/.config >> - ${CMAKE_BINARY_DIR}/defconfig.tmp || true - COMMAND export LC_ALL=C && cat ${CMAKE_BINARY_DIR}/defconfig.tmp | sort | uniq - > ${CMAKE_BINARY_DIR}/sortedconfig.tmp || true - COMMAND echo "\\#" > ${CMAKE_BINARY_DIR}/warning.tmp || true - COMMAND echo "\\# This file is autogenerated: PLEASE DO NOT EDIT IT." >> - ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND echo "\\#" >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND - echo - "\\# You can use \\\"make menuconfig\\\" to make any modifications to the installed .config file." - >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND - echo - "\\# You can then do \\\"make savedefconfig\\\" to generate a new defconfig file that includes your" - >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND echo "\\# modifications." >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND echo "\\#" >> ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND cat ${CMAKE_BINARY_DIR}/warning.tmp - ${CMAKE_BINARY_DIR}/sortedconfig.tmp > ${CMAKE_BINARY_DIR}/defconfig + COMMAND ${CMAKE_COMMAND} -P ${NUTTX_DIR}/cmake/savedefconfig.cmake + ${CMAKE_BINARY_DIR}/.config ${CMAKE_BINARY_DIR}/defconfig.tmp COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/defconfig ${NUTTX_DEFCONFIG} - COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/warning.tmp - COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/defconfig.tmp - COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/sortedconfig.tmp WORKING_DIRECTORY ${NUTTX_DIR}) # utility target to restore .config from board's defconfig diff --git a/cmake/savedefconfig.cmake b/cmake/savedefconfig.cmake new file mode 100644 index 0000000000000..2aa6fd6a15b0f --- /dev/null +++ b/cmake/savedefconfig.cmake @@ -0,0 +1,72 @@ +# ############################################################################## +# cmake/savedefconfig.cmake +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you 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. +# +# ############################################################################## + +include(cmake/nuttx_kconfig.cmake) + +set(SOURCE_FILE ${CMAKE_ARGV3}) +set(TARGET_FILE ${CMAKE_ARGV4}) + +file(STRINGS ${SOURCE_FILE} ConfigContents) +encode_brackets(ConfigContents) + +foreach(NameAndValue ${ConfigContents}) + decode_brackets(NameAndValue) + encode_semicolon(NameAndValue) + if("${NameAndValue}" MATCHES "CONFIG_ARCH=" + OR "${NameAndValue}" MATCHES "^CONFIG_ARCH_CHIP_" + OR "${NameAndValue}" MATCHES "CONFIG_ARCH_CHIP=" + OR "${NameAndValue}" MATCHES "CONFIG_ARCH_BOARD=" + OR "${NameAndValue}" MATCHES "^CONFIG_ARCH_CUSTOM" + OR "${NameAndValue}" MATCHES "^CONFIG_ARCH_BOARD_CUSTOM") + decode_semicolon(Value) + file(APPEND ${TARGET_FILE} "${NameAndValue}\n") + endif() +endforeach() + +get_filename_component(BINARY_DIR "${TARGET_FILE}" DIRECTORY) + +set(OUTPUT_FILE ${BINARY_DIR}/defconfig) + +# cmake-format: off +file(WRITE ${OUTPUT_FILE} "") +file(APPEND ${OUTPUT_FILE} "\#\n") +file(APPEND ${OUTPUT_FILE} "\# This file is autogenerated: PLEASE DO NOT EDIT IT.\n") +file(APPEND ${OUTPUT_FILE} "\#\n") +file(APPEND ${OUTPUT_FILE} "\# You can use \"make menuconfig\" to make any modifications to the installed .config file.\n") +file(APPEND ${OUTPUT_FILE} "\# You can then do \"make savedefconfig\" to generate a new defconfig file that includes your\n") +file(APPEND ${OUTPUT_FILE} "\# modifications.\n") +file(APPEND ${OUTPUT_FILE} "\#\n") +file(READ ${TARGET_FILE} CONTENTS) +# cmake-format: on +encode_brackets(CONTENTS) +encode_semicolon(CONTENTS) + +string(REGEX MATCHALL "[^\n]+" LINES ${CONTENTS}) + +list(REMOVE_DUPLICATES LINES) +list(SORT LINES) + +foreach(LINE IN LISTS LINES) + decode_brackets(LINE) + decode_semicolon(LINE) + file(APPEND ${OUTPUT_FILE} "${LINE}\n") +endforeach() + +execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${TARGET_FILE}) From b073b3efc15f11c1e69845d3fccc2e0c2c589538 Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Tue, 7 May 2024 17:09:28 +0800 Subject: [PATCH 63/81] cmake:bugfix SIM_ASAN cannot automatically link libasan in cmake build Signed-off-by: xuxin19 --- arch/sim/src/cmake/Toolchain.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sim/src/cmake/Toolchain.cmake b/arch/sim/src/cmake/Toolchain.cmake index 7fb1989fcf4c2..44533362e6c52 100644 --- a/arch/sim/src/cmake/Toolchain.cmake +++ b/arch/sim/src/cmake/Toolchain.cmake @@ -75,6 +75,7 @@ endif() if(CONFIG_SIM_ASAN) add_compile_options(-fsanitize=address) + add_link_options(-fsanitize=address) add_compile_options(-fsanitize-address-use-after-scope) add_compile_options(-fsanitize=pointer-compare) add_compile_options(-fsanitize=pointer-subtract) From 7502c9c334652a5fd7417b739d9b200e352003cd Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Tue, 23 Apr 2024 17:07:22 +0800 Subject: [PATCH 64/81] cmake:bugfix add sched include search path for fs Signed-off-by: xuxin19 --- fs/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/CMakeLists.txt b/fs/CMakeLists.txt index 57e0fb19e0a75..cc876d4c17b5f 100644 --- a/fs/CMakeLists.txt +++ b/fs/CMakeLists.txt @@ -19,4 +19,5 @@ # ############################################################################## nuttx_add_kernel_library(fs fs_initialize.c) nuttx_add_subdirectory() -target_include_directories(fs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(fs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${NUTTX_DIR}/sched) From 819685fbec0ad289e0aeb3e646615a049762dea7 Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Mon, 20 May 2024 18:22:31 +0800 Subject: [PATCH 65/81] cmake:bugfix enable ARCH_STRING_FUNCTION CMake build fail Signed-off-by: xuxin19 --- libs/libc/machine/arm/armv7-a/CMakeLists.txt | 6 ++-- libs/libc/machine/arm/armv7-m/CMakeLists.txt | 20 ++++++++---- libs/libc/machine/arm/armv7-r/CMakeLists.txt | 32 ++++++++++++++++++-- libs/libc/machine/arm/armv8-m/CMakeLists.txt | 18 ++++++----- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/libs/libc/machine/arm/armv7-a/CMakeLists.txt b/libs/libc/machine/arm/armv7-a/CMakeLists.txt index 05bd859ebee7b..7744719bb994f 100644 --- a/libs/libc/machine/arm/armv7-a/CMakeLists.txt +++ b/libs/libc/machine/arm/armv7-a/CMakeLists.txt @@ -18,8 +18,6 @@ # # ############################################################################## -set(SRCS arch_elf.c) - if(CONFIG_ARCH_TOOLCHAIN_GNU) set(ARCH_TOOLCHAIN_DIR gnu) endif() @@ -48,4 +46,8 @@ if(CONFIG_ARMV7A_STRLEN) list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() +if(CONFIG_LIBC_ARCH_ELF) + list(APPEND SRCS arch_elf.c) +endif() + target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/machine/arm/armv7-m/CMakeLists.txt b/libs/libc/machine/arm/armv7-m/CMakeLists.txt index e5395a486ea4a..10f7b2b9af231 100644 --- a/libs/libc/machine/arm/armv7-m/CMakeLists.txt +++ b/libs/libc/machine/arm/armv7-m/CMakeLists.txt @@ -20,28 +20,36 @@ set(SRCS) +if(CONFIG_ARCH_TOOLCHAIN_GNU) + set(ARCH_TOOLCHAIN_DIR gnu) +endif() + +if(CONFIG_ARMV7M_MEMCHR) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memchr.S) +endif() + if(CONFIG_ARMV7M_MEMCPY) - list(APPEND SRCS gnu/arch_memcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memcpy.S) endif() if(CONFIG_ARMV7M_MEMSET) - list(APPEND SRCS arch_memset.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memset.S) endif() if(CONFIG_ARMV7M_MEMMOVE) - list(APPEND SRCS arch_memmove.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memmove.S) endif() if(CONFIG_ARMV7M_STRCMP) - list(APPEND SRCS arch_strcmp.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcmp.S) endif() if(CONFIG_ARMV7M_STRCPY) - list(APPEND SRCS arch_strcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcpy.S) endif() if(CONFIG_ARMV7M_STRLEN) - list(APPEND SRCS arch_strlen.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() if(CONFIG_LIBC_ARCH_ELF) diff --git a/libs/libc/machine/arm/armv7-r/CMakeLists.txt b/libs/libc/machine/arm/armv7-r/CMakeLists.txt index 62ec1bed478f4..dbbedfb4da9d4 100644 --- a/libs/libc/machine/arm/armv7-r/CMakeLists.txt +++ b/libs/libc/machine/arm/armv7-r/CMakeLists.txt @@ -18,10 +18,38 @@ # # ############################################################################## +set(SRCS) + +if(CONFIG_ARCH_TOOLCHAIN_GNU) + set(ARCH_TOOLCHAIN_DIR gnu) +endif() + +if(CONFIG_ARMV7R_MEMCHR) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memchr.S) +endif() + if(CONFIG_ARMV7R_MEMCPY) - target_sources(c PRIVATE gnu/arch_memcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memcpy.S) +endif() + +if(CONFIG_ARMV7R_MEMSET) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memset.S) +endif() + +if(CONFIG_ARMV7R_MEMMOVE) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memmove.S) +endif() + +if(CONFIG_ARMV7R_STRCMP) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcmp.S) +endif() + +if(CONFIG_ARMV7R_STRLEN) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() if(CONFIG_LIBC_ARCH_ELF) - target_sources(c PRIVATE arch_elf.c) + list(APPEND SRCS arch_elf.c) endif() + +target_sources(c PRIVATE ${SRCS}) diff --git a/libs/libc/machine/arm/armv8-m/CMakeLists.txt b/libs/libc/machine/arm/armv8-m/CMakeLists.txt index 71cc3a774df7e..809f82fe6e125 100644 --- a/libs/libc/machine/arm/armv8-m/CMakeLists.txt +++ b/libs/libc/machine/arm/armv8-m/CMakeLists.txt @@ -20,36 +20,40 @@ set(SRCS) +if(CONFIG_ARCH_TOOLCHAIN_GNU) + set(ARCH_TOOLCHAIN_DIR gnu) +endif() + if(CONFIG_LIBC_ARCH_ELF) list(APPEND SRCS arch_elf.c) endif() if(CONFIG_ARMV8M_MEMCHR) - list(APPEND SRCS arch_memchr.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memchr.S) endif() if(CONFIG_ARMV8M_MEMCPY) - list(APPEND SRCS arch_memcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memcpy.S) endif() if(CONFIG_ARMV8M_MEMSET) - list(APPEND SRCS arch_memset.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memset.S) endif() if(CONFIG_ARMV8M_MEMMOVE) - list(APPEND SRCS arch_memmove.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_memmove.S) endif() if(CONFIG_ARMV8M_STRCMP) - list(APPEND SRCS arch_strcmp.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcmp.S) endif() if(CONFIG_ARMV8M_STRCPY) - list(APPEND SRCS arch_strcpy.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strcpy.S) endif() if(CONFIG_ARMV8M_STRLEN) - list(APPEND SRCS arch_strlen.S) + list(APPEND SRCS ${ARCH_TOOLCHAIN_DIR}/arch_strlen.S) endif() target_sources(c PRIVATE ${SRCS}) From 41dba46c1d721590f69f5ccf59d7a00462056776 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Wed, 14 Aug 2024 11:47:42 +0800 Subject: [PATCH 66/81] arch/riscv: fix IRQ_SOFT for non-SMP This fixes software interrupt number for non-SMP cases Signed-off-by: Yanfeng Liu --- arch/risc-v/src/common/riscv_exception.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/risc-v/src/common/riscv_exception.c b/arch/risc-v/src/common/riscv_exception.c index 0ff9af828a47d..6c296f67ef8df 100644 --- a/arch/risc-v/src/common/riscv_exception.c +++ b/arch/risc-v/src/common/riscv_exception.c @@ -304,6 +304,6 @@ void riscv_exception_attach(void) #ifdef CONFIG_SMP irq_attach(RISCV_IRQ_SOFT, riscv_pause_handler, NULL); #else - irq_attach(RISCV_IRQ_MSOFT, riscv_exception, NULL); + irq_attach(RISCV_IRQ_SOFT, riscv_exception, NULL); #endif } From b325ae639156eca231474fa32a2f1e8b841b9214 Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Tue, 28 May 2024 16:45:43 +0800 Subject: [PATCH 67/81] cmake: add_application supports only registration but not compilation for sources that have implemented multiple prog_main, there is a situation where you don't need to add source files but need to register. the add_application method is enhanced so that it can be registered without entering SRCS. Signed-off-by: xuxin19 --- cmake/nuttx_add_application.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/nuttx_add_application.cmake b/cmake/nuttx_add_application.cmake index fc12f28518b1d..4701987c6b43f 100644 --- a/cmake/nuttx_add_application.cmake +++ b/cmake/nuttx_add_application.cmake @@ -161,6 +161,10 @@ function(nuttx_add_application) PRIVATE $>) endif() + else() + set(TARGET "apps_${NAME}") + add_custom_target(${TARGET}) + set_property(GLOBAL APPEND PROPERTY NUTTX_APPS_ONLY_REGISTER ${TARGET}) endif() # store parameters into properties (used during builtin list generation) From 4cd66fa7cc0bfb686b1b1e7e24c7401e0ec066a0 Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Thu, 13 Jun 2024 15:32:30 +0800 Subject: [PATCH 68/81] windows sim:add CONFIG_SYSTEM_TIME64 fix windows build error nuttx\arch\sim\src\sim\sim_checkhostfstypes.c(80,1): error C2338: static_assert failed: 'sizeof(((struct nuttx_stat_s *)0)->st_atim) == sizeof(((struct stat *)0)->st_atim)' nuttx\arch\sim\src\sim\sim_checkhostfstypes.c(81,1): error C2338: static_assert failed: 'offsetof(struct nuttx_stat_s, st_mtim) == offsetof(struct stat, st_mtim)' nuttx\arch\sim\src\sim\sim_checkhostfstypes.c(81,1): error C2338: static_assert failed: 'sizeof(((struct nuttx_stat_s *)0)->st_mtim) == sizeof(((struct stat *)0)->st_mtim)' nuttx\arch\sim\src\sim\sim_checkhostfstypes.c(82,1): error C2338: static_assert failed: 'offsetof(struct nuttx_stat_s, st_ctim) == offsetof(struct stat, st_ctim)' Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- boards/sim/sim/sim/configs/windows/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/sim/sim/sim/configs/windows/defconfig b/boards/sim/sim/sim/configs/windows/defconfig index be8e8b4a0dd00..dccfaa4d5103a 100644 --- a/boards/sim/sim/sim/configs/windows/defconfig +++ b/boards/sim/sim/sim/configs/windows/defconfig @@ -66,4 +66,5 @@ CONFIG_SIM_HOSTFS=y CONFIG_SIM_STACKSIZE_ADJUSTMENT=10240 CONFIG_SYSTEM_NSH=y CONFIG_SYSTEM_PING=y +CONFIG_SYSTEM_TIME64=y CONFIG_TESTING_OSTEST=y From b65efdba12734fcff3bc19dcabb46ee2ad686831 Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Thu, 13 Jun 2024 11:59:18 +0800 Subject: [PATCH 69/81] sim_hostmemory.c: fix windows build error nuttx\arch\sim\src\sim\win\sim_hostmemory.c(39,40): error C2146: syntax error: missing ')' before identifier 'exec' nuttx\arch\sim\src\sim\win\sim_hostmemory.c(39,35): error C2081: 'bool': name in formal parameter list illegal nuttx\arch\sim\src\sim\win\sim_hostmemory.c(39,40): error C2061: syntax error: identifier 'exec' nuttx\arch\sim\src\sim\win\sim_hostmemory.c(39,40): error C2059: syntax error: ';' nuttx\arch\sim\src\sim\win\sim_hostmemory.c(39,44): error C2059: syntax error: ')' nuttx\arch\sim\src\sim\win\sim_hostmemory.c(40,1): error C2449: found '{' at file scope (missing function header?) nuttx\arch\sim\src\sim\win\sim_hostmemory.c(42,1): error C2059: syntax error: '}' Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- arch/sim/src/sim/win/sim_hostmemory.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sim/src/sim/win/sim_hostmemory.c b/arch/sim/src/sim/win/sim_hostmemory.c index 3eaafa0006265..98844efdabdeb 100644 --- a/arch/sim/src/sim/win/sim_hostmemory.c +++ b/arch/sim/src/sim/win/sim_hostmemory.c @@ -24,6 +24,8 @@ #include +#include "sim_internal.h" + /**************************************************************************** * Public Functions ****************************************************************************/ From f512f5e8a948f9716266006a375afe7b153cc1de Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Thu, 13 Jun 2024 11:41:50 +0800 Subject: [PATCH 70/81] windows sim:add MSCV atomic support for fix windows build error VC\Tools\MSVC\14.40.33807\include\vcruntime_c11_stdatomic.h(36,24): error C2061: syntax error: identifier 'atomic_bool' VC\Tools\MSVC\14.40.33807\include\vcruntime_c11_stdatomic.h(36,24): error C2059: syntax error: ';' VC\Tools\MSVC\14.40.33807\include\vcruntime_c11_stdatomic.h(37,23): error C2061: syntax error: identifier 'atomic_char' VC\Tools\MSVC\14.40.33807\include\vcruntime_c11_stdatomic.h(37,23): error C2059: syntax error: ';' VC\Tools\MSVC\14.40.33807\include\vcruntime_c11_stdatomic.h(38,30): error C2061: syntax error: identifier 'atomic_schar' VC\Tools\MSVC\14.40.33807\include\vcruntime_c11_stdatomic.h(38,30): error C2059: syntax error: ';' Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- arch/sim/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/sim/CMakeLists.txt b/arch/sim/CMakeLists.txt index 8aa73382d75b1..ded850e13a593 100644 --- a/arch/sim/CMakeLists.txt +++ b/arch/sim/CMakeLists.txt @@ -50,6 +50,11 @@ if(NOT WIN32) TARGET nuttx APPEND PROPERTY NUTTX_COMPILE_OPTIONS -fno-common) +else() + set_property( + TARGET nuttx + APPEND + PROPERTY NUTTX_COMPILE_OPTIONS /std:c11 /experimental:c11atomics) endif() if(CONFIG_SIM_SANITIZE) From 46f3477d2fc4bf67f3f37c15b7f8fb52e24f869f Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Thu, 13 Jun 2024 11:32:43 +0800 Subject: [PATCH 71/81] compiler.h: fix windows build error warning C5101: use of preprocessor directive in function-like macro argument list is undefined behavior Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- include/nuttx/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nuttx/compiler.h b/include/nuttx/compiler.h index c5610df5972cd..e637f5c5332b9 100644 --- a/include/nuttx/compiler.h +++ b/include/nuttx/compiler.h @@ -887,7 +887,7 @@ /* Pre-processor */ -# define CONFIG_CPP_HAVE_VARARGS 1 /* Supports variable argument macros */ +# undef CONFIG_CPP_HAVE_VARARGS /* No variable argument macros */ /* Intriniscs */ From 7c56e917e752736ec4df3e10765327bdaa9bcc2c Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Thu, 13 Jun 2024 15:27:52 +0800 Subject: [PATCH 72/81] libc:add missing source to fix windows build error nuttx_all.lib(netlib_setipv4dnsaddr.obj) : error LNK2019: unresolved external symbol _bzero referenced in function _netlib_set_ipv4dnsaddr Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- libs/libc/string/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/libc/string/CMakeLists.txt b/libs/libc/string/CMakeLists.txt index aa25dc5ad6889..c893384de296d 100644 --- a/libs/libc/string/CMakeLists.txt +++ b/libs/libc/string/CMakeLists.txt @@ -57,6 +57,7 @@ set(SRCS lib_strsep.c lib_strerrorr.c lib_explicit_bzero.c + lib_bzero.c lib_strsignal.c lib_timingsafe_bcmp.c lib_index.c From 7ce5241f0efcebb2554873a3ca9e54f5a01ec9b7 Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Thu, 13 Jun 2024 11:49:24 +0800 Subject: [PATCH 73/81] types.h: fix windows build error Windows Kits\10\Include\10.0.22621.0\ucrt\corecrt.h(605,39): error C2371: 'wint_t': redefinition; different basic types Windows Kits\10\Include\10.0.22621.0\ucrt\corecrt.h(606,39): error C2371: 'wctype_t': redefinition; different basic types Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- arch/arm/include/types.h | 3 +++ arch/arm64/include/types.h | 3 +++ arch/avr/include/avr/types.h | 3 +++ arch/avr/include/avr32/types.h | 3 +++ arch/hc/include/hc12/types.h | 3 +++ arch/hc/include/hcs12/types.h | 3 +++ arch/mips/include/types.h | 3 +++ arch/misoc/include/types.h | 3 +++ arch/or1k/include/types.h | 3 +++ arch/renesas/include/m16c/types.h | 3 +++ arch/renesas/include/rx65n/types.h | 3 +++ arch/renesas/include/sh1/types.h | 3 +++ arch/risc-v/include/types.h | 3 +++ arch/sim/include/types.h | 12 ++++++++++++ arch/sparc/include/types.h | 3 +++ arch/tricore/include/types.h | 3 +++ arch/x86/include/i486/types.h | 3 +++ arch/x86_64/include/intel64/types.h | 3 +++ arch/xtensa/include/types.h | 3 +++ arch/z16/include/types.h | 3 +++ arch/z80/include/ez80/types.h | 3 +++ arch/z80/include/z180/types.h | 3 +++ arch/z80/include/z8/types.h | 3 +++ arch/z80/include/z80/types.h | 3 +++ include/sys/types.h | 4 ++-- 25 files changed, 83 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/types.h b/arch/arm/include/types.h index eaaac738ddfbd..043937a84b5de 100644 --- a/arch/arm/include/types.h +++ b/arch/arm/include/types.h @@ -81,6 +81,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/arm64/include/types.h b/arch/arm64/include/types.h index 5d783496736af..a0faaa28ca055 100644 --- a/arch/arm64/include/types.h +++ b/arch/arm64/include/types.h @@ -72,6 +72,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + #if defined(__SIZE_TYPE__) /* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. * We simply change "unsigned" to "signed" for this single definition diff --git a/arch/avr/include/avr/types.h b/arch/avr/include/avr/types.h index 6dedd3df05f8e..2d11975a77e1e 100644 --- a/arch/avr/include/avr/types.h +++ b/arch/avr/include/avr/types.h @@ -73,6 +73,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A (near) size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/avr/include/avr32/types.h b/arch/avr/include/avr32/types.h index ad3be5ba959bc..a763ccba301ef 100644 --- a/arch/avr/include/avr32/types.h +++ b/arch/avr/include/avr32/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/hc/include/hc12/types.h b/arch/hc/include/hc12/types.h index 2a85a1a755fa3..62b5c0beb7b00 100644 --- a/arch/hc/include/hc12/types.h +++ b/arch/hc/include/hc12/types.h @@ -79,6 +79,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is two bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/hc/include/hcs12/types.h b/arch/hc/include/hcs12/types.h index 28e52459b3f9c..9dbf3d93f0277 100644 --- a/arch/hc/include/hcs12/types.h +++ b/arch/hc/include/hcs12/types.h @@ -80,6 +80,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is two bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/mips/include/types.h b/arch/mips/include/types.h index de4870bbed93b..d08f07e0994df 100644 --- a/arch/mips/include/types.h +++ b/arch/mips/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/misoc/include/types.h b/arch/misoc/include/types.h index a6d27b03ac714..1a14ab6025fd1 100644 --- a/arch/misoc/include/types.h +++ b/arch/misoc/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/or1k/include/types.h b/arch/or1k/include/types.h index 30a76756ed308..3a4ad630e0e90 100644 --- a/arch/or1k/include/types.h +++ b/arch/or1k/include/types.h @@ -73,6 +73,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/renesas/include/m16c/types.h b/arch/renesas/include/m16c/types.h index 3b2f720015ba2..3f2947aab6477 100644 --- a/arch/renesas/include/m16c/types.h +++ b/arch/renesas/include/m16c/types.h @@ -72,6 +72,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/renesas/include/rx65n/types.h b/arch/renesas/include/rx65n/types.h index d71395d52d1c0..fb73d2400ff45 100644 --- a/arch/renesas/include/rx65n/types.h +++ b/arch/renesas/include/rx65n/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/renesas/include/sh1/types.h b/arch/renesas/include/sh1/types.h index 36c2f2bbcd299..497dc0360d289 100644 --- a/arch/renesas/include/sh1/types.h +++ b/arch/renesas/include/sh1/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/risc-v/include/types.h b/arch/risc-v/include/types.h index 29fe8d56a62c4..9183cf78fa4b4 100644 --- a/arch/risc-v/include/types.h +++ b/arch/risc-v/include/types.h @@ -78,6 +78,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* Use uintreg_t for register-width integers */ #ifdef CONFIG_ARCH_RV32 diff --git a/arch/sim/include/types.h b/arch/sim/include/types.h index d347751567940..5e6083b753a95 100644 --- a/arch/sim/include/types.h +++ b/arch/sim/include/types.h @@ -94,6 +94,18 @@ typedef unsigned short _wchar_t; typedef int _wchar_t; #endif +#ifdef _MSC_VER +typedef unsigned short _wint_t; +#else +typedef int _wint_t; +#endif + +#ifdef _MSC_VER +typedef unsigned short _wctype_t; +#else +typedef int _wctype_t; +#endif + #if defined(__SIZE_TYPE__) /* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. * We simply change "unsigned" to "signed" for this single definition diff --git a/arch/sparc/include/types.h b/arch/sparc/include/types.h index 51555a9474f73..2da78227b7b90 100644 --- a/arch/sparc/include/types.h +++ b/arch/sparc/include/types.h @@ -72,6 +72,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/tricore/include/types.h b/arch/tricore/include/types.h index 0daba0000627e..0158e7e104190 100644 --- a/arch/tricore/include/types.h +++ b/arch/tricore/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/x86/include/i486/types.h b/arch/x86/include/i486/types.h index 970cdda70d79f..d72d2834863ab 100644 --- a/arch/x86/include/i486/types.h +++ b/arch/x86/include/i486/types.h @@ -71,6 +71,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/x86_64/include/intel64/types.h b/arch/x86_64/include/intel64/types.h index 8880aa37e0de1..f87167174ca70 100644 --- a/arch/x86_64/include/intel64/types.h +++ b/arch/x86_64/include/intel64/types.h @@ -71,6 +71,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + #if defined(__SIZE_TYPE__) /* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. * We simply change "unsigned" to "signed" for this single definition diff --git a/arch/xtensa/include/types.h b/arch/xtensa/include/types.h index 200b46e043f05..2fc02b5b621eb 100644 --- a/arch/xtensa/include/types.h +++ b/arch/xtensa/include/types.h @@ -70,6 +70,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/z16/include/types.h b/arch/z16/include/types.h index 1b9a51c306df5..e2719f5705701 100644 --- a/arch/z16/include/types.h +++ b/arch/z16/include/types.h @@ -66,6 +66,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 4 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/z80/include/ez80/types.h b/arch/z80/include/ez80/types.h index 734e35351f335..d852729de3c0e 100644 --- a/arch/z80/include/ez80/types.h +++ b/arch/z80/include/ez80/types.h @@ -90,6 +90,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A pointer is 2 or 3 bytes, depending upon if the ez80 is in z80 * compatibility mode or not * diff --git a/arch/z80/include/z180/types.h b/arch/z80/include/z180/types.h index 9f58ba29d03d2..438c82e414d1f 100644 --- a/arch/z80/include/z180/types.h +++ b/arch/z80/include/z180/types.h @@ -78,6 +78,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/z80/include/z8/types.h b/arch/z80/include/z8/types.h index 72e3b7164d72c..8baf908c97dfc 100644 --- a/arch/z80/include/z8/types.h +++ b/arch/z80/include/z8/types.h @@ -82,6 +82,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/arch/z80/include/z80/types.h b/arch/z80/include/z80/types.h index f8efd7ae88334..bd64f657c0954 100644 --- a/arch/z80/include/z80/types.h +++ b/arch/z80/include/z80/types.h @@ -78,6 +78,9 @@ typedef __WCHAR_TYPE__ _wchar_t; typedef int _wchar_t; #endif +typedef int _wint_t; +typedef int _wctype_t; + /* A size is 2 bytes */ #if defined(__SIZE_TYPE__) diff --git a/include/sys/types.h b/include/sys/types.h index a87827b5f199b..a316397d89be6 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -192,14 +192,14 @@ typedef _wchar_t wchar_t; * An integral type capable of storing any valid value of wchar_t, or WEOF. */ -typedef int wint_t; +typedef _wint_t wint_t; /* wctype_t * A scalar type of a data object that can hold values which represent * locale-specific character classification. */ -typedef int wctype_t; +typedef _wctype_t wctype_t; #if defined(CONFIG_FS_LARGEFILE) /* Large file versions */ From 538582ede10a5c651010fc3d7eeb25724b58f2d1 Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Thu, 13 Jun 2024 15:35:16 +0800 Subject: [PATCH 74/81] convert pointer string to number in base 16 Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- drivers/net/rpmsgdrv.c | 4 ++-- drivers/sensors/goldfish_gps_uorb.c | 2 +- drivers/sensors/goldfish_sensor_uorb.c | 2 +- sched/wqueue/kwork_thread.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c index 3f55c31584b21..bbd5b9e53fa2c 100644 --- a/drivers/net/rpmsgdrv.c +++ b/drivers/net/rpmsgdrv.c @@ -330,8 +330,8 @@ static int net_rpmsg_drv_sockioctl_task(int argc, FAR char *argv[]) /* Restore pointers from argv */ - ept = (FAR struct rpmsg_endpoint *)strtoul(argv[1], NULL, 0); - msg = (FAR struct net_rpmsg_ioctl_s *)strtoul(argv[2], NULL, 0); + ept = (FAR struct rpmsg_endpoint *)strtoul(argv[1], NULL, 16); + msg = (FAR struct net_rpmsg_ioctl_s *)strtoul(argv[2], NULL, 16); /* We need a temporary sock for ioctl here */ diff --git a/drivers/sensors/goldfish_gps_uorb.c b/drivers/sensors/goldfish_gps_uorb.c index 766d7faea0eb2..a59cf0bf3d192 100644 --- a/drivers/sensors/goldfish_gps_uorb.c +++ b/drivers/sensors/goldfish_gps_uorb.c @@ -142,7 +142,7 @@ static int goldfish_gps_activate(FAR struct gps_lowerhalf_s *gps, static int goldfish_gps_thread(int argc, FAR char** argv) { FAR struct goldfish_gps_s *priv = (FAR struct goldfish_gps_s *) - ((uintptr_t)strtoul(argv[1], NULL, 0)); + ((uintptr_t)strtoul(argv[1], NULL, 16)); ssize_t len; char buf[256]; diff --git a/drivers/sensors/goldfish_sensor_uorb.c b/drivers/sensors/goldfish_sensor_uorb.c index 94b7550d994d9..a61f98cfe2102 100644 --- a/drivers/sensors/goldfish_sensor_uorb.c +++ b/drivers/sensors/goldfish_sensor_uorb.c @@ -588,7 +588,7 @@ static int goldfish_sensor_activate(FAR struct sensor_lowerhalf_s *lower, static int goldfish_sensor_thread(int argc, FAR char** argv) { FAR struct goldfish_sensor_s *priv = - (FAR struct goldfish_sensor_s *)((uintptr_t)strtoul(argv[1], NULL, 0)); + (FAR struct goldfish_sensor_s *)((uintptr_t)strtoul(argv[1], NULL, 16)); while (true) { diff --git a/sched/wqueue/kwork_thread.c b/sched/wqueue/kwork_thread.c index a0a9ea540622b..ef3be25b2f74e 100644 --- a/sched/wqueue/kwork_thread.c +++ b/sched/wqueue/kwork_thread.c @@ -136,9 +136,9 @@ static int work_thread(int argc, FAR char *argv[]) /* Get the handle from argv */ wqueue = (FAR struct kwork_wqueue_s *) - ((uintptr_t)strtoul(argv[1], NULL, 0)); + ((uintptr_t)strtoul(argv[1], NULL, 16)); kworker = (FAR struct kworker_s *) - ((uintptr_t)strtoul(argv[2], NULL, 0)); + ((uintptr_t)strtoul(argv[2], NULL, 16)); flags = enter_critical_section(); From cedb7f97def2a7279298310b6da5a1e988823e3a Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Mon, 24 Jun 2024 18:19:23 +0800 Subject: [PATCH 75/81] compiler.h: fix windows netfilter build error nuttx\net\netfilter\ipt_sockopt.c(389,7): error C2059: syntax error: ')' nuttx\net\netfilter\ip6t_sockopt.c(387,7): error C2059: syntax error: ')' Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- include/nuttx/compiler.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/nuttx/compiler.h b/include/nuttx/compiler.h index e637f5c5332b9..eb928d4c74cf8 100644 --- a/include/nuttx/compiler.h +++ b/include/nuttx/compiler.h @@ -936,6 +936,8 @@ # define syslog_like(a, b) # define scanf_like(a, b) # define strftime_like(a) +# define object_size(o, t) ((size_t)-1) +# define typeof __typeof__ # define FAR # define NEAR From 363cd1c17ac45391226f2e5beba2b938ff0fb6c8 Mon Sep 17 00:00:00 2001 From: chenxiaoyi Date: Mon, 24 Jun 2024 18:17:10 +0800 Subject: [PATCH 76/81] windows sim:convert pointer type to char* fix windows net build error nuttx\include\nuttx\net\netfilter\ip6_tables.h(299,24): error C2036: 'void *': unknown size Co-authored-by: chenxiaoyi Co-authored-by: xuxin19 --- include/nuttx/net/netfilter/ip6_tables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nuttx/net/netfilter/ip6_tables.h b/include/nuttx/net/netfilter/ip6_tables.h index 018132a09c026..8f24797ec74e6 100644 --- a/include/nuttx/net/netfilter/ip6_tables.h +++ b/include/nuttx/net/netfilter/ip6_tables.h @@ -296,7 +296,7 @@ struct ip6t_icmp static inline FAR struct xt_entry_target * ip6t_get_target(FAR struct ip6t_entry *e) { - return (FAR void *)e + e->target_offset; + return (FAR char *)e + e->target_offset; } #endif /* __INCLUDE_NUTTX_NET_NETFILTER_IP6_TABLES_H */ From b3f1871bc3d478e0339fa326dff6bfae67dc0525 Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Wed, 14 Aug 2024 11:52:59 +0800 Subject: [PATCH 77/81] sched:fix windows sim build error nuttx\sched\signal\sig_timedwait.c(253,13): error C2059: syntax error:'' nuttx\sched\signal\sig_timedwait.c(321,44): error C2182: '$S1': illegal use of type 'void' nuttx\sched\signal\sig_timedwait.c(321,50): error C2059: syntax error:':' nuttx\sched\tls\tls_initinfo.c(68,39): error C2036: 'void *': unknown size nuttx\sched\sched\sched_get_tls.c(76,44): error C2036: 'void *': unkown size Signed-off-by: xuxin19 --- sched/sched/sched_get_tls.c | 3 ++- sched/signal/sig_timedwait.c | 4 ++-- sched/tls/tls_initinfo.c | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sched/sched/sched_get_tls.c b/sched/sched/sched_get_tls.c index 63517429ed3a7..02b64e61e8bb0 100644 --- a/sched/sched/sched_get_tls.c +++ b/sched/sched/sched_get_tls.c @@ -73,5 +73,6 @@ FAR char **nxsched_get_stackargs(FAR struct tcb_s *tcb) { /* The args data follows the TLS data */ - return (FAR char**)(tcb->stack_alloc_ptr + nxsched_get_tls(tcb)->tl_size); + return (FAR char**)((FAR char *)tcb->stack_alloc_ptr + + nxsched_get_tls(tcb)->tl_size); } diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index 1b7985deebd29..a831dd17a47c8 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -250,7 +250,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, irqstate_t flags; sclock_t waitticks; bool switch_needed; - siginfo_t sinfo; + siginfo_t unbinfo; int ret; DEBUGASSERT(set != NULL); @@ -318,7 +318,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, } #endif - rtcb->sigunbinfo = (info == NULL) ? &sinfo : info; + rtcb->sigunbinfo = (info == NULL) ? &unbinfo : info; /* Check if we should wait for the timeout */ diff --git a/sched/tls/tls_initinfo.c b/sched/tls/tls_initinfo.c index 67792004e44a0..306f00bbc35f2 100644 --- a/sched/tls/tls_initinfo.c +++ b/sched/tls/tls_initinfo.c @@ -65,7 +65,8 @@ int tls_init_info(FAR struct tcb_s *tcb) /* Derive tl_size w/o arch knowledge */ - info->tl_size = tcb->stack_base_ptr - tcb->stack_alloc_ptr; + info->tl_size = + (FAR char *)tcb->stack_base_ptr - (FAR char *)tcb->stack_alloc_ptr; /* Attach per-task info in group to TLS */ From 3ae30d00ea41738d025221552f5d569ba2f77611 Mon Sep 17 00:00:00 2001 From: Tiago Medicci Date: Wed, 14 Aug 2024 13:18:04 -0300 Subject: [PATCH 78/81] docs: Improve information about debugging for Espressif SoCs Provide more information on how to properly use OpenOCD and gdb to debug Espressif SoCs on NuttX. --- .../platforms/risc-v/esp32c3-legacy/index.rst | 64 +++++++++++++++---- .../platforms/risc-v/esp32c3/index.rst | 60 ++++++++++++++--- .../platforms/risc-v/esp32c6/index.rst | 49 +++++++++++--- .../platforms/risc-v/esp32h2/index.rst | 51 ++++++++++++--- .../platforms/xtensa/esp32/index.rst | 29 ++++++++- .../platforms/xtensa/esp32s2/index.rst | 29 ++++++++- .../platforms/xtensa/esp32s3/index.rst | 28 +++++++- 7 files changed, 263 insertions(+), 47 deletions(-) diff --git a/Documentation/platforms/risc-v/esp32c3-legacy/index.rst b/Documentation/platforms/risc-v/esp32c3-legacy/index.rst index 074d86919feb0..756c0925fd621 100644 --- a/Documentation/platforms/risc-v/esp32c3-legacy/index.rst +++ b/Documentation/platforms/risc-v/esp32c3-legacy/index.rst @@ -110,35 +110,75 @@ Note that this step is required only one time. Once the bootloader and partitio table are flashed, we don't need to flash them again. So subsequent builds would just require: ``make flash ESPTOOL_PORT=/dev/ttyUSBXX`` -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== -Download and build OpenOCD from Espressif, that can be found in -https://github.com/espressif/openocd-esp32 +Espressif uses a specific version of OpenOCD to support ESP32-C3: `openocd-esp32 `_. -If you have an ESP32-C3 ECO3, no external JTAG is required to debug, the ESP32-C3 -integrates a USB-to-JTAG adapter. +Please check `Building OpenOCD from Sources `_ +for more information on how to build OpenOCD for ESP32-C3. + +ESP32-C3 has a built-in JTAG circuitry and can be debugged without any additional chip. +Only an USB cable connected to the D+/D- pins is necessary: + +============ ========== +ESP32-C3 Pin USB Signal +============ ========== +GPIO18 D- +GPIO19 D+ +5V V_BUS +GND Ground +============ ========== + +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. OpenOCD can then be used:: openocd -c 'set ESP_RTOS none' -f board/esp32c3-builtin.cfg -For versions prior to ESP32-C3 ECO3, an external JTAG adapter is needed. -It can be connected as follows:: +If you want to debug with an external JTAG adapter it can +be connected as follows: - TMS -> GPIO4 - TDI -> GPIO5 - TCK -> GPIO6 - TDO -> GPIO7 +============ =========== +ESP32-C6 Pin JTAG Signal +============ =========== +GPIO4 TMS +GPIO5 TDI +GPIO6 TCK +GPIO7 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS none' -f board/esp32c3-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/risc-v/esp32c3/index.rst b/Documentation/platforms/risc-v/esp32c3/index.rst index c08d990757f9d..e8c68758b8f78 100644 --- a/Documentation/platforms/risc-v/esp32c3/index.rst +++ b/Documentation/platforms/risc-v/esp32c3/index.rst @@ -120,35 +120,75 @@ Where ```` is typically ``/dev/ttyUSB0`` or similar and ``./`` is the path to the folder containing the externally-built 2nd stage bootloader for the ESP32-C3 as explained above. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32-C3: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32-C3. -If you have an ESP32-C3 ECO3, no external JTAG is required to debug, the ESP32-C3 -integrates a USB-to-JTAG adapter. +ESP32-C3 has a built-in JTAG circuitry and can be debugged without any additional chip. +Only an USB cable connected to the D+/D- pins is necessary: + +============ ========== +ESP32-C3 Pin USB Signal +============ ========== +GPIO18 D- +GPIO19 D+ +5V V_BUS +GND Ground +============ ========== + +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32c3-builtin.cfg -For versions prior to ESP32-C3 ECO3, an external JTAG adapter is needed. -It can be connected as follows:: +If you want to debug with an external JTAG adapter it can +be connected as follows: - TMS -> GPIO4 - TDI -> GPIO5 - TCK -> GPIO6 - TDO -> GPIO7 +============ =========== +ESP32-C6 Pin JTAG Signal +============ =========== +GPIO4 TMS +GPIO5 TDI +GPIO6 TCK +GPIO7 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32c3-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/risc-v/esp32c6/index.rst b/Documentation/platforms/risc-v/esp32c6/index.rst index 72891f568dd90..6a51d3cf8e43e 100644 --- a/Documentation/platforms/risc-v/esp32c6/index.rst +++ b/Documentation/platforms/risc-v/esp32c6/index.rst @@ -119,35 +119,66 @@ Where ```` is typically ``/dev/ttyUSB0`` or similar and ``./`` is the path to the folder containing the externally-built 2nd stage bootloader for the ESP32-C6 as explained above. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== -Download and build OpenOCD from Espressif, that can be found in -https://github.com/espressif/openocd-esp32 +Espressif uses a specific version of OpenOCD to support ESP32-C6: `openocd-esp32 `_. + +Please check `Building OpenOCD from Sources `_ +for more information on how to build OpenOCD for ESP32-C6. You do not need an external JTAG to debug, the ESP32-C6 integrates a USB-to-JTAG adapter. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32c6-builtin.cfg If you want to debug with an external JTAG adapter it can -be connected as follows:: +be connected as follows: - TMS -> GPIO4 - TDI -> GPIO5 - TCK -> GPIO6 - TDO -> GPIO7 +============ =========== +ESP32-C6 Pin JTAG Signal +============ =========== +GPIO4 TMS +GPIO5 TDI +GPIO6 TCK +GPIO7 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwtread; set ESP_FLASH_SIZE 0' -f board/esp32c6-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/risc-v/esp32h2/index.rst b/Documentation/platforms/risc-v/esp32h2/index.rst index a06b036bbb8de..38bff47fb1795 100644 --- a/Documentation/platforms/risc-v/esp32h2/index.rst +++ b/Documentation/platforms/risc-v/esp32h2/index.rst @@ -119,35 +119,66 @@ Where ```` is typically ``/dev/ttyUSB0`` or similar and ``./`` is the path to the folder containing the externally-built 2nd stage bootloader for the ESP32-H2 as explained above. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== -Download and build OpenOCD from Espressif, that can be found in -https://github.com/espressif/openocd-esp32 +Espressif uses a specific version of OpenOCD to support ESP32-H2: `openocd-esp32 `_. -You don not need an external JTAG is to debug, the ESP32-H2 integrates a +Please check `Building OpenOCD from Sources `_ +for more information on how to build OpenOCD for ESP32-H2. + +You do not need an external JTAG to debug, the ESP32-H2 integrates a USB-to-JTAG adapter. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32h2-builtin.cfg If you want to debug with an external JTAG adapter it can -be connected as follows:: +be connected as follows: - TMS -> GPIO2 - TDI -> GPIO5 - TCK -> GPIO5 - TDO -> GPIO3 +============ =========== +ESP32-H2 Pin JTAG Signal +============ =========== +GPIO2 TMS +GPIO5 TDI +GPIO4 TCK +GPIO3 TDO +============ =========== Furthermore, an efuse needs to be burnt to be able to debug:: espefuse.py -p burn_efuse DIS_USB_JTAG +.. warning:: Burning eFuses is an irreversible operation, so please + consider the above option before starting the process. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32h2-ftdi.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + riscv-none-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/xtensa/esp32/index.rst b/Documentation/platforms/xtensa/esp32/index.rst index d8559a71b1388..115159d646483 100644 --- a/Documentation/platforms/xtensa/esp32/index.rst +++ b/Documentation/platforms/xtensa/esp32/index.rst @@ -142,8 +142,10 @@ externally-built 2nd stage bootloader and the partition table (if applicable): w ``make bootloader``, these files are placed into ``nuttx`` folder. ``ESPTOOL_BAUD`` is able to change the flash baud rate if desired. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32. @@ -165,10 +167,33 @@ Some boards, like :ref:`ESP32-Ethernet-Kit V1.2 `. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for configuring the JTAG adapter of the :ref:`ESP32-Ethernet-Kit V1.2 ` and + :ref:`ESP-WROVER-KIT ` boards and other FT2232-based JTAG adapters. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32-wrover-kit-1.8v.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + xtensa-esp32-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/xtensa/esp32s2/index.rst b/Documentation/platforms/xtensa/esp32s2/index.rst index 47037b72e66bd..93aa992b4a43f 100644 --- a/Documentation/platforms/xtensa/esp32s2/index.rst +++ b/Documentation/platforms/xtensa/esp32s2/index.rst @@ -135,8 +135,10 @@ externally-built 2nd stage bootloader and the partition table (if applicable): w ``make bootloader``, these files are placed into ``nuttx`` folder. ``ESPTOOL_BAUD`` is able to change the flash baud rate if desired. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32-S2: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32-S2. @@ -157,10 +159,33 @@ Some boards, like :ref:`ESP32-S2-Kaluga-1 Kit v1.3 `_ + for configuring the JTAG adapter of the :ref:`ESP32-S2-Kaluga-1 ` board + and other FT2232-based JTAG adapters. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32s2-kaluga-1.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + xtensa-esp32s2-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== diff --git a/Documentation/platforms/xtensa/esp32s3/index.rst b/Documentation/platforms/xtensa/esp32s3/index.rst index a16c2659ac255..23d64b3a517fe 100644 --- a/Documentation/platforms/xtensa/esp32s3/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/index.rst @@ -142,8 +142,10 @@ externally-built 2nd stage bootloader and the partition table (if applicable): w ``make bootloader``, these files are placed into ``nuttx`` folder. ``ESPTOOL_BAUD`` is able to change the flash baud rate if desired. -Debugging with OpenOCD -====================== +Debugging with ``openocd`` and ``gdb`` +====================================== + +Espressif uses a specific version of OpenOCD to support ESP32-S3: `openocd-esp32 `_. Please check `Building OpenOCD from Sources `_ for more information on how to build OpenOCD for ESP32-S3. @@ -154,10 +156,32 @@ extra wiring/cable to connect JTAG to ESP32-S3. Most of the ESP32-S3 boards have USB connector that can be used for JTAG debugging. This is the case for the :ref:`ESP32-S3-DevKit ` board. +.. note:: One must configure the USB drivers to enable JTAG communication. Please check + `Configure USB Drivers `_ + for more information. + OpenOCD can then be used:: openocd -c 'set ESP_RTOS hwthread; set ESP_FLASH_SIZE 0' -f board/esp32s3-builtin.cfg +Once OpenOCD is running, you can use GDB to connect to it and debug your application:: + + xtensa-esp32s3-elf-gdb -x gdbinit nuttx + +whereas the content of the ``gdbinit`` file is:: + + target remote :3333 + set remote hardware-watchpoint-limit 2 + mon reset halt + flushregs + monitor reset halt + thb nsh_main + c + +.. note:: ``nuttx`` is the ELF file generated by the build process. Please note that ``CONFIG_DEBUG_SYMBOLS`` must be enabled in the ``menuconfig``. + +Please refer to :doc:`/quickstart/debugging` for more information about debugging techniques. + Peripheral Support ================== From 08cdff2046a97c81a06ddd2addaf58e10659f52f Mon Sep 17 00:00:00 2001 From: pengyiqiang Date: Wed, 14 Aug 2024 17:34:40 +0800 Subject: [PATCH 79/81] arch/sim/Kconfig: set SIM_FBBPP to 32 by default 32bpp is the most commonly used option and should be used as the default Signed-off-by: pengyiqiang --- arch/sim/Kconfig | 4 ++-- boards/sim/sim/sim/configs/lvgl_fb/defconfig | 1 - boards/sim/sim/sim/configs/lvgl_lcd/defconfig | 1 - boards/sim/sim/sim/configs/nsh2/defconfig | 1 - boards/sim/sim/sim/configs/nx11/defconfig | 1 - boards/sim/sim/sim/configs/nxcamera/defconfig | 1 - boards/sim/sim/sim/configs/nxlines/defconfig | 1 - boards/sim/sim/sim/configs/nxwm/defconfig | 1 - boards/sim/sim/sim/configs/touchscreen/defconfig | 1 - 9 files changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 115104cb89725..5f89953d28716 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -408,11 +408,11 @@ config SIM_FBWIDTH config SIM_FBBPP int "Pixel depth in bits" - default 8 + default 32 ---help--- Pixel depth in bits. Valid choices are 4, 8, 16, 24, or 32. If you use the X11 display emulation, the selected BPP must match the BPP - of your graphics hardware (probably 32 bits). Default: 8 + of your graphics hardware (probably 32 bits). Default: 32 config SIM_FRAMEBUFFER_COUNT int "Framebuffer count" diff --git a/boards/sim/sim/sim/configs/lvgl_fb/defconfig b/boards/sim/sim/sim/configs/lvgl_fb/defconfig index 89c589c3c98ad..7b5c75721149e 100644 --- a/boards/sim/sim/sim/configs/lvgl_fb/defconfig +++ b/boards/sim/sim/sim/configs/lvgl_fb/defconfig @@ -46,7 +46,6 @@ CONFIG_NXFONTS_DISABLE_2BPP=y CONFIG_NXFONTS_DISABLE_32BPP=y CONFIG_NXFONTS_DISABLE_4BPP=y CONFIG_NXFONTS_DISABLE_8BPP=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=480 CONFIG_SIM_FBWIDTH=640 CONFIG_SIM_TOUCHSCREEN=y diff --git a/boards/sim/sim/sim/configs/lvgl_lcd/defconfig b/boards/sim/sim/sim/configs/lvgl_lcd/defconfig index f4473002c5540..db78a72ec12b1 100644 --- a/boards/sim/sim/sim/configs/lvgl_lcd/defconfig +++ b/boards/sim/sim/sim/configs/lvgl_lcd/defconfig @@ -49,7 +49,6 @@ CONFIG_NXFONTS_DISABLE_2BPP=y CONFIG_NXFONTS_DISABLE_32BPP=y CONFIG_NXFONTS_DISABLE_4BPP=y CONFIG_NXFONTS_DISABLE_8BPP=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=480 CONFIG_SIM_FBWIDTH=640 CONFIG_SIM_TOUCHSCREEN=y diff --git a/boards/sim/sim/sim/configs/nsh2/defconfig b/boards/sim/sim/sim/configs/nsh2/defconfig index e4bfdc0b851a2..8f6eff808585c 100644 --- a/boards/sim/sim/sim/configs/nsh2/defconfig +++ b/boards/sim/sim/sim/configs/nsh2/defconfig @@ -47,7 +47,6 @@ CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y CONFIG_SCHED_WAITPID=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_TOUCHSCREEN=y CONFIG_SIM_X11FB=y CONFIG_START_DAY=6 diff --git a/boards/sim/sim/sim/configs/nx11/defconfig b/boards/sim/sim/sim/configs/nx11/defconfig index 79ff26cb8eaa7..5f196b9d12b31 100644 --- a/boards/sim/sim/sim/configs/nx11/defconfig +++ b/boards/sim/sim/sim/configs/nx11/defconfig @@ -25,7 +25,6 @@ CONFIG_NXFONT_SANS23X27=y CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_X11FB=y CONFIG_START_DAY=28 CONFIG_START_MONTH=11 diff --git a/boards/sim/sim/sim/configs/nxcamera/defconfig b/boards/sim/sim/sim/configs/nxcamera/defconfig index faa3692029d8c..1b27f6e808fc1 100644 --- a/boards/sim/sim/sim/configs/nxcamera/defconfig +++ b/boards/sim/sim/sim/configs/nxcamera/defconfig @@ -57,7 +57,6 @@ CONFIG_PSEUDOFS_SOFTLINKS=y CONFIG_READLINE_TABCOMPLETION=y CONFIG_SCHED_BACKTRACE=y CONFIG_SCHED_HAVE_PARENT=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=480 CONFIG_SIM_FBWIDTH=640 CONFIG_SIM_X11FB=y diff --git a/boards/sim/sim/sim/configs/nxlines/defconfig b/boards/sim/sim/sim/configs/nxlines/defconfig index 234735d942078..f614d4acadf06 100644 --- a/boards/sim/sim/sim/configs/nxlines/defconfig +++ b/boards/sim/sim/sim/configs/nxlines/defconfig @@ -50,7 +50,6 @@ CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y CONFIG_SCHED_WAITPID=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_X11FB=y CONFIG_START_MONTH=5 CONFIG_START_YEAR=2012 diff --git a/boards/sim/sim/sim/configs/nxwm/defconfig b/boards/sim/sim/sim/configs/nxwm/defconfig index 6dd1c95594edc..af3c3f8fa38a6 100644 --- a/boards/sim/sim/sim/configs/nxwm/defconfig +++ b/boards/sim/sim/sim/configs/nxwm/defconfig @@ -46,7 +46,6 @@ CONFIG_NXWM_TASKBAR_LEFT=y CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_SCHED_WAITPID=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_X11FB=y CONFIG_START_MONTH=5 CONFIG_START_YEAR=2012 diff --git a/boards/sim/sim/sim/configs/touchscreen/defconfig b/boards/sim/sim/sim/configs/touchscreen/defconfig index 6a630a23391f2..170064350a592 100644 --- a/boards/sim/sim/sim/configs/touchscreen/defconfig +++ b/boards/sim/sim/sim/configs/touchscreen/defconfig @@ -29,7 +29,6 @@ CONFIG_NXFONT_SANS23X27=y CONFIG_NX_BLOCKING=y CONFIG_NX_KBD=y CONFIG_NX_XYINPUT_MOUSE=y -CONFIG_SIM_FBBPP=32 CONFIG_SIM_FBHEIGHT=320 CONFIG_SIM_FBWIDTH=240 CONFIG_SIM_TOUCHSCREEN=y From f05c85e6228a7c6f2471da33e09fa1e8e0dc07e9 Mon Sep 17 00:00:00 2001 From: Alexis Guijarro Date: Thu, 25 Jul 2024 02:18:18 +0000 Subject: [PATCH 80/81] arm/stm32h7x3x_rcc.c: Add External Power Supply option to stm32h7x3x targets --- arch/arm/src/stm32h7/Kconfig | 6 ++++++ arch/arm/src/stm32h7/stm32h7x3xx_rcc.c | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig index 91c66280aa2cd..15ba5312c547e 100644 --- a/arch/arm/src/stm32h7/Kconfig +++ b/arch/arm/src/stm32h7/Kconfig @@ -293,6 +293,12 @@ config STM32H7_PWR_DIRECT_SMPS_SUPPLY depends on STM32H7_HAVE_SMPS default n +config STM32H7_PWR_EXTERNAL_SOURCE_SUPPLY + bool "Use external source as power supply" + default n + ---help--- + Select this option for using an external power supply connected directly to the VCAP pin. + choice prompt "STM32 H7 Power Supply Selection" default STM32H7_PWR_DEFAULT_SUPPLY diff --git a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c index da7af1f59c796..51031027aee17 100644 --- a/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c +++ b/arch/arm/src/stm32h7/stm32h7x3xx_rcc.c @@ -148,12 +148,18 @@ # if defined(CONFIG_STM32H7_PWR_DIRECT_SMPS_SUPPLY) # define STM32_PWR_CR3_SELECTION STM32_PWR_CR3_SDEN +# elif defined(CONFIG_STM32H7_PWR_EXTERNAL_SOURCE_SUPPLY) +# define STM32_PWR_CR3_SELECTION STM32_PWR_CR3_BYPASS # else # define STM32_PWR_CR3_SELECTION STM32_PWR_CR3_LDOEN # endif #else # define STM32_PWR_CR3_MASK 0xffffffff -# define STM32_PWR_CR3_SELECTION (STM32_PWR_CR3_LDOEN | STM32_PWR_CR3_SCUEN) +# if defined(CONFIG_STM32H7_PWR_EXTERNAL_SOURCE_SUPPLY) +# define STM32_PWR_CR3_SELECTION (STM32_PWR_CR3_BYPASS | STM32_PWR_CR3_SCUEN) +# else +# define STM32_PWR_CR3_SELECTION (STM32_PWR_CR3_LDOEN | STM32_PWR_CR3_SCUEN) +# endif #endif From a409c42d1377ad004a0986453bee42b13bfff2f1 Mon Sep 17 00:00:00 2001 From: "Alan C. Assis" Date: Wed, 14 Aug 2024 12:16:31 -0700 Subject: [PATCH 81/81] Doc: Fix broken SPI Tool documentation --- .../applications/system/spi/index.rst | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Documentation/applications/system/spi/index.rst b/Documentation/applications/system/spi/index.rst index 9c1ae3ed86b0b..71e0593de9a2e 100644 --- a/Documentation/applications/system/spi/index.rst +++ b/Documentation/applications/system/spi/index.rst @@ -2,7 +2,7 @@ ``spi`` SPI Tool ================ -The I2C tool provides a way to debug SPI related problems. This README file will +The SPI Tool provides a way to debug SPI related problems. This README file will provide usage information for the SPI tools. Contents @@ -29,10 +29,10 @@ Contents * ``set`` * ``verf`` -- I2C Build Configuration +- SPI Build Configuration * NuttX Configuration Requirements - * I2C Tool Configuration Options + * SPI Tool Configuration Options System Requirements ------------------- @@ -71,7 +71,7 @@ or:: nsh> spi ? -Here is an example of the help output. I shows the general form of the command +Here is an example of the help output. It shows the general form of the command line, the various SPI commands supported with their unique command line options, and a more detailed summary of the command SPI command options:: @@ -95,8 +95,8 @@ and a more detailed summary of the command SPI command options:: **Notes**: - An environment variable like $PATH may be used for any argument. -- Arguments are _sticky_. For example, once the SPI address is specified, that - address will be re-used until it is changed. +- Arguments are _sticky_. For example, once the SPI bus is specified, that + bus will be re-used until it is changed. **Warning**: @@ -117,7 +117,7 @@ SPI operation. Those arguments vary from command to command as described below. However, there is also a core set of common ``OPTIONS`` supported by all commands. So perhaps a better representation of the general SPI command would be:: - i2c [OPTIONS] [arguments] + spi [OPTIONS] [arguments] Where ``[OPTIONS]`` represents the common options and and arguments represent the operation-specific arguments. @@ -146,7 +146,7 @@ Environment Variables variables. Environment variables must be preceded with the special character ``$``. For example, ``PWD`` is the variable that holds the current working directory and so ``$PWD`` could be used as a command line argument. The use of environment -variables on the I2C tools command is really only useful if you wish to write +variables on the SPI tools command is really only useful if you wish to write NSH scripts to execute a longer, more complex series of SPI commands. Common Option Summary @@ -187,7 +187,7 @@ Common Option Summary Various SPI devices support different data widths. This option is untested. -- ``[-f freq]`` I2C frequency. Default: ``4000000`` Current: ``4000000`` +- ``[-f freq]`` SPI frequency. Default: ``4000000`` Current: ``4000000`` The ``[-f freq]`` sets the frequency of the SPI device. The default is very conservative. @@ -212,7 +212,9 @@ Exchange data: ``exch [OPTIONS] `` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This command triggers an SPI transfer, returning the data back from the far end. -As an example (with MOSI looped back to MISO):: + +As an example you can exchange (send and receive) 4 bytes (-x 4) on SPI2 (-b 2) using the command below with the ``loopback`` approach. +This approach requires that you connect the MOSI pin directly to the MISO pin (NOTE: SCLK and CS are not directly involved, but you still can see the clock and chip select waveforms if you decide to use an oscilloscope or more properly a logic analyzer to analyze these pins):: nsh> spi exch -b 2 -x 4 aabbccdd @@ -221,7 +223,7 @@ As an example (with MOSI looped back to MISO):: Note that the ``TX Data`` are always specified in hex, and are always two digits each, case insensitive. -I2C Build Configuration +SPI Build Configuration ----------------------- NuttX Configuration Requirements @@ -241,7 +243,7 @@ The SPI tools requires the following in your NuttX configuration: CONFIG_SPI_DRIVER=y The SPI tool will then use the SPI character driver to access the SPI bus. - These devices will reside at ``/dev/spiN`` where ``N`` is the I2C bus number. + These devices will reside at ``/dev/spiN`` where ``N`` is the SPI bus number. **Note**: The SPI driver ``ioctl`` interface is defined in ``include/nuttx/spi/spi.h``.